Skip to content

fix(opencode): ignore unknown config fields - #41312

Merged
kitlangton merged 1 commit into
devfrom
forgiving-config
Aug 8, 2026
Merged

kitlangton merged 1 commit into
devfrom
forgiving-config

Conversation

@opencode-agent

@opencode-agent opencode-agent Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • let V1 ignore config fields it does not recognize instead of refusing to start
  • preserve schema validation for recognized fields and values
  • cover the V2 plugins field in the V1 parser regression test

This allows V1 and V2 to share an opencode.json while their config schemas differ. Unknown values are discarded rather than passed into V1.

Testing

  • bun test test/config/config.test.ts (96 passed)
  • bun x prettier --check src/config/parse.ts test/config/config.test.ts
  • bun typecheck attempted but did not complete within the 5-minute local timeout

Requested by: @kitlangton (Kit via Slack)

@kitlangton
kitlangton merged commit 38e10eb into dev Aug 8, 2026
11 checks passed
@kitlangton
kitlangton deleted the forgiving-config branch August 8, 2026 18:53
HQ123-BOOP pushed a commit to HQ123-BOOP/LibreCode that referenced this pull request Aug 9, 2026
Qiiks added a commit to Qiiks/opencode that referenced this pull request Aug 15, 2026
…hydration-fix

