Commit Graph

810 Commits

Author SHA1 Message Date
YeonGyu-Kim f6a2ff3541 test(coupling-audit): allowlist dual-runtime spawn shims 2026-05-21 12:50:10 +09:00
YeonGyu-Kim e15461febc refactor(model-core): inject bundled capabilities snapshot from harness
- remove bundled snapshot dependency on src/generated in model-core

- make shared harness provide runtime bundled snapshot

- update guardrail and capability tests to pass explicit snapshot

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-21 12:50:10 +09:00
YeonGyu-Kim 2462d7af29 refactor(model-core): remove src back-imports via core utilities and adapter
- move fuzzyMatchModel and transformModelForProvider into model-core

- replace connected-providers re-export with adapter contract

- route shared wrappers through model-core exports

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-21 12:50:10 +09:00
YeonGyu-Kim 819bf0d11f chore: update meta-audits + add opencode coupling grep gate 2026-05-21 12:50:10 +09:00
YeonGyu-Kim 2748009ff2 refactor(packages): extract model-core package 2026-05-21 12:49:50 +09:00
YeonGyu-Kim a5c1d71001 refactor(packages): extract utils package 2026-05-21 12:48:43 +09:00
YeonGyu-Kim db4c9f49e3 Merge pull request #3316 from ahuangsnail/fix/max-output-tokens-zero-fallback
fix: treat zero limit.output as unknown to enable fallback to bundled…
2026-05-21 00:59:05 +09:00
YeonGyu-Kim d0719ff7b7 Merge pull request #3875 from jollyxenon/fix/3846-opencode-config-dir-additive
fix(config): align OPENCODE_CONFIG_DIR with additive OpenCode semantics
2026-05-21 00:48:00 +09:00
YeonGyu-Kim b18963b0a9 Merge pull request #3868 from MoerAI/fix/openai-server-error-retryable
fix(model-error-classifier): mark OpenAI server_error patterns as retryable (fixes #3799)
2026-05-21 00:46:16 +09:00
YeonGyu-Kim 7651c856aa Merge pull request #3944 from survivor998/fix/ultraworker-display-name-zwsp
fix(display): lowercase ultraworker to avoid ZWSP rendering glitch
2026-05-21 00:45:07 +09:00
YeonGyu-Kim aa3187bfbb Merge pull request #4180 from JacobZyy/fix/plugin-hooks-merge 2026-05-21 00:14:58 +09:00
YeonGyu-Kim 12ed091e93 Merge pull request #4101 from sjawhar/fix/modalities-object-shape
fix(model-capabilities): handle object-shaped modalities in readModalityKeys
2026-05-21 00:10:29 +09:00
JacobZyy 33f121b113 fix: add PATH to restricted hook env, protect HOME/CLAUDE_PROJECT_DIR from allowlist override, reset plugin hooks state in tests
- P1: When allowedEnvVars is provided, PATH was missing from the base
  restricted env, causing non-builtin commands to fail at exec time
- P2: Allowlisted HOME/CLAUDE_PROJECT_DIR could overwrite normalized
  values from getHomeDirectory()/cwd with ambient process.env values
- P2: Test suite mutated shared pluginHooksState singleton without
  resetting it in afterEach, causing cross-test state leaks
2026-05-20 22:49:05 +08:00
YeonGyu-Kim 791825fc20 Merge pull request #4153 from MoerAI/fix/fallback-model-string-guard
fix(shared,delegate-task,claude-code-agent-loader): guard model parsers against non-string input (fixes #4145)
2026-05-20 23:40:33 +09:00
JacobZyy 0a20844bd4 fix: address PR #4180 review - security, typing, and test coverage
- Apply mcp_env_allowlist to plugin hooks: intersect HTTP allowedEnvVars
  with MCP allowlist, set command allowedEnvVars to full MCP allowlist
- Scrub process.env in executeHookCommand when allowedEnvVars provided
- Add PluginHooksState class with per-directory Map storage
- Add PluginHooksConfig interface for typed boundary layer
- Pass directory context through hook-config-handler
- Add 16 tests across 4 files (40 assertions) covering allowlist
  filtering, env scrubbing, directory isolation, and edge cases
- Remove unnecessary 'as' type assertions, use discriminated union
  narrowing instead
2026-05-20 22:30:25 +08:00
YeonGyu-Kim 32f0e1e0af Merge pull request #4186 from lang-911/feat/grok-reasoning-effort
fix(model-heuristics): register Grok family so reasoningEffort survives on @ai-sdk/openai
2026-05-20 22:05:22 +09:00
MoerAI c85d2f9bc8 fix(model-error-classifier): mark OpenAI server_error patterns as retryable (fixes #3799)
OpenAI streaming responses can surface mid-stream errors with type
'server_error' or with the prose message 'An error occurred while processing
your request'. Neither matched any entry in RETRYABLE_MESSAGE_PATTERNS, so
shouldRetryError returned false and the runtime-fallback / fallback-retry
code paths skipped retry. The result was that GPT-5.5 subagent (and main)
turns silently stalled until the stale timeout fired.

The maintainer's diagnosis on issue #3799 explicitly recommends adding
these two patterns to model-error-classifier.ts; this commit does exactly
that and adds two regression tests covering the JSON envelope and the
prose form.
2026-05-20 19:11:54 +09:00
YeonGyu-Kim 330e437f08 docs(agents): regenerate hierarchical AGENTS.md for 2026-05-20
Sync the AGENTS.md hierarchy to current code state:

Drift fixes in 11 existing files
- Root: 2026-05-20 commit 39aadbf9f, ~2167 TS files, 120 barrel index.ts,
  57 src/hooks dirs, 297 (179 non-test) src/shared files, 11 OpenCode hook
  handlers in plugin-interface.ts, packages list adds ast-grep-mcp + rules-core,
  first-prompt-watchdog 206 LOC, parent-wake-notifier 587 LOC
- src/AGENTS.md: file counts, plugin-interface handler count
- src/shared/AGENTS.md: title + counts 278/170 -> 297/179
- src/hooks/AGENTS.md: 57 dirs, note unwired WIP (task-reminder,
  hashline-edit-diff-enhancer)
- src/features/AGENTS.md: module map with NON-TEST counts + sub-AGENTS.md
  column, 7 modules without sub-doc
- src/features/background-agent/AGENTS.md: add 12 newer files (parent-wake-
  notifier 587 LOC, loop-detector, error-classifier, fallback-retry-handler,
  process-cleanup, subagent-spawn-limits, session-status-classifier,
  compaction-aware-message-resolver, etc.)
- src/plugin/AGENTS.md: 11 handlers, add system-transform.ts + command-
  execute-before.ts + build-team-idle-wake-hint-client.ts
- src/config/AGENTS.md: note schema/internal/permission.ts
- src/cli/AGENTS.md: 8 commands including 'version'
- src/plugin-handlers/AGENTS.md, packages/web/AGENTS.md: date bump

New AGENTS.md in 4 directories
- packages/AGENTS.md: index of 15 packages (11 platform binaries + 2 MCP
  packages + rules-core + web), role map, conventions
- docs/AGENTS.md: WHERE TO LOOK table for 19 docs across 6 subdirs
- .opencode/AGENTS.md: 5 skills + 4 slash commands + relationship to .agents/
- .agents/AGENTS.md: superset migration target (9 skills + 4 commands)
2026-05-20 17:18:44 +09:00
YeonGyu-Kim f8f4b572dc fix(runtime-fallback,prompt-gate): recognize all OpenCode progress event shapes and boolean/completed finish markers
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-20 13:12:06 +09:00
YeonGyu-Kim d3e218f912 fix(prompt): treat post-dispatch failures as accepted 2026-05-20 11:42:32 +09:00
Sami Jawhar 94e71936fb fix(model-capabilities): handle object-shaped modalities in readModalityKeys 2026-05-19 12:24:59 +00:00
YeonGyu-Kim b2918fd4db fix(team-mode): close peer message delivery races 2026-05-19 19:18:13 +09:00
YeonGyu-Kim bcea4a9d28 fix(prompt-gate): harden sync and team prompt dispatch 2026-05-19 19:18:13 +09:00
YeonGyu-Kim 1492bffd20 fix(prompt-gate): harden internal prompt dispatch 2026-05-19 19:18:13 +09:00
lang-911 8b097f2c3b fix(model-heuristics): register Grok family with reasoningEffort support
Grok model IDs (e.g. `grok-4.3`, `grok-3-mini`) were missing from `HEURISTIC_MODEL_FAMILY_REGISTRY`, so `resolveCompatibleModelSettings` returned an "unknown family" result for them.

The `chat.params` hook treats unknown families as "no reasoning support" and deletes `output.options.reasoningEffort` before the request leaves the plugin, so users routing Grok via OpenAI-compatible endpoints never saw their reasoning effort forwarded — even with `forceReasoning: true`.

Add a `grok` family entry that includes any model ID containing "grok", exposes `low | medium | high` variants, and sets `reasoningEfforts` so the heuristic surfaces the same capability flag used by the `chat.params` hook. Extend the family table-driven test in `model-settings-compatibility.test.ts` to cover `grok-4.3`.
2026-05-19 02:44:38 -07:00
YeonGyu-Kim bb75751410 fix(babysitter): avoid double prompt gate 2026-05-19 13:48:55 +09:00
YeonGyu-Kim e57bac3b6b fix(prompt-retry): preserve async holds without blocking validation fallbacks 2026-05-19 13:48:33 +09:00
YeonGyu-Kim 98c3fee181 fix(prompt-gate): detect finish-only tool waits 2026-05-19 13:16:39 +09:00
YeonGyu-Kim dfc2e8e4ae fix(prompt-retry): preserve peer prompt reservations 2026-05-19 13:16:39 +09:00
YeonGyu-Kim f5f358ab9d fix(prompt-gate): ignore internal user tails in tool waits 2026-05-19 13:16:39 +09:00
YeonGyu-Kim 90b3f4ac96 test: harden workspace package assumptions
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 21:28:12 +09:00
YeonGyu-Kim c9a3c34a29 test: stabilize dependency verification
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 20:55:33 +09:00
MoerAI ae0c106ed4 fix(shared,delegate-task,claude-code-agent-loader): guard model parsers against non-string input (fixes #4145)
After the 4.2.0 unified-dispatch refactor (a42f894f / df198d8b / fee515c5 / 989ab717 / dd3fecaf / 1bbe065c / 12bd6580), at least one caller in the new prompt-async-gate path forwards a FallbackModelObject (or some other non-string shape) into parsers that statically claim 'model: string'. The downstream .trim() call then throws 'model.trim is not a function', which rejects the session.processor promise and surfaces as 'Aborted process' + UI 'interrupted'. The issue (#4145) reports this aborts 90% of subagent dispatches across every provider on 4.2.0 + opencode 1.15.4.

This patch adds a 'typeof x !== "string"' runtime guard at the four parser entrypoints called from the dispatch path:

- src/shared/fallback-chain-from-models.ts :: parseVariantFromModel, parseFallbackModelEntry

- src/tools/delegate-task/model-string-parser.ts :: parseVariantFromModelID, parseModelString

- src/shared/model-string-parser.ts (duplicate file with same API) :: parseVariantFromModelID, parseModelString

- src/features/claude-code-agent-loader/claude-model-mapper.ts :: mapClaudeModelString

Each parser now returns undefined / { modelID: "" } for non-string input instead of throwing. This unblocks subagent dispatch and leaves the underlying caller bug for a follow-up.

Regression coverage: three new tests in src/shared/fallback-chain-from-models.test.ts pin the non-string behavior (object, null/undefined, number). Existing 38 tests still pass. Total: 41/41 green, typecheck clean.
2026-05-18 19:22:33 +09:00
YeonGyu-Kim c712b71d9a test(tmux): isolate pane close logic tests 2026-05-18 14:46:10 +09:00
YeonGyu-Kim 66cb72b831 fix(prompt-gate): bind session messages receiver 2026-05-18 14:22:58 +09:00
YeonGyu-Kim b2961409b7 test(shell-env): add csh/tcsh detection and buildEnvPrefix coverage
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 14:04:17 +09:00
YeonGyu-Kim bc2ed016e4 Merge pull request #4141 from code-yeongyu/fix/3396-config-skills-paths-discovery
fix: discover skills from host config.skills.paths set by other plugins
2026-05-18 13:50:34 +09:00
YeonGyu-Kim b0f432dbe5 Merge pull request #4136 from code-yeongyu/fix/4059-blocker4-reland
fix(runtime-fallback): reland BLOCKER-4 delegated empty-history fallback (#4059)
2026-05-18 13:50:03 +09:00
YeonGyu-Kim c8c06d601c Merge pull request #4020 from scw1109/fix/default-agent-sort-order
fix: respect default_agent in sort shim ordering
2026-05-18 13:48:58 +09:00
YeonGyu-Kim c37725bb7f Merge pull request #4139 from code-yeongyu/fix/3450-anthropic-context-limit-revisited
fix(shared): return GA 1M context limit for Anthropic 4.6/4.7 models without cached entry
2026-05-18 13:44:56 +09:00
YeonGyu-Kim 043e84be56 fix: add adaptHostSkillConfig utility for host config.skills.paths
Converts the host OpenCode config.skills object (with paths/urls arrays set by other plugins like superpowers) into the SkillsConfig format used by discoverConfigSourceSkills. Filters blank/whitespace entries and non-string values.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:43:08 +09:00
YeonGyu-Kim f5e063b00a fix: only call setDefaultAgentForSort when user explicitly sets default_agent
The previous code read params.config.default_agent which is always populated to
"Sisyphus - Ultraworker" by existing logic (lines 196-204) even when the user
never configured default_agent. This silently overrode any custom agent_order.

Now we gate on configuredDefaultAgent (the user's explicit value) so the sort
shim rank map is only mutated when the user actually set default_agent.

Add regression test: agent_order without default_agent must preserve order.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:42:59 +09:00
YeonGyu-Kim f17623d450 test(shared): isolate logger module in full suite
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:42:57 +09:00
YeonGyu-Kim b9a8ffec51 fix(shared): return GA 1M context limit for Anthropic 4.6/4.7 models without cached entry
Anthropic made the 1M context window GA for Opus 4.6, Sonnet 4.6, and 4.7 models on March 13, 2026 — no beta header required. The resolver was still falling back to 200K when no modelContextLimitsCache entry existed, causing premature compaction and over-truncation.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:36:01 +09:00
YeonGyu-Kim 03f04ca3da test(shared): isolate logger test overrides
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:24:08 +09:00
YeonGyu-Kim b20e2c9c55 fix: refactor 5 additional aliased output.args mutations + strengthen audit test
Address Oracle review feedback: refactor 4 aliased mutations via argsObject
in plugin/tool-execute-before.ts and 1 via toolOutput in atlas/tool-execute-before.ts.
Strengthen audit test regex to catch Output.args mutations regardless of the
variable name prefix (toolOutput, argsObject aliases).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:04:10 +09:00
YeonGyu-Kim 3a63a8b205 test(shared): add audit test forbidding direct output.args mutation + fix 9th site
Add replace-tool-args.audit.test.ts that scans src/**/*.ts for direct
output.args property assignments and Object.assign(output.args, ...) outside
the helper. Also fix the 9th mutation site discovered by the audit in
compaction-todo-preserver/hook.ts.

Add replace-tool-args.test.ts with 12 regression tests covering both mutable
and Object.freeze'd output.args scenarios for all hook patterns.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:46:52 +09:00
YeonGyu-Kim 6bffb2c40f feat(shared): add replaceToolArgs helper for safe tool-args mutation
opencode >=1.14 freezes output.args via Immer before plugin hooks run.
Direct property assignment or Object.assign on a frozen object throws
TypeError. This helper replaces output.args with a shallow clone
containing the patch, avoiding mutation of the frozen original.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:32:10 +09:00
Chau Luu 4713a90816 fix(shared): cap log file growth via size-based rotation
Refs #3772 (the rotation half — EPIPE shutdown-noise suppression
remains a separate follow-up).

`src/shared/logger.ts` appends every entry to `os.tmpdir()/oh-my-opencode.log`
via `fs.appendFileSync` with no size cap. On long-running or busy projects
the file grows into the multi-GB range — a real-world reproduction on one
machine showed a 4.5 GB `oh-my-opencode.log.1` accumulated from per-shutdown
noise across many sessions. Eats `%TEMP%` on Windows and `/tmp` on Unix.

Add size-based rotation inside the existing batched `flush()` path:

  oh-my-opencode.log    → oh-my-opencode.log.1
  oh-my-opencode.log.1  → oh-my-opencode.log.2 (oldest dropped)

Cap is 50 MB per file; worst-case on-disk footprint is therefore ~150 MB.
The check runs only inside `flush()`, so the cost is amortized over
`BUFFER_SIZE_LIMIT` (50 entries) or the 500 ms flush timer. All filesystem
ops stay wrapped in try/catch — logging must never throw — and a failed
rotation leaves existing on-disk state intact rather than crashing the
agent. Pattern mirrors `src/openclaw/reply-listener-log.ts`, but with two
backup slots instead of one to keep a usable history window for debugging.

No config knobs in this iteration. The issue proposes `logs.max_size_mb`
/ `logs.max_files`, but the defaults are reasonable and adding schema is
more surface area than the bug warrants. Easy to promote later (the
existing test seams already let callers override the cap).

Tests:
- `src/shared/logger.test.ts` (new): under-threshold no-rotate, over-
  threshold rotates to `.1`, repeated rotation evicts oldest, rotation-
  failure-doesn't-throw, default path lives under `os.tmpdir()`. Uses a
  `mock.module(...)` substring marker so `script/run-ci-tests.ts` routes
  the file to its own bun process — the logger module's singleton state
  otherwise gets contaminated by sibling tests that mock `./shared`.

Out of scope: suppressing specific shutdown-noise messages (EPIPE,
`unhandledRejection received during shutdown cleanup`). The rotation
cap bounds the disk impact regardless of which noise pattern is
generating volume; per-message suppression can stand on its own
merits in a follow-up.
2026-05-17 19:46:29 +00:00
YeonGyu-Kim 7a3a0a031c test(tmux): ignore unrelated pane runner mock calls
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-17 17:21:35 +09:00