Commit Graph
9801 Commits
Author SHA1 Message Date
roboomp b257a6dcbf fix(session): preserved startup fallback ownership
- Carried startup-selected fallback role and primary selector into AgentSession.
- Continued remaining role fallback entries after the startup fallback fails.
- Added regression coverage for chained startup failover.

Fixes #6283
2026-07-22 11:11:30 +00:00
roboomp b823c18837 fix(catalog): guarded request-model header recovery
Versioned request-header restoration metadata inside v10 cache rows so only markers written by the old id-only matcher can bypass an unrestorable marker through requestModelId. Current aliases whose live headers differ from their static base remain unresolved and are refetched or dropped.

Added catalog and startup-registry regressions for custom-header aliases while preserving legacy Copilot -1m cache recovery.

Fixes #6284
2026-07-22 11:10:23 +00:00
roboomp 79edf46158 fix(sdk): preserved suffixed role fallback lookup
- Stripped explicit thinking suffixes before recording configured role identity.
- Covered unavailable suffixed-role primaries selecting authenticated fallbacks.

Fixes #6283
2026-07-22 11:01:05 +00:00
roboomp d9bab7ce8b fix(catalog): restore cached request-model variants via requestModelId
Copilot -1m long-context variants are synthesized with transport
headers and a requestModelId to a bundled base. The v10 cache omits
headers; the writer only matched a same-id static entry, so these
variants were flagged unrestorable and dropped on the next offline
read, vanishing from the picker with a "Could not restore model"
warning. The startup registry loader dropped them the same way.

Restore/match headers through requestModelId in the cache writer, the
model-manager restore path, and the coding-agent startup loader, and
bypass a stale unrestorable marker written by the old id-only writer.

Fixes #6284
2026-07-22 10:59:10 +00:00
roboomp 093f7c2660 fix(sdk): resolved missing role fallback chains
- Carried configured role identity through deferred CLI model resolution.
- Consulted ordered authenticated role fallbacks after unavailable primaries.
- Added startup regression coverage for missing primary and fallback entries.

Fixes #6283
2026-07-22 10:52:57 +00:00
Wolfgang Schoenberger 9ce37050d6 style(coding-agent): sort native diff imports 2026-07-22 01:58:26 -07:00
Wolfgang Schoenberger 2b7707e6d7 perf(coding-agent): use native diff for edit diffs, intra-line word diff, and hashline recovery 2026-07-22 01:24:43 -07:00
Alexander Kirilin 5abac0245a fix(agent): bound OpenRouter thinking stream retries 2026-07-22 03:21:00 -04:00
roboomp dfeaa7aed1 fix(catalog): aborted codex discovery on failed account refresh
resolveCodexDiscoveryAccounts now returns null when any stored Codex OAuth
account fails to resolve (e.g. a transient refresh failure), and the manager's
resolveAccounts callback propagates null to skip discovery. Previously a failed
account was silently dropped before unionCodexModels saw it, so the remaining
accounts were unioned and cached as the authoritative catalog, hiding the
failed account's models for the cache TTL. Aborting keeps the previous/bundled
catalog.

Add a ModelRegistry regression test with one refreshable and one failing Codex
account asserting discovery makes no /models call and bundled models survive.

Fixes #6265
2026-07-22 07:19:11 +00:00
roboomp 2eff59e060 fix(catalog): preserved codex discovery token fallback
Keep the bearer resolved by the discovery preflight when it is not among the
stored OAuth account resolutions. This preserves Codex discovery for env,
runtime/config override, and stored non-OAuth credential sources while still
unioning all configured OAuth account catalogs.

Add a ModelRegistry regression test that drives runtime-key discovery and
asserts the resolved bearer reaches the Codex models endpoint.

Fixes #6265
2026-07-22 07:08:22 +00:00
roboomp b9dd5bce8a fix(catalog): unioned codex models across oauth accounts
Codex catalog discovery resolved a single access token, mapped it to one
chatgpt-account-id, and made one authoritative fetchCodexModels call whose
result pruned bundled entries. With multiple ChatGPT/Codex OAuth accounts,
the visible catalog depended on whichever account the discovery preflight
selected, hiding models available only through a sibling account.

openaiCodexModelManagerOptions now takes a resolveAccounts callback, fetches
each configured account's /models catalog independently, and unions them by
id before the authoritative merge. Bundled models are retained when every
account fetch fails. The runtime wiring resolves every stored openai-codex
OAuth account via AuthStorage.getOAuthAccesses.

Fixes #6265
2026-07-22 07:00:31 +00:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 546a8caa1b Refresh base system prompt after switchSession to sync workspace-roots block
switchSession (/resume, RPC reload) updates the manager's roots from
the target header but never rebuilt the base system prompt. The next
turn would see the previous session's stale <workspace-roots> block
until an unrelated prompt rebuild happened.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 03:09:41 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 00fd98729a Make parent live root list authoritative for subagents, CLI merge stays in buildSessionOptions
- main.ts:buildSessionOptions now merges --add-dir with settings
  before passing to options.additionalDirectories
- sdk.ts: when options.additionalDirectories is explicitly provided,
  uses it as-is (no settings re-merge); falls back to settings only
  when not provided
- This prevents removed roots from being re-seeded in subagent sessions

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 03:01:10 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 6c15874d15 Clear workspace.additionalDirectories setting for isolated worktree subagent runs
Setting options.additionalDirectories to undefined wasn't enough:
createAgentSession also merges settings.get('workspace.additionalDirectories').
Now createSubagentSettings gets an override to clear the setting
when worktree is set, ensuring isolated runs can't edit outside the
worktree.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 02:52:42 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 2fa43ad5a6 Omit additionalDirectories for isolated (worktree) task runs
Isolated tasks clone only cwd into the worktree. Forwarding the
parent's additional directories would let the subagent edit absolute
paths under the original extra roots, bypassing isolation. Now
additionalDirectories is undefined when worktree is set.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 02:44:56 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> ffe50650e1 Propagate workspace roots into subagent sessions
Subagents (task tool) now inherit the parent session's
additionalDirectories via ToolSession → ExecutorOptions →
CreateAgentSessionOptions, so delegated agents see the same
<workspace-roots> block and can read/grep/glob added roots.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 02:36:38 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> c24cb606a8 Normalize additionalDirectories in #resetToNewSession through normalizeSessionWorkspace
Relative paths in workspace.additionalDirectories settings (e.g.
'../shared') were stored raw in the new-session header instead of
being expanded to absolute. Now all new-session roots go through the
same normalizer used at startup.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 02:25:03 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 33e1857a1d Centralize additional-root seeding in SessionManager.newSession
- Add additionalDirectories to NewSessionOptions
- #resetToNewSession now seeds #additionalDirectories from options,
  so all new-session transitions (handoff, branch, /new) get the roots
- AgentSession.newSession passes settings dirs via options instead of
  calling setAdditionalDirectories after the fact

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 02:14:51 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> bff14d121d Copy additionalDirectories in createBranchedSession and normalize fork roots against target cwd
- createBranchedSession (/branch, /btw) now copies additionalDirectories
  to the new header so branches preserve multi-root state
- forkFrom filters source additionalDirectories against the target cwd
  so the new cwd is never also listed as an additional root

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 02:04:05 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> aa15496d29 Await providedWorkspaceTree when it's a Promise before merging root agentsMdFiles
Fixes a crash: createAgentSession passes workspaceTreePromise (a
Promise) as providedWorkspaceTree. The merge path accessed
primary.agentsMdFiles without awaiting, rejecting the system-prompt
prep and falling back to an empty tree.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 01:55:29 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 1704e3fd5a Normalize additional dirs on /move and discover nested AGENTS.md from added roots
- Filter #additionalDirectories when moveTo changes cwd so the new cwd
  is never also listed as an additional root (session-manager.ts)
- Build workspace tree for each additional root to discover nested
  AGENTS.md files under added roots, merging agentsMdFiles into the
  primary set (system-prompt.ts)

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 01:47:46 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 25761276bb Merge CLI --add-dir roots with settings roots instead of skipping settings
When --add-dir is provided, settings.get('workspace.additionalDirectories')
was skipped entirely. Now both sources are merged so configured default
roots apply to every session even when CLI adds a one-off root.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 01:38:27 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> e0e7eb4a3b Refresh base system prompt after /new and use top-level os import in tests
- Call refreshBaseSystemPrompt() after newSession so the
  <workspace-roots> block reflects the new session's directory set,
  not the previous session's stale roots (agent-session.ts)
- Replace inline require('node:os') with top-level import * as os
  in test file, following repo convention

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 01:30:21 -03:00
roboomp d30c5e8603 fix(settings): cleared persisted pending role writes
Serialize queued global saves and remove opportunistically persisted roles from the pending set after a successful write when their value has not changed again. This prevents a redundant follow-up save from replaying stale local values over newer external edits.

Expanded the locked-save regression to externally change the same role after the first write and verify flush leaves that newer disk value intact.
2026-07-22 04:27:25 +00:00
maatheusgois-ddandoh-my-pi <https://omp.sh> d3777e778d Restore additionalDirectories on failed session switch rollback
restoreState() now syncs #additionalDirectories from the captured
snapshot header, so a failed switchSession (e.g. from a session_switch
hook or model-restore error) doesn't leave the original session with
the target's workspace roots.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 01:20:48 -03:00
roboomp 640249ef33 fix(settings): preserved role writes during pending saves
Snapshot model roles when each save starts and merge any newer pending values before replacing the in-memory global settings. This keeps a second model switch intact while an earlier locked save is in flight.

Added a deterministic regression test that blocks the first file-lock operation, changes another role, and verifies both memory and disk.
2026-07-22 04:19:35 +00:00
maatheusgois-ddandoh-my-pi <https://omp.sh> ab0c25e058 Fix 2nd-round AI review: context files for all roots, merge on resume, fork copies roots
- Always augment context files with additional root context, even when
  createAgentSession passes preloaded contextFiles (system-prompt.ts)
- Merge configured dirs with existing restored roots on resume instead
  of replacing them (sdk.ts)
- Copy additionalDirectories from source header in forkFrom so forks
  preserve the multi-root set (session-manager.ts)
- Add test for forkFrom preserving additionalDirectories

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 01:14:13 -03:00
roboomp 14a8b709cc fix(settings): merge global model roles per-role on save
Global setModelRole marked the whole modelRoles path modified and
saveNow overwrote the freshly re-read disk record with the stale
in-memory map, clobbering concurrent/external per-role edits despite
the re-read intended to preserve them. Track modified global roles
individually and merge only those into the re-read file, mirroring the
project save path.

Fixes #6260
2026-07-22 04:09:55 +00:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 0a4ca2fe20 Load project context files for all workspace roots, not just cwd
When additional workspace directories have their own AGENTS.md/rules,
the agent now discovers and injects those context files alongside the
primary cwd's context. This prevents the agent from editing under a
root without seeing the rules that apply there.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 01:06:55 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 48381f0e98 Fix AI review findings: settings on initial launch, /new root leak, persisted roots on resume, consistent ~ normalization, dead exports
- Seed workspace.additionalDirectories settings on initial launch session,
  not just /new (sdk.ts)
- Always call setAdditionalDirectories on /new, even with empty list, to
  clear stale roots from the previous session (agent-session.ts)
- Make setAdditionalDirectories async and trigger atomic rewrite when a
  session file already exists, so --continue --add-dir persists (session-manager.ts)
- Route addWorkspaceDirectory/removeWorkspaceDirectory through
  normalizeWorkspaceDirectory for consistent ~ expansion (session-manager.ts)
- Drop dead exports: workspaceRootForPath (no production callers),
  getWorkspace (no production callers), and unused SessionWorkspace type
  import from session-manager.ts (session-workspace.ts, session-manager.ts)
- Remove unnecessary as SettingPath / as string[] casts (agent-session.ts)
- Update tests: add ~ expansion coverage, root-clearing on /new,
  persistence on resumed sessions, fix header line parsing

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-22 00:58:02 -03:00
maatheusgois-ddandoh-my-pi <https://omp.sh> 32d8b84e26 Add dynamic multi-root workspace context (#2569)
A session now carries an ordered list of workspace directories beyond cwd,
managed live from the terminal. New /add-dir, /remove-dir, and /dirs slash
commands let you add and remove folders mid-session; the repeatable --add-dir
CLI flag seeds them at launch, and the workspace.additionalDirectories
setting persists defaults per project. Additional roots are persisted in the
session header, survive reopen/fork/move, and are surfaced to the agent in the
system prompt so it knows they exist and can read/grep/glob them by absolute
path. Design aligns with the endorsed community implementation on
feature/session-workspace.

