Skip to content

feat: add server_url_override config for tmux integration#2987

Open
simoncrypta wants to merge 2 commits intocode-yeongyu:devfrom
simoncrypta:fix/tmux-server-url-override
Open

feat: add server_url_override config for tmux integration#2987
simoncrypta wants to merge 2 commits intocode-yeongyu:devfrom
simoncrypta:fix/tmux-server-url-override

Conversation

@simoncrypta
Copy link
Copy Markdown

@simoncrypta simoncrypta commented Mar 31, 2026

Summary

  • Adds server_url_override configuration option to tmux integration for overriding auto-detected server URLs
  • Fixes TLS certificate errors when opencode binds to VPN/Tailscale IPs by allowing users to force localhost
  • Adds comprehensive URL validation at config parse time and runtime with safe fallbacks

Changes

  • Added server_url_override field to TmuxConfigSchema with z.preprocess() to handle empty strings/null as undefined
  • Updated TmuxSessionManager to validate URLs and check for port '0', falling back safely on invalid URLs
  • Updated shared TmuxConfig type in src/plugin/types.ts to include server_url_override?: string
  • Updated plugin config initialization in index.ts to pass through the new option

Screenshots

N/A - Configuration/feature change without UI

Testing

# Build verification
bun build src/config/schema/tmux.ts --target bun --format esm
bun build src/features/tmux-subagent/manager.ts --target bun --format esm
bun build src/index.ts --target bun --format esm
bun build src/plugin/types.ts --target bun --format esm

Test Cases:

  • server_url_override: "http://localhost:4096" - Valid URL, uses localhost
  • server_url_override: "https://example.com:8080" - Valid HTTPS URL with port
  • server_url_override: "not-a-url" - Invalid URL, fails config validation
  • server_url_override: "" - Empty string, treated as not provided (via preprocess)
  • server_url_override: null - Null value, treated as not provided (via preprocess)
  • server_url_override: "http://localhost:0" - Port 0, falls back to default URL
  • Without server_url_override set - Uses existing auto-detection logic

Related Issues

Addresses issue where tmux integration fails when opencode auto-binds to VPN/Tailscale IPs (e.g., 100.77.163.81:4096) instead of localhost, causing TLS certificate errors during health checks.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

All contributors have signed the CLA. Thank you! ✅
Posted by the CLA Assistant Lite bot.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 3 files

Confidence score: 3/5

  • There is a concrete regression risk: malformed server_url_override values are not being validated early, so they can pass config parsing and later crash tmux health checks.
  • Both issues are medium severity (6/10) with high confidence (9/10), which suggests real user-facing instability unless URL validation is added at assignment/parsing time.
  • Pay close attention to src/config/schema/tmux.ts and src/features/tmux-subagent/manager.ts - missing URL validation for server_url_override can turn bad config into runtime failures instead of safe fallback behavior.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/config/schema/tmux.ts">

<violation number="1" location="src/config/schema/tmux.ts:29">
P2: Validate `server_url_override` as a real URL so malformed config values fail during config parsing instead of crashing tmux health checks.</violation>
</file>

<file name="src/features/tmux-subagent/manager.ts">

<violation number="1" location="src/features/tmux-subagent/manager.ts:82">
P2: Validate `server_url_override` before assigning it; malformed values now throw in the tmux health check instead of falling back safely.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@simoncrypta
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@simoncrypta simoncrypta force-pushed the fix/tmux-server-url-override branch from 644869c to d63a18d Compare March 31, 2026 18:14
github-actions bot added a commit that referenced this pull request Mar 31, 2026
@simoncrypta
Copy link
Copy Markdown
Author

@cubic-dev-ai re-review please - I have addressed the URL validation issues by:

  1. Changed schema validation from z.string().optional() to z.string().url().optional() for config-time URL validation

  2. Added runtime URL validation in manager.ts using new URL() with try-catch, falling back to default behavior on invalid URLs

Both issues should now be resolved.

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai bot commented Mar 31, 2026

@cubic-dev-ai re-review please - I have addressed the URL validation issues by:

  1. Changed schema validation from z.string().optional() to z.string().url().optional() for config-time URL validation

  2. Added runtime URL validation in manager.ts using new URL() with try-catch, falling back to default behavior on invalid URLs
    ...

@simoncrypta I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 3 files

Confidence score: 3/5

  • Schema in src/config/schema/tmux.ts still rejects ""/null, so documented "treat as not provided" cases can fail at config parse time, which is user-facing.
  • src/features/tmux-subagent/manager.ts accepts http://localhost:0; without the port === '0' guard, health checks and opencode attach will target port 0 and the pane never starts.
  • Given the concrete runtime/config impacts above, this change carries some risk and merits a careful check before merging.
  • Pay close attention to src/config/schema/tmux.ts, src/features/tmux-subagent/manager.ts, src/index.ts - config validation, port guard, and shared type wiring.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/features/tmux-subagent/manager.ts">

<violation number="1" location="src/features/tmux-subagent/manager.ts:83">
P2: Apply the existing `port === '0'` guard to `server_url_override`. Right now `http://localhost:0` is accepted, but health checks and `opencode attach` will target port 0 and the pane never starts.</violation>
</file>

<file name="src/index.ts">

<violation number="1" location="src/index.ts:54">
P2: Update the shared `TmuxConfig` type as well; this new field is currently untyped through `createManagers`.</violation>
</file>

<file name="src/config/schema/tmux.ts">

<violation number="1" location="src/config/schema/tmux.ts:29">
P2: This schema still rejects `""` and `null`, so the documented "treat as not provided" cases now fail at config parse time.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Add server_url_override option to tmux configuration to allow users
to override the auto-detected server URL. This fixes issues where
opencode binds to VPN/Tailscale IPs with TLS certificate errors,
preventing the tmux health check from succeeding.

Changes:
- Add server_url_override field to TmuxConfigSchema
- Update TmuxSessionManager to use override URL when provided
- Pass server_url_override through plugin config initialization

Users can now set tmux.server_url_override to "http://localhost:4096"
to force localhost instead of using auto-detected IPs.
@simoncrypta simoncrypta force-pushed the fix/tmux-server-url-override branch from d63a18d to 768a013 Compare March 31, 2026 18:40
@simoncrypta
Copy link
Copy Markdown
Author

@cubic-dev-ai re-review please - all 3 issues have been addressed:

  1. manager.ts:83 - Added guard for :

  2. plugin/types.ts - Added to the shared type so it's properly typed through

  3. schema.ts:29 - Added to handle empty strings and null values:

All test cases now pass.

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai bot commented Mar 31, 2026

@cubic-dev-ai re-review please - all 3 issues have been addressed:

  1. manager.ts:83 - Added guard for :

...

@simoncrypta I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Auto-approved: Safe addition of a configuration option with robust URL validation and fallback logic. Preserves existing behavior when the override is not used.