Sync 86 upstream commits (Aug 6-14) including:
- ID-wrap/chronological message ordering fixes (anomalyco#40987-anomalyco#41006) — upstream
  independently fixed the same bug class as our 07889a1/21964da41;
  adopted upstream versions (parentID === user.id for prompt exit, same
  findIndex boundaries for revert/session, isAfter helper in latest())
- v1.18.18 release (4 releases: v1.18.15-18)
- v1 database compatibility preservation (anomalyco#42444)
- ignore unknown config fields (anomalyco#41312)
- session retry cap with jitter (anomalyco#41939)
- compaction instructions for smaller models (anomalyco#42045)
- DeepSeek V4 Flash sampling defaults (anomalyco#41620)
- Copilot PDF input support detection (anomalyco#41522)
- web search for opencode-go (anomalyco#42630)
- compaction plugin hooks (experimental.session.compacting, messages.transform)
- New models: GLM 5.3, Gemini 3.7 Flash, Grok 4.6, Zen updates

Fork-only changes preserved:
- Synthetic web search backend (synthetic flag in webSearchEnabled)
- Config npm propagation to inherited models
- Tool-result media extraction for models without attachment capability
- packageManager pin to bun 1.4.-canary.1 (Rust runtime)

Conflicts resolved: message-v2, prompt, revert, session, server-session
(adopted upstream), compaction (adopted upstream), registry + websearch
test (merged both synthetic + opencode-go).
Spark-Liang pushed a commit to Spark-Liang/opencode that referenced this pull request Aug 18, 2026
vsixer added a commit to vsixer/opencode that referenced this pull request Aug 22, 2026
Conflict resolution via two-model concilium in packages/opencode/src/config/parse.ts:
keep fork strict top-level extra-keys check + lenient decode() split,
adopt upstream onExcessProperty ignore (anomalyco#41312), restore topLevelExtraKeys helper.
1056674754 added a commit to 1056674754/opencode that referenced this pull request Aug 31, 2026
Upstream v1.18.15 (d7b115f) -> v1.18.16 (a3647eb), 4 commits.

Functional changes:
- fix(opencode): ignore unknown config fields (anomalyco#41312) - config parse
  uses onExcessProperty: 'ignore' instead of hard-failing on unknown keys
- fix(stats): fall back after full sync failure (anomalyco#41411) - full stats
  sync failure falls back to incremental sync with warning log

Conflicts resolved: 29 package.json version bumps (rebranded 1.18.16-sscity)
and bun.lock. No functional code conflicts.
androidand pushed a commit to androidand/opencode-skein that referenced this pull request Sep 19, 2026
xiaoshidefeng added a commit to xiaoshidefeng/clawd-on-desk that referenced this pull request Sep 24, 2026
opencode <= 1.18.15 rejects unknown top-level config keys
(Unrecognized key: plugins), so the unconditional dual-key write from
rullerzhou-afk#1039 broke every older host on the next Clawd startup sync — the
silent drop verified on 1.18.32 only holds from 1.18.16
(anomalyco/opencode#41312).

Add hooks/opencode-host-detect.js (opencode --version tri-state:
v2/v1/unknown, login-shell PATH fallback for GUI launches, win32 via
where, CLAWD_OPENCODE_HOST escape hatch) and gate the managed register
on it: a v2 host registers the key as before, a v1 host never writes it
and sweeps proven-owned leftovers so a v2->v1 downgrade self-heals, an
unknown host never touches the key. unregister keeps sweeping both keys
unconditionally. Doctor no longer demands the v2 entry without a v2
host and reports a leftover entry on a 1.x host as a repairable
broken-path.

Note the probe side effect: running opencode --version makes the host
create its config dir, so tests pin the verdict explicitly.
rldona pushed a commit to rldona/FlupCode that referenced this pull request Sep 24, 2026
rullerzhou-afk added a commit to rullerzhou-afk/clawd-on-desk that referenced this pull request Sep 26, 2026
…1045)

* feat(opencode): support opencode v2 dual-key plugin registration

OpenCode 2.x (npm @opencode/cli) renamed the config key plugin -> plugins,
requires a { id, setup } plugin definition, replaced the event hook with
ctx.event.subscribe(), runs plugins in a shared background service, and
ships a native permission evaluate hook. The v1 function entry fails the
v2 loader schema, which is why Clawd stopped recognizing opencode after a
v2 upgrade (#1039).

- Add createOpencodeFamilyPluginV2 in the shared family core: zero-import
  { id, setup } definition, event-subscription translation for the v2
  vocabulary (session.step/tool/execution.*, session.renamed,
  session.usage.updated), per-event cwd from the envelope location, and a
  blocking evaluate hook whose decision is the /permission response body
  ({ decision: allow | always | deny }). 204/timeout/any error leaves the
  effect untouched so the native ask UI wins. No reverse bridge on v2.
- Materialize opencode-plugin-v2/index.mjs as a fifth bundle file and
  register it under the plugins key (new opencode-family-v2-registration
  module); the v1 plugin-key entry is untouched. Dual-key coexistence is
  verified in both directions: v2 tolerates the legacy plugin key, and
  v1 1.18.32 silently drops an unknown plugins key - no host-version
  detection anywhere. inspectGeneration accepts the historical four-file
  set as a legal owned-stale shape so old generations migrate.
- Server: new opencode-v2 sub-branch in the permission route holds the
  connection and answers the decision JSON; every Clawd-stays-out gate
  (DND, agent disabled, sub-gate, bubbles-off without remote) answers
  204 no-decision. resolvePermissionEntry and the dismiss sweep write the
  decision / release the await for v2 entries.
- Doctor: the managed inspector factors the v2 key into the verdict -
  a healthy v1 entry with a missing v2 entry is a repairable legacy-path,
  never ok.
- Known v2 degradations (documented): plugin runs in the shared service,
  so process-tree fields are omitted (terminal focus degrades) and
  Always-allow is a per-session in-plugin rule; opencode service restart
  is needed after install/repair.

Real-machine evidence (macOS, opencode 2.0.15 + GLM): docs/investigations/
opencode-v2-e1-evidence.md.

* docs(opencode): record macOS live bubble-decision verification for v2

Full Allow / Deny / family-Always / always-hit matrix verified against a
live source-run Clawd carrying the v2 branch (opencode 2.0.15 + GLM):
sequential and parallel asks, auto-tools automation interop, and the
fail-closed fallback against a Clawd without the v2 branch. Only the
Windows matrix and a packaged-asar spot check remain pending.

* docs(opencode): add opencode v2 real-machine evidence record

E1 probe evidence (loader schema, plugins-key tolerance both directions,
evaluate-hook blocking semantics, service process model, full event
vocabulary) plus the E2 live bubble-decision matrix against a Clawd
instance running the v2 branch. Referenced by PR #1045; docs/** is
gitignored for new files so this one is force-added like its siblings.

* fix(opencode): write the v2 plugins key only for a detected v2 host

opencode <= 1.18.15 rejects unknown top-level config keys
(Unrecognized key: plugins), so the unconditional dual-key write from
#1039 broke every older host on the next Clawd startup sync — the
silent drop verified on 1.18.32 only holds from 1.18.16
(anomalyco/opencode#41312).

Add hooks/opencode-host-detect.js (opencode --version tri-state:
v2/v1/unknown, login-shell PATH fallback for GUI launches, win32 via
where, CLAWD_OPENCODE_HOST escape hatch) and gate the managed register
on it: a v2 host registers the key as before, a v1 host never writes it
and sweeps proven-owned leftovers so a v2->v1 downgrade self-heals, an
unknown host never touches the key. unregister keeps sweeping both keys
unconditionally. Doctor no longer demands the v2 entry without a v2
host and reports a leftover entry on a 1.x host as a repairable
broken-path.

Note the probe side effect: running opencode --version makes the host
create its config dir, so tests pin the verdict explicitly.

* fix(opencode): scan v2 shell resources for the destructive-action reminder

The v2 plugin sends a single shell command as tool_input.resource
(buildV2PermissionBody), but the destructive-action reminder only scans
command-carrying fields — so under permission automation a v2
rm -rf was auto-approved and the bubble showed no hint.

Alias a lone shell resource to command for the detail/reminder view
(mapOpencodeV2ShellResource, gated on the same SHELL_TOOLS set the
reminder uses); the raw resource stays in place for display and the
stored tool_input keeps the original payload. Multi-resource requests
and non-shell tools are intentionally left unmapped.

* fix(opencode): finish v1 cleanup and native approval feedback

---------

Co-authored-by: Ruller_Lulu <228746293+rullerzhou-afk@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant