Commit Graph
9400 Commits
Author SHA1 Message Date
can1357 1088ee2127 Merge PR #7203: fix(tui): render mid-turn steering skips as info, not errors (@roboomp) 2026-08-01 20:14:40 +02:00
can1357 61d066bd2a Merge PR #6756: fix(coding-agent): suppress WIP advisor non-blockers (@wolfiesch) 2026-08-01 20:14:39 +02:00
can1357 60d5b9b49d fix(coding-agent): classify host before auth storage 2026-08-01 20:13:40 +02:00
can1357 b6e12240c9 Merge PR #7240: fix(coding-agent): bound synchronous SQLite busy-waits in headless hosts (@pi3123) 2026-08-01 20:13:39 +02:00
can1357 539e7277d0 fix(session): fence title updates during moves 2026-08-01 20:13:39 +02:00
can1357 6948d34573 Merge PR #7271: fix(session): fence appends during session moves (@roboomp) 2026-08-01 20:13:39 +02:00
can1357 890dc0c55d Merge PR #7195: fix(coding-agent): omit unsupported Anthropic search temperature (@will-bogusz) 2026-08-01 20:13:38 +02:00
can1357 237aa46faf fix(coding-agent): refreshed repo context after cwd changes 2026-08-01 20:13:38 +02:00
can1357 93a9f0d991 Merge PR #7262: fix(coding-agent): refresh context files on plugin reload (@roboomp) 2026-08-01 20:13:38 +02:00
can1357 5e819172a5 Merge PR #7285: fix(coding-agent): preserve explicit extensions in isolation (@alphastorm) 2026-08-01 20:13:38 +02:00
can1357 4a83ea86fc Merge PR #7107: feat(mcp): let a server opt into integer JSON-RPC request ids (@kodlian) 2026-08-01 20:13:38 +02:00
can1357 efc515d77c Merge PR #7251: fix(memory): clarify /memory stats and /memory diagnose message when memory is off (@KennethHoff) 2026-08-01 20:13:37 +02:00
can1357 6cf01fe5dc fix(keybindings): preserve explicit shift-up remaps 2026-08-01 20:13:37 +02:00
can1357 aaeb14c850 Merge PR #7149: feat(keybindings): accept shift+up for the steering dequeue (@metaphorics) 2026-08-01 20:13:37 +02:00
can1357 401ff44f08 Merge PR #7202: fix(agent): route codex v2 compaction through websockets (@roboomp)
# Conflicts:
#	packages/ai/src/providers/openai-codex-responses.ts
2026-08-01 20:13:28 +02:00
Sunil Srivatsa f22c0edbfa fix(coding-agent): scope SDK extension packages 2026-08-01 13:50:53 -04:00
Sunil Srivatsa df38e5b48e fix(coding-agent): rebind relative extension roots 2026-08-01 13:24:11 -04:00
Sunil Srivatsa b1a46eec5c fix(coding-agent): ignore unreadable hook dirs 2026-08-01 13:15:19 -04:00
roboomp 8378d523ce fix(collab): converted guest prompts in side requests
Routed direct custom-message conversion through the collab steering transform so side requests and compaction see the same enveloped user turn as primary requests.

Extended the regression test to exercise convertToLlm without transformContext.
2026-08-01 17:10:36 +00:00
Sunil Srivatsa 5d8a2d6b82 fix(coding-agent): scope explicit hook discovery 2026-08-01 13:04:04 -04:00
roboomp 352c0fdce2 fix(collab): treated guest prompts as user interjections
Converted user-attributed collab prompt frames to prioritized user messages only on the model-facing path, preserving guest details in persisted transcript frames.

Added regression coverage for the provider role, steering envelope, and retained guest attribution.

Fixes #7288
2026-08-01 17:04:00 +00:00
Sunil Srivatsa 8a7edb3f3d fix(coding-agent): preserve explicit extensions in isolation 2026-08-01 12:32:19 -04:00
roboomp dd0972456d docs(session): clarify move flushSync durability caveat
The move fence intentionally defers a flushSync landing in the rename window; full synchronous durability there is incompatible with orphan-avoidance for a rename-based, Windows-safe move. Document the caveat honestly instead of implying parity with the in-place rewrite path.