caravanglory added a commit to caravanglory/oh-my-magento that referenced this pull request Apr 2, 2026
* fix(sisyphus): block premature implementation before context is complete (fixes code-yeongyu#2274)

* fix(analyze-mode): add mandatory load_skills param hint to prevent delegate_task errors

* fix(hooks): add bash-file-read-guard to warn agents against cat/head/tail (fixes code-yeongyu#2096)

* fix(ralph-loop): add semantic completion detection as fallback for natural language (fixes code-yeongyu#2489)

* fix(ralph-loop): restrict semantic completion to DONE promise and assistant entries

- Gate semantic detection on promise === 'DONE' in both transcript and
  session message paths to prevent false positives on VERIFIED promises
- Restrict transcript semantic fallback to assistant/text entries only,
  skipping tool_use/tool_result to avoid matching file content
- Add regression test for VERIFIED promise not triggering semantic detection

* fix(shared): add bounded project discovery helpers

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(shared): support opencode directory aliases

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(skills): discover ancestor project skill directories

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(skills): expand tilde config source paths

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(agents): include .agents skills in agent awareness

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(commands): discover ancestor opencode project commands

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(slashcommand): discover nested opencode commands with slash names

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(skills): remove duplicate homedir import

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(tests): drop duplicate tilde config regression

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(model-requirements): align fallback models with available provider catalogs

- opencode/minimax-m2.7-highspeed → opencode/minimax-m2.5 (provider lacks m2.7 variants)
- opencode-go/minimax-m2.7-highspeed → opencode-go/minimax-m2.7 (provider lacks -highspeed)
- opencode/minimax-m2.7 → opencode/minimax-m2.5 (provider only has m2.5)
- added xai as alternative provider for grok-code-fast-1 (prevents wrong provider prefix)

* fix(model-resolution): honor user config overrides on cold cache

When provider-models cache is cold (first run / cache miss),
resolveModelForDelegateTask returns {skipped: true}. Previously this
caused the subagent resolver to:

1. Ignore the user's explicit model override (e.g. explore.model)
2. Fall through to the hardcoded fallback chain which may contain
   model IDs that don't exist in the provider catalog

Now:
- subagent-resolver: if resolution is skipped but user explicitly
  configured a model, use it directly
- subagent-resolver: don't assign hardcoded fallback chain on skip
- category-resolver: same — don't leak hardcoded chain on skip
- general-agents: if user model fails resolution, use it as-is
  instead of falling back to hardcoded chain first entry

Closes code-yeongyu#2820

* feat(doctor): warn on legacy package name + add example configs

- Doctor now detects when opencode.json references 'oh-my-opencode'
  (legacy name) and warns users to switch to 'oh-my-openagent' with
  the exact replacement string.

- Added 3 example config files in docs/examples/:
  - default.jsonc: balanced setup with all agents documented
  - coding-focused.jsonc: Sisyphus + Hephaestus heavy
  - planning-focused.jsonc: Prometheus + Atlas heavy

All examples include every agent (sisyphus, hephaestus, atlas,
prometheus, explore, librarian) with model recommendations.

Helps with code-yeongyu#2823

* feat: upgrade remaining MiniMax M2.5 fallbacks to M2.7-highspeed

Upgrade the secondary MiniMax fallback entries in librarian and explore
agents from M2.5 to M2.7-highspeed, completing the M2.5→M2.7 migration.

- librarian: minimax-m2.5 → minimax-m2.7-highspeed (2nd fallback)
- explore: minimax-m2.7 → minimax-m2.7-highspeed (2nd), minimax-m2.5 → minimax-m2.7 (3rd)
- Update corresponding test assertions

* fix(ci): resolve all test failures + complete rename compat layer

Sisyphus-authored fixes across 15 files:

- plugin-identity: align CONFIG_BASENAME with actual config file name
- add-plugin-to-opencode-config: handle legacy→canonical name migration
- plugin-detection tests: update expectations for new identity constants
- doctor/system: fix legacy name warning test assertions
- install tests: align with new plugin name
- chat-params tests: fix mock isolation
- model-capabilities tests: fix snapshot expectations
- image-converter: fix platform-dependent test assertions (Linux CI)
- example configs: expanded with more detailed comments

Full suite: 4484 pass, 0 fail, typecheck clean.

* fix(test): isolate model-capabilities from local provider cache

Mock connected-providers-cache in model-capabilities.test.ts to prevent
findProviderModelMetadata from reading disk-cached model metadata.

Without this mock, the 'prefers runtime models.dev cache' test gets
polluted by real cached data from opencode serve runs, causing the
test to receive different maxOutputTokens/supportsTemperature values
than the mock runtime snapshot provides.

This was the last CI-only failure — passes locally with cache, fails
on CI without cache, now passes everywhere via mock isolation.

Full suite: 4484 pass, 0 fail.

* fix(ralph-loop): extract text from parsed entry instead of testing raw JSONL

* @kuitos has signed the CLA in code-yeongyu#2833

* feat(hephaestus): upgrade default model from gpt-5.3-codex to gpt-5.4

Hephaestus now uses gpt-5.4 as its default model across all providers
(openai, github-copilot, venice, opencode), matching Sisyphus's GPT 5.4
support. The separate gpt-5.3-codex → github-copilot fallback entry is
removed since gpt-5.4 is available on all required providers.

* docs: update hephaestus default model references from gpt-5.3-codex to gpt-5.4

Updated across README (all locales), docs/guide/, docs/reference/,
docs/examples/, AGENTS.md files, and test expectations/snapshots.

The deep category and multimodal-looker still use gpt-5.3-codex as
those are separate from the hephaestus agent.

* feat(compat): package rename compatibility layer for oh-my-opencode → oh-my-openagent

- Add legacy plugin startup warning when oh-my-opencode config detected
- Update CLI installer and TUI installer for new package name
- Split monolithic config-manager.test.ts into focused test modules
- Add plugin config detection tests for legacy name fallback
- Update processed-command-store to use plugin-identity constants
- Add claude-code-plugin-loader discovery test for both config names
- Update chat-params and ultrawork-db tests for plugin identity

Part of code-yeongyu#2823

* fix(test): use Bun.spawnSync in command discovery test to avoid execFileSync mock leakage

The opencode-project-command-discovery test used execFileSync for git init,
which collided with image-converter.test.ts's global execFileSync mock when
running in parallel on Linux CI. Switching to Bun.spawnSync avoids the mock
entirely since spyOn(childProcess, 'execFileSync') doesn't affect Bun APIs.

Fixes CI flake that only reproduced on Linux.

* fix(test): make legacy-plugin-warning tests isolation-safe

Pass explicit config dir to checkForLegacyPluginEntry instead of relying
on XDG_CONFIG_HOME env var, which gets contaminated by parallel tests on
Linux CI. Also adds missing 'join' import.

* fix(publish): restore version commit-back to dev after npm release

* fix(session-recovery): filter invalid prt_* part IDs from tool_use_id reconstruction

When recovering missing tool results, the session recovery hook was using
raw part.id (prt_* format) as tool_use_id when callID was absent, causing
ZodError validation failures from the API.

Added isValidToolUseID() guard that only accepts toolu_* and call_* prefixed
IDs, and normalizeMessagePart() that returns null for parts without valid
callIDs. Both the SQLite fallback and stored-parts paths now filter out
invalid entries before constructing tool_result payloads.

Includes 4 regression tests covering both valid/invalid callID paths for
both SQLite and stored-parts backends.

* fix(test): restore shared Bun mocks after suite cleanup

Prevent src/shared batch runs from leaking module mocks into later files, which was breaking Linux CI cache metadata and legacy plugin warning assertions.

* fix(ci): isolate mock-heavy shared tests to prevent cross-file contamination

Move 4 src/shared tests that use mock.module() to the isolated test section:
- model-capabilities.test.ts (mocks ./connected-providers-cache)
- log-legacy-plugin-startup-warning.test.ts (mocks ./legacy-plugin-warning)
- model-error-classifier.test.ts
- opencode-message-dir.test.ts

Also isolate recover-tool-result-missing.test.ts (mocks ./storage).

Use find + exclusion pattern in remaining tests to dynamically build the
src/shared file list without the isolated mock-heavy files.

Fixes 6 Linux CI failures caused by bun's mock.module() cache pollution
when running in parallel.

* fix(publish-ci): sync mock-heavy test isolation with ci.yml

Apply the same mock.module() isolation fixes to publish.yml:
- Move shared and session-recovery mock-heavy tests to isolated section
- Use dynamic find + exclusion for remaining src/shared tests
- Include session-recovery tests in remaining batch

Ensures publish workflow has the same test config as main CI run.

* docs(config): document object-style fallback_models

* fix(delegate-task): apply category config temperature/maxTokens/top_p to categoryModel (fixes code-yeongyu#2831)

* fix(recovery): detect empty text parts alongside tool calls in fixEmptyMessages (fixes code-yeongyu#2830)

* fix(delegate-task): reject when both category and subagent_type provided (fixes code-yeongyu#2847)

* fix: add missing load_skills parameter to hook-injected delegate_task examples

* fix: detect empty text parts in messages with tool calls during session recovery

* fix(tools): add max_tools config to cap registered tools for OpenAI compatibility (fixes code-yeongyu#2848)

* test: update test to expect mutual exclusion error for category+subagent_type

* fix(cli): respect platform shell for --on-complete

* fix: guard fallback override to preserve category config params when fallback fields are undefined

* docs: comprehensive update for v3.14.0 features

- Document object-style fallback_models with per-model settings
- Add package rename compatibility layer docs (oh-my-opencode → oh-my-openagent)
- Update agent-model-matching with Hephaestus gpt-5.4 default
- Document MiniMax M2.5 → M2.7 upgrade across agents
- Add agent priority/order deterministic Tab cycling docs
- Document file:// URI support for agent prompt field
- Add doctor legacy package name warning docs
- Update CLI reference with new doctor checks
- Document model settings compatibility resolver

* @Jholly2008 has signed the CLA in code-yeongyu#2871

* fix(lsp): accept directory as alias for filePath in lsp_diagnostics

Models frequently hallucinate a 'directory' parameter alongside filePath,
causing hard failures. Instead of rejecting, accept directory as an alias
for filePath and gracefully handle when both are provided (prefer filePath).

This prevents the 'filePath and directory are mutually exclusive' error
that users hit when models pass both parameters.

Fixes model confusion with lsp_diagnostics tool parameters.

* docs: update documentation for v3.13.1 feature changes

- Document object-style fallback_models with per-model settings
- Add model-settings compatibility normalization docs
- Document file:// URI support for prompt and prompt_append
- Add deterministic core-agent order (Tab cycling) docs
- Update rename compatibility notes (legacy plugin warning)
- Document doctor legacy package name detection
- Add models.dev-backed capability cache documentation
- Update Hephaestus default to gpt-5.4 (medium)
- Correct MiniMax M2.7/M2.5 usage across all docs
- Update all agent/category provider chain tables
- Fix stale CLI install/doctor options to match source
- Add refresh-model-capabilities command to CLI reference

Co-authored-by: Sisyphus <sisyphus@oh-my-opencode>

* feat(atlas): support plugin tools with metadata.sessionId in orchestration hook

The tool-execute-after hook only processed the built-in 'task' tool.
Plugin tools (e.g. custom-agent-bridge delegate) that set
context.metadata({ metadata: { sessionId } }) were ignored by atlas
orchestration (boulder tracking, verification reminders).

- Add extractSessionIdFromMetadata() to read sessionId from tool
  metadata, preferred over text-based extraction
- Extend tool-execute-after guard to also process any tool that has
  metadata.sessionId set (not just tool === 'task')
- Recognize 'Background delegate launched' as a background launch
- Add tests for metadata-based session ID extraction

* fix: resolve three open bugs (code-yeongyu#2836, code-yeongyu#2858, code-yeongyu#2873)

- fix(context-limit): check modelContextLimitsCache for all Anthropic
  models, not just GA-model set; user config/cache wins over 200K default
  (fixes code-yeongyu#2836)

- fix(agent-key-remapper): preserve config key aliases alongside display
  names so `opencode run --agent sisyphus` resolves correctly
  (fixes code-yeongyu#2858)

- fix(tool-config): respect host permission.skill=deny by disabling
  skill/skill_mcp tools when host denies them (fixes code-yeongyu#2873)

- test: update context-limit and agent-key-remapper tests to match new
  behavior

* fix(code-yeongyu#2852): forward model overrides from categories/agent config to subagents

- fix(switcher): use lastIndexOf for multi-slash model IDs (e.g. aws/anthropic/claude-sonnet-4)
- fix(model-resolution): same lastIndexOf fix in doctor parseProviderModel
- fix(call-omo-agent): resolve model from agent config and forward to both
  background and sync executors via DelegatedModelConfig
- fix(subagent-resolver): inherit category model/variant when agent uses
  category reference without explicit model override
- test: add model override forwarding tests for call-omo-agent
- test: add multi-slash model ID test for switcher

* fix(code-yeongyu#2853): sync .sisyphus state from worktree to main repo before removal

When .sisyphus/ is gitignored, task state written during worktree execution
is lost when the worktree is removed. Fix:

- add worktree-sync.ts: syncSisyphusStateFromWorktree() copies .sisyphus/
  contents from worktree to main repo directory
- update start-work.ts template: documents the sync step as CRITICAL when
  worktree_path is set in boulder.json
- update work-with-pr/SKILL.md: adds explicit sync step before worktree removal
- export from boulder-state index
- test: 5 scenarios covering no-.sisyphus, nested dirs, overwrite stale state

* fix(code-yeongyu#2855): tmux health check fails across module instances in same process

The server-health module used module-level state for inProcessServerRunning,
which doesn't survive when Bun loads separate module instances in the same
process. Fix: use globalThis with Symbol.for key so the flag is truly
process-global.

- server-health.ts: replace module-level boolean with globalThis[Symbol.for()]
- export markServerRunningInProcess from tmux-utils barrel
- test: verify flag skips HTTP fetch, verify globalThis persistence

* fix: use getAgentDisplayName in injectBoulderContinuation

The agent parameter was using raw config key "atlas" but the SDK
expects the display name "Atlas (Plan Executor)". This caused
"Agent not found: 'atlas'" errors when auto-compact tried to
continue boulder execution.

Root cause: injectBoulderContinuation passed raw agent key to
session.promptAsync, but SDK's agent matching logic compares
against display names registered in the system.

Fix: Use getAgentDisplayName() to convert the config key to
the expected display name before passing to the SDK.

* fix(code-yeongyu#2736): prevent infinite compaction loop by setting cooldown before try

lastCompactionTime was only set on successful compaction. When compaction
failed (rate limit, timeout, etc.), no cooldown was recorded, causing
immediate retries in an infinite loop.

Fix: set lastCompactionTime before the try block so both success and
failure respect the cooldown window.

- test: add failed-compaction cooldown enforcement test
- test: fix timeout retry test to advance past cooldown

* @WhiteGiverMa has signed the CLA in code-yeongyu#2877

* fix(code-yeongyu#2731): skip unauthenticated providers when resolving subagent model

Background subagents (explore/librarian) failed with auth errors because
resolveModelForDelegateTask() always picked the first fallback entry when
availableModels was empty — often an unauthenticated provider like xai
or opencode-go.

Fix: when connectedProvidersCache is populated, iterate fallback chain
and pick the first entry whose provider is in the connected set.
Legacy behavior preserved when cache is null (not yet populated).

- model-selection.ts: use readConnectedProvidersCache to filter fallback chain
- test: 4 new tests for connected-provider-aware resolution

* fix(code-yeongyu#2822): properly cleanup tmux sessions on process shutdown

Two issues fixed:
1. process-cleanup.ts used fire-and-forget void Promise for shutdown
   handlers — now properly collects and awaits all cleanup promises
   via Promise.allSettled, with dedup guard to prevent double cleanup
2. TmuxSessionManager was never registered for process cleanup —
   now registered in create-managers.ts via registerManagerForCleanup

Also fixed setTimeout().unref() which could let the process exit
before cleanup completes.

* fix(code-yeongyu#2823): auto-migrate legacy plugin name and warn users at startup

- logLegacyPluginStartupWarning now emits console.warn (visible to user,
  not just log file) when oh-my-opencode is detected in opencode.json
- Auto-migrates opencode.json plugin entry from oh-my-opencode to
  oh-my-openagent (with backup)
- plugin-config.ts: add console.warn when loading legacy config filename
- test: 10 tests covering migration, console output, edge cases

* fix(code-yeongyu#2732): detect crashed subagent sessions with shorter timeout

When a subagent session disappears from the status registry (process
crashed), the main agent was waiting the full stale timeout before
acting. Fix:

- Add sessionGoneTimeoutMs config option (default 60s, vs 30min normal)
- task-poller: use shorter timeout when session is gone from status
- manager: verify session existence when gone, fail crashed tasks
  immediately with descriptive error
- Add legacy-plugin-toast hook for code-yeongyu#2823 migration warnings
- Update schema with new config option

* fix(code-yeongyu#2732): enhance notification for failed/crashed subagent tasks

- completedTaskSummaries now includes status and error info
- notifyParentSession: noReply=false for failed tasks so parent reacts
- Batch notification distinguishes successful vs failed/cancelled tasks
- notification-template updated to show task errors
- task-poller: session-gone tests (85 new lines)
- CI: add Bun shim to PATH for legacy plugin migration tests

* fix(code-yeongyu#2735): check model availability before using custom subagent default model

subagent-resolver: when falling back to matchedAgent.model for custom
subagents, verify the model is actually available via fuzzyMatchModel
before setting it as categoryModel. Prevents delegate_task from using
an unavailable model when the user's custom agent config references
a model they don't have access to.

Test updated to include the target model in available models mock.

* fix(code-yeongyu#2825): secondary agents no longer pruned after 30 min of total runtime

TTL (pruneStaleTasksAndNotifications) now resets on last activity:
- Uses task.progress.lastUpdate as TTL anchor for running tasks
  (was always using startedAt, causing 30-min hard deadline)
- Added taskTtlMs config option for user-adjustable TTL
- Error message shows actual TTL duration, not hardcoded '30 minutes'
- 3 new tests for the new behavior

* fix(code-yeongyu#2857): prevent npm scoped package paths from being resolved as skill paths

resolveSkillPathReferences: add looksLikeFilePath() guard that requires
a file extension or trailing slash before resolving @scope/package
references. npm packages like @mycom/my_mcp_tools@beta were incorrectly
being rewritten to absolute paths in skill templates.

2 new tests.

* fix(code-yeongyu#2854): enable task system by default (oracle/subagent delegation)

task_system now defaults to true instead of false. Users on opencode-go
or other plans were unable to invoke oracle or use subagent delegation
because experimental.task_system defaulted off.

The task system is the primary mechanism for oracle, explore, and other
subagent invocations — it should not be behind an experimental flag.

Users can still explicitly set experimental.task_system: false to opt out.

* fix: isolate event hook failures during dispatch

* fix(code-yeongyu#2754): include native PluginInput skills in skill() discovery

The skill tool previously only merged disk-discovered skills and preloaded
options.skills, so skills registered natively via ctx.skills (for example
from config.skills.paths or other plugins) were prompt-visible but not
discoverable by skill().

Fix:
- pass ctx.skills from tool-registry into createSkillTool
- extend SkillLoadOptions with nativeSkills accessor
- merge nativeSkills.all() results into getSkills()
- add test covering native PluginInput skill discovery

* fix(code-yeongyu#2748): pass browserProvider into skill() discovery

skill-context already filtered browser-related skills using the configured
browser provider, but the skill tool rebuilt discovery without forwarding
browserProvider. That caused skills like agent-browser to be prompt-visible
while skill() could still fail to resolve them unless browser_automation_engine.provider
was explicitly threaded through both paths.

Fix:
- pass skillContext.browserProvider from tool-registry into createSkillTool
- extend SkillLoadOptions with browserProvider
- forward browserProvider to getAllSkills()
- add regression tests for execution and description visibility

* fix(code-yeongyu#2849): resolve platform binaries using current package name

The installer wrapper and postinstall script still hardcoded the old
oh-my-opencode-* platform package family. When users installed the renamed
npm package oh-my-openagent (for example via npx oh-my-openagent install on
WSL2/Linux), the main package installed correctly but the wrapper looked for
nonexistent optional binaries like oh-my-opencode-linux-x64.

Fix:
- derive packageBaseName from package.json at runtime in wrapper/postinstall
- thread packageBaseName through platform package candidate resolution
- keep legacy oh-my-opencode default as fallback
- add regression test for renamed package family

* fix(code-yeongyu#2791): await session.abort() in all subagent completion/cancel paths

Fire-and-forget session.abort() calls during subagent completion left
dangling promises that raced with parent session teardown. In Bun on
WSL2/Linux, this triggered a StringImplShape assertion (SIGABRT) as
WebKit GC collected string data still referenced by the inflight request.

Fix: await session.abort() in all four completion/error paths:
- startTask promptAsync error handler (launch path)
- resume promptAsync error handler (resume path)
- cancelTask (explicit cancel path)
- tryCompleteTask (normal completion path)

Also marks the two .catch() error callbacks as async so the await is
valid.

Test: update session.deleted cascade test to flush two microtask rounds
since cancelTask now awaits abort before cleanupPendingByParent.

* fix(config): apply git_master defaults when section is missing (fixes code-yeongyu#2040)

* fix(start-work): gracefully handle missing Atlas agent (fixes code-yeongyu#2132)

* fix: detect and warn about opencode-skills conflict

When opencode-skills plugin is registered alongside oh-my-openagent,
all user skills are loaded twice, causing 'Duplicate tool names detected'
warnings and HTTP 400 errors.

This fix:
1. Detects if opencode-skills plugin is loaded in opencode.json
2. Emits a startup warning explaining the conflict
3. Suggests fixes: either remove opencode-skills or disable skills in oh-my-openagent

Fixes code-yeongyu#2881

* fix(delegate-task): honor user model override in category-resolver cold cache (fixes code-yeongyu#2712)

* fix(keyword-detector): add logging for silent skip paths (fixes code-yeongyu#2058)

* fix(session-recovery): fallback to fetching messageID from session messages (fixes code-yeongyu#2046)

* fix: apply Zod defaults to empty config fallback

* @codivedev has signed the CLA in code-yeongyu#2888

* fix: use display name in runtime-fallback retry

* fix: detect and warn about opencode-skills conflict

* fix: address review comments - remove duplicates and respect skills config

* fix(code-yeongyu#2885): add model_not_supported to RETRYABLE error patterns

model_not_supported errors from providers (e.g. OpenAI returning
{"error": {"code": "model_not_supported"}}) were not recognized as
retryable. Subagents would silently fail with no response, hanging the
parent session.

Fix:
- Add "model_not_supported", "model not supported", "model is not
  supported" to RETRYABLE_MESSAGE_PATTERNS in model-error-classifier.ts
- Add regex patterns to RETRYABLE_ERROR_PATTERNS in
  runtime-fallback/constants.ts to match "model ... is ... not ...
  supported" with flexible spacing
- Add regression test covering all three variations

Now model_not_supported errors trigger the normal fallback chain instead
of silent failure.

* fix: resolve 25 pre-publish blockers

- postinstall.mjs: fix alias package detection
- migrate-legacy-plugin-entry: dedupe + regression tests
- task_system: default consistency across runtime paths
- task() contract: consistent tool behavior
- runtime model selection, tool cap, stale-task cancellation
- recovery sanitization, context-limit gating
- Ralph semantic DONE hardening, Atlas fallback persistence
- native-skill description/content, skill path traversal guard
- publish workflow: platform awaited via reusable workflow job
- release: version edits reapplied before commit/tag
- JSONC plugin migration: top-level plugin key safety
- cold-cache: user fallback models skip disconnected providers
- docs/version/release framing updates

Verified: bun test (4599 pass), tsc --noEmit clean, bun run build clean

* fix: resolve 5 remaining pre-publish blockers (14, 15, 17, 21, 25c)

- completion-promise-detector: restrict to assistant text parts only,
  remove tool_result from completion detection (blocker 14)
- ralph-loop tests: flip tool_result completion expectations to negative
  coverage, add false-positive rejection tests (blocker 15)
- skill tools: merge nativeSkills into initial cachedDescription
  synchronously before any execute() call (blocker 17)
- skill tools test: add assertion for initial description including
  native skills before execute() (blocker 25c)
- docs: sync all 4 fallback-chain docs with model-requirements.ts
  runtime source of truth (blocker 21)

Verified: bun test (4599 pass / 0 fail), tsc --noEmit clean

* fix(recovery): ignore empty summary-only assistant messages

* test(fallback): add quotio-only integration matrix

* test(fallback): rename quotio matrix to cliproxyapi

* @AlexDochioiu has signed the CLA in code-yeongyu#2916

* add bool value: tdd to sisyphus_agent config

* nit

* nit

* @ryandielhenn has signed the CLA in code-yeongyu#2919

* use optional instead of required for tdd config for backwards compatibility

* fix: resolve 3 community-reported bugs (code-yeongyu#2915, code-yeongyu#2917, code-yeongyu#2918)

- background_output: snapshot read cursor before consuming, restore on
  /undo message removal so re-reads return data (fixes code-yeongyu#2915)
- MCP loader: preserve oauth field in transformMcpServer, add scope/
  projectPath filtering so local-scoped MCPs only load in matching
  directories (fixes code-yeongyu#2917)
- runtime-fallback: add 'reached your usage limit' to retryable error
  patterns so quota exhaustion triggers model fallback (fixes code-yeongyu#2918)

Verified: bun test (4606 pass / 0 fail), tsc --noEmit clean

* @lorenzo-dallamuta has signed the CLA in code-yeongyu#2925

* fix(rules-injector): respect claude_code config for user rule loading

When claude_code integration is disabled in oh-my-opencode.json, the
rules-injector now skips loading rules from ~/.claude/rules/ to prevent
Claude Code-specific instructions from leaking into non-Claude agents
(e.g., GPT-5.4 Sisyphus), which causes agent hallucination.

Also adds ~/.sisyphus/rules/ and ~/.opencode/rules/ as OpenCode-native
user rule directories that are always searched regardless of config.

Fixes code-yeongyu#2920

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* @quangtran88 has signed the CLA in code-yeongyu#2929

* fix: use strict equality for claude_code flag checks

Use `=== false` instead of falsy negation so that missing/undefined
fields are not treated as explicitly disabled. Only skip ~/.claude/rules
when all three flags are explicitly set to false.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: stabilize timestamp-output tests across timezones

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* @HOYALIM has signed the CLA in code-yeongyu#2935

* fix: preserve nested async skill names in discovery

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test: cover remaining nested async skill paths

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* address bot review

* address bot review

* @florianschepp has signed the CLA in code-yeongyu#2938

* fix(delegate-task): replace mutual exclusion throw with category-wins override

* fix: permanently resolve agent name duplication yo-yo bug

* @major has signed the CLA in code-yeongyu#2942

* feat(tmux): add session isolation mode for subagent panes

* fix(anthropic-effort): skip effort injection for internal agents (fixes code-yeongyu#2940)

Internal agents (title, summary, compaction) no longer receive the
anthropic-beta effort header, preventing 400 errors on Google Vertex
Anthropic provider.

Verified: 12 tests pass, typecheck clean

* fix(config): accept object-format fallback_models in Zod validation (fixes code-yeongyu#2943)

FallbackModelsSchema now explicitly accepts string[], object[], and
mixed array formats, matching the JSON schema definition.

Verified: 15 config schema tests pass, typecheck clean

* @kui123456789 has signed the CLA in code-yeongyu#2958

* fix: add ./ prefix to package.json main field for OpenCode-Go plugin loading (code-yeongyu#2966)

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: skip thinking param injection for GLM models in sisyphus-junior (code-yeongyu#2967)

GLM-5 has native reasoning built-in. Injecting thinking: {type: 'enabled'}
causes a param conflict (400 error). Add isGlmModel() check to return base
config without thinking/reasoningEffort for GLM models.

- Add isGlmModel() helper to types.ts
- Early return in createSisyphusJuniorAgentWithOverrides for GLM models
- Add tests for isGlmModel and GLM reasoning config behavior

* fix(tests): resolve 25 pre-publish test failures

- Add providerModelsCache/fetchAvailableModels mocks to 20 utils.test.ts
  tests that broke when createBuiltinAgents started reading the cache
- Isolate ALL src/plugin and src/features/background-agent test files in CI
  (mock.module pollution crosses between files in the same bun process)
- Mirror CI isolation changes in publish.yml

25 failures → 0 in CI (all mock-pollution tests run individually)

* @duckkkkkkkkking has signed the CLA in code-yeongyu#2980

* @TravisDart has signed the CLA in code-yeongyu#2982

* @simoncrypta has signed the CLA in code-yeongyu#2987

* fix(tests): resolve 6 test isolation failures in full suite

3 failures in fallback.cliproxyapi-matrix.test.ts:
- Root cause: leaked spyOn(getMainSessionID) in
  tool-execute-before-session-notification.test.ts was never restored,
  poisoning module state for subsequent tests in the same worker
- Added mockRestore() call and _resetModelFallbackForTesting in afterEach

3 failures in background-agent/manager.test.ts:
- Root cause: connected-providers-cache memConnected/memProviderModels
  persisted across test files, making isReachable() skip fallback
  candidates in retry tests
- Added mock.module for connected-providers-cache at file level
- Added _resetMemCacheForTesting export and global beforeEach cleanup

Full suite: 4638/4638 pass, 0 fail

* fix(agents): stop advertising custom agents to orchestrators

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(delegate-task): reject stray backend-style categories

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(agents): use list display names for ordered agent config

* refactor(background-task): stop cancelling launched tasks during session wait

* test(delegate-task): cover aborted concurrent background launches

* chore(schema): regenerate oh-my-opencode schema

* chore: remove unused FIX-BLOCKS.md and uvscripts dev utility

* fix: normalize zero-width prefix in agent registration lookup

* fix(tmux): allow subsequent subagents to spawn in existing isolated container

* fix: resolve process-cleanup signal delay and hashline_edit tool name mismatch

* fix: add missing run_in_background to resume snippet and fix background launch detection

* fix: honor category-derived model overrides in call_omo_agent

* fix: distinguish transient errors from missing sessions in crash detection

* fix: apply scope filter to getSystemMcpServerNames and fix async native skill description refresh

* fix: use jsonc-parser for safe JSONC migration and add project-local config detection

* feat: add review-work and ai-slop-remover as built-in skills, add remove-ai-slops command

Embed user-level skills into the plugin's built-in system so they ship
with the product rather than requiring per-user configuration.

- review-work: 5-agent parallel post-implementation review orchestrator
- ai-slop-remover: per-file AI-generated code smell detector and remover
- /remove-ai-slops: command that orchestrates parallel ai-slop-remover runs

* fix: revert delegate-task to string category schema, fix mock isolation and restore UB7 originals

* feat(deep): upgrade default model from gpt-5.3-codex to gpt-5.4

Deep category now uses gpt-5.4 as its default model across all providers
(openai, github-copilot, venice, opencode), matching Hephaestus's GPT 5.4
upgrade. The requiresModel constraint is removed since gpt-5.4 is widely
available. Adds openai/gpt-5.3-codex -> openai/gpt-5.4 config migration
for existing user configs. Deep category prompt optimized for GPT 5.4's
stronger native capabilities (leaner, less verbose).

* docs: update deep category model references from gpt-5.3-codex to gpt-5.4

* fix(dispose): improve hook disposal and plugin cleanup

🤖 Generated with assistance of OhMyOpenCode

* fix(anthropic-recovery): fix retry timer memory leak in context window recovery

🤖 Generated with assistance of OhMyOpenCode

* feat(context-injector): enhance context collector functionality

🤖 Generated with assistance of OhMyOpenCode

* feat(claude-code-hooks): improve session handling and add tests

🤖 Generated with assistance of OhMyOpenCode

* fix(comment-checker): improve pending calls handling and add tests

🤖 Generated with assistance of OhMyOpenCode

* feat(lsp): add extension inference and improve diagnostics

🤖 Generated with assistance of OhMyOpenCode

* feat(openclaw): improve dispatcher and integration

🤖 Generated with assistance of OhMyOpenCode

* fix(anthropic-recovery): improve executor test coverage and assertions

🤖 Generated with assistance of OhMyOpenCode

* fix(delegate-task): update test category references from deep to quick

🤖 Generated with assistance of OhMyOpenCode

* fix(start-work): fall back to sisyphus without atlas

/start-work should leave plan mode even when Atlas is unavailable. This prevents Prometheus from being persisted into boulder state and keeping resumed work sessions in md-only mode.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(agents): make sisyphus, hephaestus, atlas primary-only (not callable as subagents)

These agents should only be usable as primary session agents, not as
subagent targets via call_omo_agent/task(). Previously MODE was 'all'
which allowed them to be spawned as subagents, leading to confusing
behavior (e.g. Atlas delegating to Hephaestus as a subagent).

Subagent-callable agents remain: oracle, explore, librarian,
multimodal-looker, metis, momus, sisyphus-junior.

Note: Prometheus is not a BuiltinAgentName and is only invoked via
slash commands, so no change needed there.

* fix(start-work): restore atlas handoff

Keep native /start-work resolvable on Sisyphus, but switch the work session back to Atlas when Atlas is registered. Stamp the outgoing agent with Atlas's actual list-display key so config→start-work execution resolves correctly and still falls back to Sisyphus when Atlas is unavailable.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(auto-slash-command): resolve project commands from session dir

Use the plugin session directory instead of process.cwd() when resolving project slash commands. This restores project and opencode-project slashcommand behavior when the runtime cwd differs from the actual session workspace.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* @GreenPi290 has signed the CLA in code-yeongyu#2991

* @sihy233 has signed the CLA in code-yeongyu#3004

* fix: remove orphan closing brace in signatures/cla.json

The CLA assistant action failed with a JSON parse error due to a
duplicate closing brace at line 2475.

* fix: remove orphan closing brace in signatures/cla.json on dev branch

* fix: resolve usage module merge conflicts and typecheck error

- Accept upstream usage module (CLI usage reporting with SQLite)
- Fix cross-db-query type error by casting OpenCodeDB to access private path
- Fix report-generator test expectations (upstream has investment section)

* fix: resolve usage module merge conflicts and test expectations

- Accept upstream usage module (CLI usage reporting with SQLite)
- Fix cross-db-query type error (private path access)
- Fix opencode-db.test.ts byAgent expectation (2 groups, not 3)

---------

Co-authored-by: MoerAI <skyinbss@gmail.com>
Co-authored-by: Taegeon Go (Alan) <tae.gun7784@gmail.com>
Co-authored-by: YeonGyu-Kim <code.yeon.gyu@gmail.com>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: PR Bot <pr-bot@minimaxi.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Peïo Thibault <peio.thibault@gmail.com>
Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com>
Co-authored-by: ewjin <leewoojin98@naver.com>
Co-authored-by: 孔祥俊 <xiangjunkong90@gmail.com>
Co-authored-by: Sisyphus <sisyphus@oh-my-opencode>
Co-authored-by: sanoyphilippe <philippeoscar.sanoy@osome.com>
Co-authored-by: WhiteGiverMa <WhiteGiverMa@users.noreply.github.com>
Co-authored-by: User <user@example.com>
Co-authored-by: codivedev <codive.dev@gmail.com>
Co-authored-by: Ryan Dielhenn <dielhennr@gmail.com>
Co-authored-by: Tran Quang <randytran8800@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Ho Lim <166576253+HOYALIM@users.noreply.github.com>
Co-authored-by: Sami Jawhar <sami@trajectorylabs.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant