Commit Graph

2890 Commits

Author SHA1 Message Date
roboomp 929ab1a20f fix(coding-agent): allowed retries for buffered print output
Made text replay safety depend on whether the active output sink has committed streamed text.

Kept tool calls, images, and server tools replay-unsafe while covering text and JSON print policies plus a transient socket-close recovery.

Fixes #7625
2026-08-04 13:50:09 +00:00
Slava Zavadsky 84922eca22 Merge remote-tracking branch 'upstream/main' into fix/7443-streaming-message-update-coalesce 2026-08-04 07:29:25 -04:00
Kyle McCleary 91467c2f27 fix(coding-agent): restore Agent Hub lineage metrics 2026-08-03 19:42:11 -07:00
Kyle McCleary 8f1de61e9f refactor(coding-agent): densify Agent Hub metrics 2026-08-03 19:42:11 -07:00
Kyle McCleary c30ca0b157 refactor(coding-agent): preserve Agent Hub history 2026-08-03 19:42:11 -07:00
Kyle McCleary bda330bb13 refactor(coding-agent): add Agent Hub inspector 2026-08-03 19:42:11 -07:00
Kyle McCleary 4fb3ecd69a refactor(coding-agent): polish agent hub menu 2026-08-03 19:42:11 -07:00
can1357 bc39ffa265 feat: introduced omptype validation package and migrated workspace dependencies
- Introduce `@oh-my-pi/omptype` as a new ArkType-compatible schema validation package featuring a lazy JIT runtime, JSON Schema emission, and compatibility adapters.
- Replace `arktype` across workspace packages and test utilities with `@oh-my-pi/omptype`.
- Add benchmark suites, tests, and documentation for the new validation engine and adapters.
- Update workspace build, test runner, and release configurations to include the new package.
2026-08-03 21:56:48 +02:00
Slava Zavadsky 84813ad37a fix(coding-agent): handle timer-triggered message update flush rejections (#7443) 2026-08-03 14:14:07 -04:00
Slava Zavadsky fed51f1ffc fix(coding-agent): coalesce streaming message_update handler work per render window (#7443) 2026-08-03 14:06:48 -04:00
Brent db97103c32 fix(coding-agent): complete usage-aware fallback integration 2026-08-03 16:34:35 +00:00
can1357 a418920ec1 feat: made /reset semantically different
Closes #4447
2026-08-03 15:46:46 +02:00
can1357 267856deb8 Merge PR #7475: fix(session): prevent stale /btw branch promotion (@roboomp) 2026-08-03 15:12:03 +02:00
hancens e388bc14ce perf(agent-hub): bound roster rendering to viewport
Agent Hub previously pre-rendered every registry row and resolved each
row's observer via getSessions().find, which copy-sorts the full observer
map. On large rosters that made open/selection/age-tick O(all rows) and
observer lookup near O(N^2 log N).

- Add SessionObserverRegistry.getSession(id) for O(1) Map lookup
- Lazy-render hub rows around the selection within the terminal line budget
- Keep ordering, selection, status counts, overflow, badges, and task lines
- Add 10k-row regression covering bounded getSession/render work
2026-08-03 21:09:45 +08:00
can1357 d2fe1b212b style: applied biome formatting to input-controller 2026-08-03 14:51:52 +02:00
can1357 d46c58b5c8 fix(tui): clear extension command image drafts 2026-08-03 14:46:24 +02:00
Aleksandr Khaustov 276ff92afe fix(tui): consume extension slash commands locally 2026-08-03 14:02:05 +04:00
roboomp a54a2f79cb fix(tui): preserved b before /btw completion
Reserve the plain b shortcut only after /btw has a completed answer or a branch is already pending. Running, empty, aborted, and failed panels now leave the key for the composer, while completed-but-refused branches still consume it with an explanation.

Fixes #7474
2026-08-03 09:33:07 +00:00
roboomp 98f484bd2f fix(session): validated session identity for /btw branch
Branched session files preserve entry ids, so leaf-id equality alone let a stale /btw answer promote into a different loaded session. Capture the originating session id at /btw start and require it to match at both the controller gate and every branchFromBtw checkpoint.

Fixes #7474
2026-08-03 09:22:32 +00:00
roboomp 7a1183da91 fix(session): prevented stale /btw branch promotion
- Passed the authorized leaf through the branch executor and revalidated it before rewriting history.
- Refused promotion during active turns and bounded post-prompt drains.
- Consumed unavailable branch keys while showing pending and refusal state in the panel.

Fixes #7474
2026-08-03 09:07:12 +00:00
can1357 5ad263f0a6 fix(tui): hid stripped-tool-call placeholder with tool activity
- The 'N tool calls elided' replay placeholder leaked tool activity while
  display.hideToolActivity was on; it is now a visibility-aware component
  wired into both the hotkey and /settings toggle paths.
- Added replay + live-reveal regression coverage.
2026-08-03 05:42:07 +02:00
can1357 03c07f89ec Merge PR #7342: feat(tui): add hidden tool activity mode (@dannyboy-ai) 2026-08-03 05:34:17 +02:00
Daniel Anderson-Little 4471a3f26d fix(tui): purge hidden tool images 2026-08-02 23:21:17 -04:00
Daniel Anderson-Little a20690a40b feat(tui): add hidden tool activity mode 2026-08-02 22:59:48 -04:00
roboomp c6a057073b fix(mcp): expand env vars in reauth oauth credentials and reject empty tokens
/mcp reauth read OAuth clientId/clientSecret from the raw, unexpanded config
while URL and resource used expandEnvVarsDeep, so `${VAR}` placeholders were
sent literally to the token exchange. MCPOAuthFlow.exchangeToken() also accepted
any HTTP-success body, storing an empty access token when a provider signals
failure with HTTP 200 (e.g. Slack `{ ok: false, error }`), surfacing only later
as invalid_token.

- Select flow client credentials from runtimeBaseConfig / expanded auth block;
  keep the raw placeholder for the persisted config file.
- Reject token responses without a non-empty access_token, including the
  sanitized provider error when present.
- Add regression tests for env-expanded reauth credentials and HTTP-200 token
  error bodies.

Fixes #7440
2026-08-03 00:33:36 +00:00
can1357 9b3e9a5d0e Merge PR #7126: feat(omp): navigate conversation turns in tree (@oleksoleksoleks) 2026-08-02 21:21:37 +02:00
can1357 73b834dcbc style: applied biome formatting to merged evaluator fixes 2026-08-02 21:01:20 +02:00
can1357 83e23a58e6 Merge PR #7387: fix(tui): keep working title across non-terminal agent_end (@roboomp) 2026-08-02 20:53:22 +02:00
can1357 81babef622 fix(coding-agent): avoid redundant faint sequence in status cap 2026-08-02 20:53:22 +02:00
can1357 7f20bafc03 Merge PR #7385: fix(coding-agent): keep focused status bar caps bright (@art-wiedzmin) 2026-08-02 20:53:21 +02:00
can1357 3de8c3a476 Merge PR #7344: fix(agent): stop leaking scout into prompts when it is disabled (@szavadsky)
# Conflicts:
#	packages/coding-agent/src/prompts/system/system-prompt.md
2026-08-02 20:52:56 +02:00
can1357 abebe8c2a8 Merge PR #7333: fix(tui): compact linear branch continuations (@roboomp) 2026-08-02 20:52:07 +02:00
roboomp 84135e9fed fix(tui): flush deferred model switch on non-terminal settle
The isTerminal:false early-return skipped #finishAgentEnd, the only site
that flushes a deferred plan-mode model switch, so an automatic continuation
(async wake) ran on the old model/thinking level until the terminal settle.
Flush the pending switch on the non-terminal branch before returning; the
title/loader teardown stays deferred to the terminal agent_end.
2026-08-02 12:24:01 +00:00
roboomp 4e4c5564c9 fix(tui): keep working title across non-terminal agent_end
EventController.#handleAgentEnd guarded only on session.isStreaming, so a
non-terminal agent_end (isTerminal:false, emitted while an async job will
re-wake the loop) flipped the terminal title to idle and tore down the
working loader while a /vibe worker or async bash job was still running.

Early-return on event.isTerminal === false, matching the guard every other
agent_end consumer already applies; the later terminal agent_end performs
the normal teardown.

Fixes #7386
2026-08-02 12:18:08 +00:00
art-wiedzmin 6f6d298e6e fix(coding-agent): keep focused status caps bright 2026-08-02 14:55:13 +03:00
Slava Zavadsky 9885ee34fc fix(agent): stop leaking scout into prompts when it is disabled
Hard-coded 'scout' references reached the model even when the scout
agent was disabled via task.disabledAgents or absent from the session
spawn list. Gate every such reference on scout actually being spawnable:
the task tool description, the delegation gates, the plan-mode and
workflowz notices, the glob/grep/ast-grep guidance, and the task
specialization advisory. Prompt shape is otherwise unchanged; only
erroneous references to the unavailable subagent are dropped.

Closes #7313
2026-08-01 23:50:33 -04:00
roboomp ca5504cae0 fix(tui): kept virtual-root children nested
- Advanced indentation for a virtual root's direct children so single-child roots no longer collapse to the shared column-0 root.

- Mirrored the fix in the HTML export renderer and added a multi-root regression.

Fixes #7332
2026-08-02 00:34:42 +00:00
roboomp f8b71b4a3c fix(tui): compacted linear branch continuations
- Kept single-child chains aligned with their branch head while preserving real branch depth.

- Removed disconnected terminal-branch anchors from TUI and HTML tree renderers.

- Updated nested tree regressions for compact connector alignment.

Fixes #7332
2026-08-02 00:27:41 +00:00
roboomp 3945b1b4af fix(tui): preserved loop after cancelling iteration
Kept /loop running when Esc aborts an active streamed turn. Idle Esc still pauses the loop and cancels a pending submission.

Fixes #7329
2026-08-02 00:00:25 +00:00
can1357 992963f949 feat(coding-agent): allowed switching to models smaller than session context with compaction
- Make over-context models selectable in the model picker by graying them instead of disabling them.
- Trigger automatic session compaction with the current model prior to switching when an over-context model is chosen.
2026-08-01 20:59:24 +02:00
can1357 cc884eea9b Merge PR #7252: fix(coding-agent): keep hub-killed subagent from resurrecting as parked (@roboomp) 2026-08-01 20:14:40 +02:00
can1357 3fd042c38b fix(coding-agent): preserve grouped reads during retraction 2026-08-01 20:14:40 +02:00
can1357 191872990e Merge PR #6881: fix(coding-agent): retract superseded turn's tool cards to stop double render (@roboomp) 2026-08-01 20:14:40 +02:00
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 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 aaeb14c850 Merge PR #7149: feat(keybindings): accept shift+up for the steering dequeue (@metaphorics) 2026-08-01 20:13:37 +02: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
roboomp 65fd8cb0e8 fix(coding-agent): keep hub-killed subagent from resurrecting as parked
The Agent Hub kill path called AgentLifecycleManager.release(), which
disposes the session and then unregisters the ref while leaving the
on-disk <id>.jsonl intact. On the next hub open, registerPersistedSubagents
rescans the transcript tree and its `if (!registry.get(id))` guard cannot
distinguish an explicit kill from a normally-parked agent, so it re-adopts
the killed id as a fresh `parked` row.

Add a `tombstone` option to release() that mirrors finalizeSubagentLifecycle's
genuine-kill path: dispose and detach the session but keep the ref registered
as terminal `aborted` instead of removing it. The kept-registered id makes the
rescan guard skip it, and the transcript stays on disk (still reachable via
history://<id>, per #5261). The hub kill button now passes tombstone: true.

Fixes #7250
2026-08-01 09:26:26 +00: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