Refs #7270
2026-08-01 14:07:41 +00:00
roboomp 8f4e58edd2 fix(session): fence session moves without canceling queued rewrites
The move fence bumped #diskEpoch, which no-oped any disk task already queued at the prior epoch (e.g. a header-only ensureOnDisk materializing rewrite), losing explicitly materialized ACP/draft sessions. Gate the append hot path on #sessionFileRelocating instead of a fresh epoch, so prior disk work still drains.

Fixes #7270
2026-08-01 13:56:30 +00:00
roboomp f3fda5139d fix(session): fence flushSync during session moves
A fenced append followed by a Ctrl+C flushSync in the post-rename, pre-repoint window rewrote the full body to the old path, recreating the orphan. Sync rewrites now defer while the session file is relocating.

Fixes #7270
2026-08-01 13:47:58 +00:00
roboomp ea265df009 fix(session): fenced appends during session moves
Prevented synchronous session appends from reopening the vacated source path while moveTo relocates and repoints the journal.

Fixes #7270
2026-08-01 13:39:51 +00:00
roboomp 55115f4bfd fix(coding-agent): refresh advisor context prompt on reload
Rebuilt advisor runtimes with the rediscovered context files so advisor turns stop evaluating against stale AGENTS.md instructions after /reload-plugins.

Fixes #7258
2026-08-01 11:46:55 +00:00
roboomp 08c80f7da0 fix(coding-agent): scope context rediscovery to session settings
Threaded the session's disabledExtensions into context-file rediscovery so a concurrently-created session's global settings cannot toggle another session's context entries.

Fixes #7258
2026-08-01 11:36:34 +00:00
roboomp 2b268b4d2c fix(coding-agent): refreshed context files on plugin reload
Rediscovered context files from the active session cwd whenever plugin prompt sources refresh, while preserving explicitly preloaded SDK context.

Covered edited and disabled context files in the current system prompt.

Fixes #7258
2026-08-01 11:27:03 +00:00
Kenneth Hoff c3a72e026e fix(memory): mirror off-backend message in ACP /memory stats|diagnose
The TUI's CommandController special-cased backend.id === "off" for
/memory stats|diagnose, but the ACP/RPC slash-command handler in
builtin-registry.ts still fell back to the generic "not available for
the off backend" template — non-TUI users with memory.backend=off saw
the self-contradictory wording this PR was meant to remove.

Extract the shared fallback into memoryStatsUnavailableMessage()
(memory-backend/messages.ts) and use it from both CommandController
and the ACP builtin-registry handler, so the two surfaces can't drift
again.

Addresses review comment:
https://github.com/can1357/oh-my-pi/pull/7251#discussion_r3695383090
2026-08-01 12:12:57 +02:00
Kenneth Hoff 7d0b8cf8dc fix(memory): clarify /memory stats and /memory diagnose message when memory is off
/memory stats and /memory diagnose fall back to a generic
'Memory <action> is not available for the <backend.id> backend.'
message whenever the active backend's stats/diagnose hook is
undefined. For every real backend (hindsight, mnemopi, local) this
reads fine, but the off backend isn't a backend a user picked among
several stats-capable options - it's the no-op state memory falls
back to by default - so the same template renders as 'Memory stats
is not available for the off backend.', which reads as an odd,
almost self-contradictory warning.

