Conversation
- Add TrackerConfig, ToastConfig, BudgetConfig interfaces to lib/shared.ts - Add validateConfig(raw) that normalizes arbitrary input to valid config - Invalid fields silently corrected to defaults with warnings collected - Validates types, non-negative numbers, ranges, Infinity/NaN rejection - Refactor index.ts and bin/opencode-tokens.ts to use shared types/validation - Remove duplicated Config interfaces and DEFAULT_CONFIG from consumers - Plugin shows validation warnings via Toast; CLI prints to stderr - Add 12 new unit tests for validateConfig (31 total, all passing)
feat: config validation
There was a problem hiding this comment.
Pull request overview
Introduces shared config normalization/validation so both the plugin and CLI can safely consume arbitrary JSON config, emitting user-facing warnings instead of failing at runtime.
Changes:
- Added shared config types,
DEFAULT_CONFIG, andvalidateConfig(raw)normalization inlib/shared.ts. - Refactored
index.ts(plugin) andbin/opencode-tokens.ts(CLI) to use the shared validator and surface warnings (toast / stderr). - Added 12 unit tests covering
validateConfigbehavior.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| lib/shared.ts | Adds shared config types/defaults and implements validateConfig + helpers. |
| index.ts | Switches plugin config loading to validateConfig and displays config warnings via toast. |
| bin/opencode-tokens.ts | Switches CLI config loading to validateConfig and prints config warnings to stderr. |
| test/shared.test.ts | Adds unit tests for config validation/normalization and warning behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (obj["warnAt"] !== undefined) { | ||
| if (isFiniteNumber(obj["warnAt"]) && obj["warnAt"] > 0 && obj["warnAt"] <= 1) { | ||
| result.warnAt = obj["warnAt"] | ||
| } else { | ||
| warnings.push("budget.warnAt should be a number between 0 and 1 (exclusive-inclusive), using default") | ||
| } |
There was a problem hiding this comment.
budget.warnAt validation currently requires warnAt > 0 && warnAt <= 1, but the PR description says the allowed range is 0–1. Either adjust the check to match the intended range (e.g., allow 0) or update the docs/CLI text accordingly. Also the warning message text "between 0 and 1 (exclusive-inclusive)" is confusing; consider rephrasing it to precisely match the implemented bounds.
|
|
||
| if (raw === null || raw === undefined || typeof raw !== "object" || Array.isArray(raw)) { | ||
| warnings.push("Config is not a valid object, using defaults") | ||
| return { config: DEFAULT_CONFIG, warnings } |
There was a problem hiding this comment.
validateConfig returns DEFAULT_CONFIG by reference for invalid/non-object input. Because DEFAULT_CONFIG contains nested mutable objects, any downstream mutation of the returned config would mutate the shared default for the rest of the process. Consider returning a fresh copy (e.g., clone defaults / call the same normalization path) instead of the constant object.
| return { config: DEFAULT_CONFIG, warnings } | |
| const config: TrackerConfig = JSON.parse(JSON.stringify(DEFAULT_CONFIG)) | |
| return { config, warnings } |
Summary
Merge dev into main: config validation feature (PR #38).
validateConfig(raw)函数,规范化任意配置输入TrackerConfig、ToastConfig、BudgetConfigindex.ts和bin/opencode-tokens.ts移除重复定义