Co-authored-by: oh-my-pi <https://omp.sh>
2026-07-21 23:38:32 -03:00
roboomp 615d3c6dc5 fix(session): persisted terminal empty error turns ending the run
A non-retriable provider error on the continuation turn after a failed
tool result ended the run, but #persistSessionMessageIfMissing dropped
the empty error turn as reload poison, so the session JSONL stopped at
the last tool result and the provider errorMessage was lost with no
durable record of why the run stopped. When retry, model fallback, and
compaction all decline the turn, the non-retry terminal error tail now
persists it via the same helper the retry-lifecycle dead-ends use; the
empty turn stays off the wire on reload via the transform-messages
empty-assistant filter, matching the existing retry-exhaustion path.

Fixes #6249
2026-07-22 02:29:05 +00:00
roboomp 040c1d5891 fix(extensibility): validated unsafe schemas at runtime
Used the shared JSON Schema validator for Type.Unsafe so direct safeParse calls and composed shim schemas reject invalid values while preserving valid input identity.

Added direct and composed runtime regression assertions.
2026-07-21 22:42:09 +00:00
roboomp 04179bf0b8 fix(mcp): route task proxies through source tool and mark tools non-strict
MCP-backed tools never declared an explicit strict value, so OpenAI-family
serializers (post-#4336/#4340) had no false to preserve and models over-filled
mutually exclusive optional fields. Task/subagent proxies also rebuilt a raw
tools/call instead of executing through the source MCPTool, bypassing intent
stripping, placeholder pruning, local-URL resolution, reconnect, abort, and
result metadata; strict servers rejected proxied calls with
unrecognized_keys ["i"].

- MCPTool/DeferredMCPTool now declare `readonly strict = false as const`.
- createMCPProxyTools delegates to the current source tool, re-resolved by raw
  MCP server/tool metadata so reconnect replacements are honored, and keeps the
  Task 60s timeout by combining its abort signal with the caller's.
- Regression coverage: strict flags, proxy parity for i/placeholder shaping,
  declared-i passthrough, and reconnect re-resolution.

Fixes #6208
2026-07-21 22:37:12 +00:00
roboomp 49e63c1f2c fix(extensibility): added Type.Unsafe to typebox shim
Preserved raw JSON Schema documents while keeping the shim validator identity-based, allowing provider wire conversion and runtime argument validation to consume MCP input schemas.

Added direct shim and remapped-extension regression coverage.

Fixes #6221
2026-07-21 22:34:44 +00:00
roboomp b2e7e34567 fix(write): let conflict:// writes reach the resolver
- Exempted the handler-less conflict:// scheme from the URI-like guard so parseConflictUri still splices registered blocks.
- Extended the near-miss regression to assert conflict://1 reaches the resolver.

Fixes #6123
2026-07-21 22:33:33 +00:00
roboomp 27b0d1722b fix(tui): locked plan review overlay after a choice commits
The fullscreen Plan Review overlay stayed mounted, focused, and fully
interactive after a choice was picked. showPlanReview's finish() resolves
the choice promise but deliberately defers the hide until #approvePlan
(guarded for #5688/#5319/#5689), so during slow async approval work — e.g.
context compaction — arrow keys still moved the cursor and repeat
Enter/Esc were silently swallowed by the settle guard, with the
fullscreen buffer masking all progress underneath. Users on Ghostty and
macOS Terminal read this as "/plan is frozen".

The overlay now flips to a committed state the moment a choice fires:
handleInput is a no-op, and the render shows a "<choice> — submitting…"
indicator plus an "applying your selection" footer. The deferred-hide
timing is untouched, so the existing stale-buffer and focus guards stay
intact.

Fixes #5926
2026-07-21 22:21:35 +00:00
roboomp d0f1cd1b77 fix(git): degrade gracefully when git binary is missing
The read-only git helpers spawned `git` directly and only inspected the
result exit code. When git is absent from PATH, Bun's spawn throws ENOENT
(uv_spawn 'git') at launch, which escaped as an unhandled rejection and
crashed the process (e.g. Windows without git, relying on WSL git).

Translate a missing-binary launch failure into a non-zero GitCommandResult
in the async git() wrapper and into a null degrade in the sync reftable ref
readers, matching the existing non-zero-exit handling. Mutating/checked
commands keep surfacing the clean "git is not installed." error.

Fixes #6169
2026-07-21 22:07:42 +00:00
roboomp ee9c08a5c1 fix(session): log provider turn errors at warn with error fields
The agent_end handler only recorded stopReason/provider/model at debug and dropped errorMessage/errorStatus/errorId, so a session dying repeatedly on provider stream failures left no actionable trace in the main log. Extract logProviderTurnError and emit one warn-level entry carrying provider, model, errorMessage, errorStatus, and errorId when a turn ends in stopReason:error.

Fixes #6177
2026-07-21 22:06:57 +00:00
roboomp b3ec980da4 fix(coding-agent): embedded changelog in standalone binaries
Bundled the release history as a fallback when package assets cannot be resolved, while preserving external package-directory overrides.

Added regression coverage for the compiled-binary fallback.

Fixes #6172
2026-07-21 22:06:46 +00:00
roboomp 451ad31cc0 fix(sdk): resolve configured default role over cold-cache discovery race
On a cache-cold interactive launch, a modelRoles.default pointing at a
models.yml discovery provider (openai-models-list) was silently replaced
by an unrelated authenticated provider's default. createAgentSession
resolves the default role before background discovery populates the
catalog, so the configured provider had no models yet and the fallback
fell through to pickDefaultAvailableModel.

Await one cache-aware discovery pass and re-resolve the configured
default whenever it is still unresolved (not only when nothing resolved
at all) before accepting a bundled-provider fallback.

Fixes #6162
2026-07-21 21:58:35 +00:00
roboomp 62b47dede8 fix(cli): preferred authenticated provider for bare models
Made startup resolution rank configured providers before catalog-only matches while preserving explicit provider pins and catalog fallback behavior.

Added regression coverage for shared bare model IDs across authenticated and unauthenticated providers.

Fixes #6150
2026-07-21 21:50:36 +00:00
roboomp 48a7287c68 fix(coding-agent): replayed commits over dirty parent
- Seeded dirty-baseline blobs into the parent object database before reconstructing filtered agent commits.
- Used three-way synthetic-tree application for committed and trailing task state while preserving parent WIP.
- Added a focused merge regression covering unrelated edits in the same tracked file.

Fixes #6135
2026-07-21 21:34:27 +00:00
roboomp 7c96386e29 fix(session): skipped stop hooks during aborts
Short-circuited session_stop emission when an abort or disposal is already in progress, avoiding extension work whose result cannot be used.

Added deterministic coverage for an abort racing the final settle pass.

Fixes #6134
2026-07-21 21:31:46 +00:00
roboomp 050aec7632 fix(coding-agent): make hindsight request timeouts per-op and configurable
The single 30s hang-guard from #4290 (sized for metadata fetches per #4229)
wrapped every Hindsight op including reflect, an agentic retrieve+synthesize
call whose healthy latency routinely exceeds 30s, so ordinary successful
reflects were aborted client-side.

- Give HindsightApi per-op deadlines with sensible defaults (reflect 120s,
  retain 60s, recall/request 30s) plus a HindsightTimeouts option bag.
- Report the effective seconds in the timeout error instead of a hard-coded
  "after 30s".
- Add hindsight.requestTimeoutMs / reflectTimeoutMs / recallTimeoutMs /
  retainTimeoutMs settings and matching HINDSIGHT_*_TIMEOUT_MS env vars.
- Preserve caller-abort merging via withTimeoutSignal.

Fixes #6125
2026-07-21 21:26:11 +00:00
roboomp ea5c816e65 fix(write): rejected unknown uri-like targets
- Blocked malformed and unregistered URI-like paths before filesystem resolution.
- Suggested canonical xd:// spelling while preserving explicitly escaped local paths.
- Added regression coverage for xdt://, xd:/, and xd/ near misses.

Fixes #6123
2026-07-21 21:19:53 +00:00
roboomp 013f70c7d7 fix(tts): prioritized playback interruption on escape
- Moved active playback cancellation ahead of ongoing loop and stream interruption.

- Added an overlapping TTS and agent-turn regression.

Fixes #6118
2026-07-21 21:13:45 +00:00
roboomp 1cf4831c9c fix(tui): surfaced provider errors above plan review
- Dismissed the fullscreen plan review and settled its pending choice when a turn-ending provider error is pinned.
- Added regression coverage for restored editor focus and visible error presentation.

Fixes #6086
2026-07-21 21:09:17 +00:00
roboomp c0966d0f64 fix(prompting): preserved absolute working directory
Removed display-only home shortening from the provider-facing project prompt and covered home-relative project paths with a regression test.

Fixes #6100
2026-07-21 21:07:11 +00:00
jiwangyihao ad32548087 fix(coding-agent): 修复 HTML 导出深树栈溢出
将树排序和活动路径标记改为迭代遍历,避免有效深层会话耗尽浏览器调用栈。
2026-07-22 05:06:15 +08:00