Special-case backend.id === "off" with wording that matches the
phrasing offBackend.status() already uses elsewhere ('Memory backend
is off.'), and add a unit test covering both the off-backend wording
and the unchanged generic fallback for a real backend (local) that
simply has no stats hook.

The regression test only asserts on a mocked showWarning call and
never renders Markdown, so it doesn't need a real theme instance;
drop the global dark-theme setup/teardown to avoid leaving the
process-wide theme singleton mutated for later suites in the same
Bun process.
2026-08-01 11:58:50 +02:00
can1357 f94c8809e5 Merge remote-tracking branch 'origin/farm/101aa6fd/codex-search-preserve-sse-error' 2026-08-01 08:33:48 +02:00
can1357 126c3804e3 Merge remote-tracking branch 'origin/farm/41d773e1/ask-dialog-question-undefined-crash' 2026-08-01 08:33:30 +02:00
can1357 03f5eb7acf Merge remote-tracking branch 'origin/farm/c5198f90/fix-effective-prompt-cache-key' 2026-08-01 08:33:25 +02:00
can1357 2b8546faa0 Merge remote-tracking branch 'origin/farm/8f2adac9/bash-auto-background-clearable-timer' 2026-08-01 08:33:11 +02:00
can1357 ad78b6a84e feat(coding-agent/tools): implemented shared browser daemon management
- Added `ensureSharedBrowser` and shared browser acquisition to manage project-shared broker-owned Chromium instances.
- Implemented concurrent duplicate daemon start prevention and single-flight `pendingOpens` deduplication.
- Updated browser handle disposal to disconnect from shared daemons rather than closing them.
- Updated browser documentation and launch specifications to support shared and local headless runs.
2026-08-01 08:30:05 +02:00
pi3123 4a9350963f Hoist interactive-host flag above settings load; add changelog entries
Settings.init opens agent.db/stats.db before setInteractiveHost ran, so
interactive hosts received the 1000ms headless busy timeout on those
databases (issue #2421 class). Declare the flag before settings load and
add [Unreleased] changelog entries per repo conventions.
2026-07-31 23:27:15 -07:00
roboomp fe4e553be3 fix(coding-agent): clear bash auto-background threshold timer
waitForManagedBashJob raced job completion against a bare
Bun.sleep(thresholdMs), which cannot be cancelled. When completion,
abort, or steering won the race, the losing Bun.sleep timer stayed
scheduled and ref'd, keeping Bun's event loop alive until the threshold
expired — delaying SDK/headless shutdown and accumulating timers under
fast command rates.

Replace the Bun.sleep with a Promise.withResolvers settled by a
cancellable setTimeout, and route every outcome (including the former
no-signal early return) through one try/finally that clears the timer
and removes the abort/steer listeners.

Add a child-process regression test that runs the real auto-background
path for a fast command against a 30s threshold and asserts the process
exits promptly instead of being held for the full threshold.

Fixes #7235
2026-08-01 05:14:43 +00:00
roboomp 838d120249 fix(coding-agent): reused effective prompt cache key
- Reused the agent's explicit or inherited cache identity for ephemeral side turns.
- Forwarded the same effective key through manual and automatic native compaction.
- Added regression coverage for all three secondary request paths.

Fixes #7218
2026-08-01 03:44:59 +00:00
pi3123 edb3feda9b Bound synchronous SQLite busy-waits in headless hosts
Headless hosts (print/RPC/ACP/eval/SDK) run the agent loop on the same
thread as bun:sqlite, so a lock-contention busy-wait of the interactive
5s timeout freezes the protocol loop for seconds at a time with no
liveness signal. Use a 1s busy_timeout for session-critical databases
(agent.db, history.db, stats.db) when the host is not interactive, and
let the existing asynchronous open/retry paths recover from contention.
2026-07-31 19:59:48 -07:00
roboomp 8a059e3027 fix(coding-agent): normalize ask dialog questions to prevent render crash
The live AskDialog trusted question.question while its render helpers
(replaceTabs, renderQuestionTitle, questionTabLabel) assume a string. A
question reaching AskDialogComponent without a string question field threw
an uncaught TypeError that escaped the TUI render loop and killed the
session. The transcript renderer already normalizes the same malformed
data via normalizeRenderQuestions; the live path did not.

Normalize the questions array at dialog entry (new normalizeDialogQuestions),
coercing question/id/label to strings and options to a well-formed array,
matching the transcript path.

Fixes #7211
2026-08-01 00:11:21 +00:00
roboomp af343f70d0 fix(agent): distinguished started steering aborts
Track entry into tool.execute separately from tool event emission. Never-started skips retain SyntheticToolResultDetails with executed:false; in-flight aborts now use distinct interrupted metadata with execution:started so consumers do not assume no partial work occurred.

Keep both interrupt states neutral in the TUI and cover the agent metadata boundary plus rendering behavior.

Fixes #7199
2026-07-31 21:16:28 +00:00
roboomp ebd84d4f85 fix(tui): render mid-turn steering skips as info, not errors
A tool call aborted mid-batch to service queued steering/peer input emits a synthetic placeholder result with isError:true so the model retries it. The TUI keyed all error styling (red ✘, red frame/text) off that flag, so a normal steering skip rendered identically to a real tool failure.

Mark the skip placeholder with the existing SyntheticToolResultDetails discriminator (source: "interrupt_skipped", executed:false) and render benign skips through the neutral generic card (info glyph, dim text, neutral background), bypassing any bespoke error frame. Genuine failures keep their error styling.

Fixes #7199
2026-07-31 21:06:07 +00:00
roboomp 5283c4c99b fix(agent): routed codex v2 compaction through websockets
- Reused the live Codex provider session for WebSocket-first V2 compaction.
- Fell back to SSE V2 on WebSocket transport failure before the existing V1 fallback.
- Propagated the configured WebSocket preference through manual, automatic, and advisor compaction paths.
- Added transport reuse and fallback regression coverage.

Fixes #7198
2026-07-31 21:00:15 +00:00
roboomp d4cb024b57 fix(coding-agent): preserve codex web search backend error diagnostics
The Codex SSE `type:"error"` branch read only top-level `code`/`message`,
so backend rejections emitted under a nested `error` or `response.error`
object collapsed to `Codex error (): Unknown error`, hiding the cause
(e.g. a regional/model-snapshot rejection). `response.failed` similarly
dropped the error code.

Add a shared `extractCodexSseError` that reads top-level, nested `error`,
and `response.error` envelopes, and wire both error paths through it so
the backend code and message survive in `SearchProviderError`. The
existing `web_search_call` requirement is untouched.

Fixes #7200
2026-07-31 20:56:54 +00:00
Will e3f66975e9 fix(coding-agent): omit unsupported search temperature 2026-07-31 16:38:02 -04:00
Jérémy Marchand 4476940a4a docs(mcp): document requestIdFormat as OMP-specific
The option only exists in OMP's own config format, so the OMP-owned discovery
providers are the only ones that parse it. Say so in the schema description, the
MCPServerConfigBase doc, and the changelog, and name the config paths where
setting it actually takes effect, so nobody expects a server imported from
another tool's config to honor it.
2026-07-31 21:04:02 +02:00
Jérémy Marchand c676bbb81b fix(mcp): honor requestIdFormat in OMP plugin MCP configs
OMP plugins ship their own .mcp.json, and that provider whitelists fields into
the canonical MCPServer shape the same way the other loaders do, so a plugin
bundling an integer-only server could set requestIdFormat and still have it
dropped before it reached a transport.

Extract the value parsing into parseRequestIdFormat() next to parseBoolean() in
discovery/helpers.ts and use it from all three OMP-owned loaders (native,
standalone mcp.json, omp-plugins), replacing the two hand-rolled copies.

Vendor providers (claude, claude-plugins, cursor, vscode, gemini, opencode,
windsurf) are deliberately untouched: they translate another tool's own server
list, where an OMP-specific key has no meaning.
2026-07-31 21:03:06 +02:00
Jérémy Marchand 0a1b8e35b8 fix(mcp): include requestIdFormat in connection-equivalence dedup
Discovery collapses differently-named MCP entries that point at the same
command/args/env/cwd (or url/headers) into one connection, keeping whichever
loaded first and dropping the rest as aliases. requestIdFormat changes the bytes
sent on the wire, same as auth/oauth which the comparator already covers, so a
higher-priority alias lacking the field could shadow a lower-priority entry that
set it, silently falling back to string ids for a server that needs numbers.

Add requestIdFormat to isSameMCPConnection, normalized against its own default so
an explicit "string" is not treated as a different connection than leaving it
unset. timeout stays excluded, since it is a client-side knob that never touches
the wire.
2026-07-31 21:03:06 +02:00
Jérémy Marchand 3cb6e5df9c fix(mcp): carry requestIdFormat through MCP config discovery
The option was only present on the transport-facing `MCPServerConfig`, so a
value written in `.omp/mcp.json` or a standalone `.mcp.json` never reached the
transports: discovery normalizes config into the canonical `MCPServer` shape and
`convertToLegacyConfig()` rebuilds the transport config from it, and neither step
knew about the field. Setting `"number"` in the documented config path silently
kept the snowflake-string default, which is the hang the option exists to avoid.

Wire it through the same four places `timeout` already uses: the canonical
`MCPServer` shape, the two OMP-native loaders (with validate-and-warn on an
unrecognized value), and the legacy conversion. Foreign-format providers are
untouched, since the key is OMP-specific.

Also point the `MCPServerConfigBase` doc comment at `RequestIdAllocator` rather
than a helper name that never existed.
2026-07-31 21:03:06 +02:00