Commit Graph

6325 Commits

Author SHA1 Message Date
YeonGyu-Kim f0f798d1b8 Merge pull request #4138 from code-yeongyu/fix/3207-git-master-shell-detect-reland
fix(git-master): use shared shell detection for cross-platform env prefix (fix #3207)
2026-05-18 13:40:33 +09:00
YeonGyu-Kim fdf7ba2e6f Merge pull request #4129 from code-yeongyu/feature/stage-c-lsp-mcp
Extract LSP tools into Tier-1 MCP server via lsp-tools-mcp submodule
2026-05-18 13:39:17 +09:00
YeonGyu-Kim 6251a63219 Merge pull request #4135 from code-yeongyu/fix/3893-team-mode-fresh-install
fix: add team mode fresh install diagnostics
2026-05-18 13:38:30 +09:00
YeonGyu-Kim 2387f1e702 Merge pull request #4134 from code-yeongyu/ulw/rule-comment-baseline-20260518
Optimize rules injector caches
2026-05-18 13:37:09 +09:00
YeonGyu-Kim 161813c1e6 test(doctor): remove unstable unavailable-binary assertion
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:34:24 +09:00
YeonGyu-Kim a0b015507d Merge pull request #4137 from code-yeongyu/fix/3763-exa-bearer-auth-reland
fix(websearch): use Bearer auth for Exa MCP
2026-05-18 13:33:37 +09:00
YeonGyu-Kim d7caeb0178 fix(git-master): use shared shell detection for cross-platform env prefix (fix #3207)
Use detectShellType() and buildEnvPrefix() from src/shared/shell-env.ts instead of hardcoding bash-only VAR=value syntax. PowerShell users get $env:VAR='value'; cmd users get set VAR="value" &&; unix/Git Bash users keep VAR=value. Skips injecting non-bash prefixes into bash code blocks to avoid syntax mismatch.

Reland of #3214 (ekkoitac) which had unresolvable CLA + used custom shell detection instead of the shared utility.

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

Co-authored-by: ekkoitac <lobster@example.com>

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:31:55 +09:00
YeonGyu-Kim 00e6c82409 Merge pull request #4117 from ririnto/fix/plan-subagent-hidden-registry
fix(delegate-task): restore hidden plan subagent delegation
2026-05-18 13:30:35 +09:00
YeonGyu-Kim 50ae2e110e perf(rules-injector): cache match decisions
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:30:23 +09:00
YeonGyu-Kim a4cd7457e1 test(doctor): force unavailable lsp binary branch in CI
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:29:10 +09:00
YeonGyu-Kim 5ae0db042d fix(websearch): use Bearer auth for Exa MCP
Switch from query-param (?exaApiKey=...) to Authorization: Bearer header
for Exa MCP authentication. The MCP SDK's SSE endpoint resolution discards
query parameters when the server replies with a relative path, causing
EXA_API_KEY to be silently lost and falling back to rate-limited free tier.

Bearer auth via header survives URL resolution and is consistent with the
Tavily MCP config pattern already in use.

Fixes #3763
Relands #4090 (CLA unsigned by original author)

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

Co-authored-by: Minsoo Choi <Neo1228@users.noreply.github.com>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:28:31 +09:00
YeonGyu-Kim 364c7fee3d docs: note team mode fresh install fix
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 364092701f docs: add team mode fresh install note
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 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 21b782de93 test(plugin): cover fresh install team mode tools
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 9bae873395 fix(plugin): log team tool registry state
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 e5653f1655 fix(config): log resolved team mode state
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 9560e93235 docs: correct tool directory counts and lsp alias wording
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:21:25 +09:00
YeonGyu-Kim 7e777b0cde chore(mcp): ship vendored lsp cli in npm artifacts
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:21:13 +09:00
YeonGyu-Kim 69371b78b7 test(mcp): stabilize lsp builtin and doctor checks
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:21:02 +09:00
YeonGyu-Kim f7b60e360f fix(mcp): harden lsp cli resolution and doctor disable checks
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:20:41 +09:00
YeonGyu-Kim 5555dbfc67 Merge pull request #4133 from code-yeongyu/fix/3816-frozen-output-args
fix: replace direct output.args mutation with replaceToolArgs helper (fixes #3816)
2026-05-18 13:09:30 +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 61890f0857 fix(rules-injector): bound parsed rule cache
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:58:41 +09:00
YeonGyu-Kim 46b965b9da fix(rules-injector): bound matcher cache
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:58:41 +09:00
YeonGyu-Kim 1ab1b54ce6 perf(rules-injector): cache compiled glob matchers
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:58:41 +09:00
YeonGyu-Kim a7e5a657e9 Merge pull request #4131 from code-yeongyu/fix/3563-effort-max-pre-set-clamp
fix(anthropic-effort): clamp pre-set effort=max for constrained providers regardless of variant (fixes #3563)
2026-05-18 12:50:26 +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 13d8857415 refactor(hooks): replace direct output.args mutation with replaceToolArgs (question/webfetch/null-byte)
Replace Object.assign(output.args, truncatedArgs), output.args.url = resolution.url,
and output.args.command = ... .replace(/\x00/g, "") with replaceToolArgs() calls
in question-label-truncator, webfetch-redirect-guard, and plugin/tool-execute-before.

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 af66b8de0b refactor(hooks): replace direct output.args mutation with replaceToolArgs (env + prompt injectors)
Replace output.args.command and output.args.prompt direct assignments
with replaceToolArgs() in non-interactive-env, prometheus-md-only,
and sisyphus-junior-notepad hooks.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:37:45 +09:00
YeonGyu-Kim 63a3021094 test(anthropic-effort): cover pre-set effort=max clamping for constrained providers (#3563)
Add 4 regression tests covering the pre-set effort path:

- pre-set effort=max + variant=max + github-copilot Opus -> clamped to high

- pre-set effort=max + variant=high + github-copilot Opus -> clamped to high (cubic violation case from PR #3608)

- pre-set effort=max + non-constrained Opus -> max preserved (no regression)

- pre-set effort=high + github-copilot Opus -> high preserved (don't overwrite valid pre-set)

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:36:56 +09:00
YeonGyu-Kim 96767b5d1a fix(anthropic-effort): clamp pre-set effort=max for constrained providers regardless of variant
Move the pre-set effort handling BEFORE the message.variant !== "max" early-return so that output.options.effort="max" set via session params or model-requirements fallback chains is always clamped to "high" on constrained providers (github-copilot, Anthropic OAuth), even when message.variant is not "max".

This addresses the cubic violation from PR #3608 where the clamp block was gated behind the variant-based return.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:36:45 +09:00
YeonGyu-Kim f72bb3fe8f refactor(hooks): replace direct output.args mutation with replaceToolArgs (claude-code-hooks)
Replace output.args.todos = parsed and Object.assign(output.args, result.modifiedInput)
with replaceToolArgs() calls that create a shallow clone instead of
mutating the potentially-frozen args object.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:33:32 +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
YeonGyu-Kim b149ce5331 docs: update AGENTS docs for MCP-backed LSP architecture 2026-05-18 12:24:44 +09:00
YeonGyu-Kim 54eb3963af chore(ci): init and build vendor lsp submodule in CI 2026-05-18 12:22:54 +09:00
YeonGyu-Kim 48c827ffc0 test: update plugin tests for MCP-backed LSP 2026-05-18 12:22:54 +09:00
YeonGyu-Kim 8716ef458c refactor(plugin): drop lspManager lifecycle wiring 2026-05-18 12:22:54 +09:00
YeonGyu-Kim ca51f613ca refactor(tools): remove native LSP tool registry wiring 2026-05-18 12:22:54 +09:00
YeonGyu-Kim c2c078fec3 feat(mcp): register lsp tier-1 stdio MCP server 2026-05-18 12:22:54 +09:00
YeonGyu-Kim d95a45c872 chore: add lsp-tools-mcp submodule at vendor/lsp-tools-mcp 2026-05-18 12:22:54 +09:00
YeonGyu-Kim 34e6af1ae6 docs: update AGENTS guidance 2026-05-18 11:49:56 +09:00
YeonGyu-Kim c4dd21e1f3 Merge pull request #4127 from code-yeongyu/fix/3997-notification-crash
fix(hooks): guard session-notification against missing ctx.$ (refs #3997)
2026-05-18 11:12:38 +09:00
YeonGyu-Kim baa0470e2f Merge pull request #3870 from cvqluu/fix/3772-log-bloat-and-epipe-suppression
fix(shared): cap log file growth via size-based rotation
2026-05-18 11:09:37 +09:00
YeonGyu-Kim 6037b91706 Merge pull request #4122 from mguttmann/fix-4120
fix(background-agent): defer parent-wake when a user message just arrived (fixes #4120)
2026-05-18 11:06:00 +09:00
YeonGyu-Kim 442cdebc14 docs: add Deepgram to sponsor list in README files 2026-05-18 10:58:24 +09:00
YeonGyu-Kim 755f380a85 docs: update AGENTS.md metadata for v4.2.0 release 2026-05-18 10:58:20 +09:00
YeonGyu-Kim 397ed1048a fix(hooks): guard session-notification against missing ctx.$ (refs #3997) 2026-05-18 10:47:27 +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
Claude Agent 3294128271 fix(background-agent): defer parent-wake when a user message just arrived (fixes #4120)
When a background subagent emits [ALL BACKGROUND TASKS COMPLETE], the
plugin queues a parent-wake that ultimately calls
dispatchInternalPrompt against the parent session. If the user submits
a new prompt inside the ~250 ms post-dispatch hold window, both writes
land on the same OpenCode session-storage file at the same instant.
OpenCode's @parcel/watcher (which the plugin itself does not depend on,
but does indirectly trigger) batches those events into a TSFN callback
and dispatches them into a JS env that the renderer has just torn down
because the session view re-mounted around the user's new message ->
napi_fatal_error / SIGABRT on macOS arm64. Removing the plugin removes
the parent-wake, which is why removing OmO eliminates the crash.

Mitigation:
- Before flushPendingParentWake calls dispatchInternalPrompt, inspect
  the parent session's message tail. If the most recent message is a
  user message added inside PARENT_WAKE_USER_MESSAGE_IN_PROGRESS_WINDOW_MS
  (default 2_000 ms), reschedule instead of dispatching. The user's own
  prompt will drive the model; queued notifications will be re-flushed
  on the next idle.
- Best-effort unref() of the long-lived pending-retry and dispatched-
  wake bookkeeping setTimeouts. They previously pinned the host event
  loop and prolonged the teardown window during which the watcher race
  can fire.

The new option userMessageInProgressWindowMs is wired through
BackgroundManager via a module-level constant and is independently
testable.

Regression test parent-wake-user-message-race.test.ts covers:
- fresh user message -> dispatch deferred
- latest message is assistant -> dispatch proceeds
- user message older than window -> dispatch proceeds
- window=0 disables the guard

This is a surface-level mitigation of the most-likely root cause from
the audit; a deeper fix (singleton guard against plugin
double-instantiation under @opencode-ai/plugin@local reload, dispose
lifecycle for OpenCode plugin reload) is out of scope here.
2026-05-17 21:27:11 +02:00