Commit Graph
5772 Commits
Author SHA1 Message Date
can1357 c9715460d0 Merge remote-tracking branch 'origin/farm/a8779c95/windows-cmd-mcp-spawn' 2026-06-11 15:51:09 +02:00
can1357 be834e017a Merge remote-tracking branch 'origin/farm/bf519648/hashline-block-anchor-guidance' 2026-06-11 15:51:01 +02:00
can1357 0fa27b2afc Merge remote-tracking branch 'origin/farm/25da87c8/fallback-on-refusal' 2026-06-11 15:50:45 +02:00
can1357 5d3f22470d Merge remote-tracking branch 'origin/farm/752cbbfe/anthropic-search-metadata-user-id' 2026-06-11 15:50:17 +02:00
can1357 b0a5b8859d Merge remote-tracking branch 'origin/farm/ace32da7/tree-view-user-message-connectors' 2026-06-11 15:49:26 +02:00
roboomp dcf93a2ee9 feat(tui): added statusLine.transparent setting for terminal-native background
Status line painted theme.statusLineBg across the bar, which renders as
visible dark/black blocks on terminals (Ghostty, transparent themes,
custom palettes) whose background does not match the theme's hardcoded
status-line color. Powerline end caps inherited the same fill so they
also stood out against the surrounding terminal.

The new statusLine.transparent appearance setting (default off) routes
the bar to the terminal's default background via the existing empty-bg
sentinel (\x1b[49m) and drops the powerline end caps, which need a
contrasting fill to bridge into the terminal.

Theme authors can opt in per-theme by setting statusLineBg to '' — the
existing empty-string sentinel already resolves to the same ANSI escape
the new toggle uses.

Fixes #2306
2026-06-11 10:49:32 +00:00
roboomp 5e6f5bf66d fix(tui): scoped chain gutter extension to nearest branch
Only chain rows should force their nearest connector gutter back to vertical.
Inherited gutters from older last-sibling ancestors must stay suppressed so
linear continuations under nested branched grandchildren do not draw floating
vertical lines below unrelated branch connectors.

Updated the TUI renderer, mirrored the HTML export renderer, regenerated the
HTML template, and extended the #2298 regression to cover nested branched
grandchildren with linear continuations.

Fixes #2298
2026-06-11 10:26:20 +00:00
roboomp d40a136105 style: bun run fix 2026-06-11 10:21:02 +00:00
roboomp dca4da87f1 fix(tui): extended chain gutter past last-sibling branches in tree view
The /tree selector and HTML session export rendered chain rows (flattened
user/assistant turns) with bare spaces when their nearest branched ancestor
was the last sibling, breaking the visual connection back to the branch
parent.

Cause: tree-selector.ts and export/html/template.js propagated
`show: !isLast` to descendant gutters, so any chain row under a `└─`
ancestor rendered the gutter as space instead of `│`. Branched
grandchildren correctly need that space to keep standard tree drawing, but
chain-flattened conversation rows lost their anchor.

Fix: at render time, when the row has no connector of its own (chain row),
force the gutter to `│` regardless of the ancestor's `show` flag. Rows
with their own connector still respect the `show` flag so a `│` never
floats below an unrelated `└─` for branched descendants.

Applied identically in tree-selector.ts (TUI) and export/html/template.js
(HTML export, regenerated into template.generated.ts).

Fixes #2298
2026-06-11 10:20:56 +00:00
roboomp dfc04ab482 docs(changelog): move #2295 fix to Unreleased
The web-search metadata.user_id fix was mistakenly added under the released 15.11.0 section; relocate it under [Unreleased] per AGENTS.md.

Refs #2295
2026-06-11 08:26:18 +00:00
roboomp 4f39003a0f fix(providers): claude-code-shaped metadata for oauth search
Anthropic OAuth web search now uses resolveAnthropicMetadataUserId so metadata.user_id matches the main streaming path's {session_id, account_uuid?, device_id} JSON envelope. API-key paths keep forwarding the raw session id.

Exported resolveAnthropicMetadataUserId from pi-ai. Extended the regression test to cover the OAuth shape.

Refs #2295
2026-06-11 08:24:53 +00:00
roboomp 22f05cb1a3 fix(providers): sent anthropic search metadata
Forwarded the active web search session id as Anthropic Messages metadata.user_id so enterprise gateways can attribute and rate-limit search calls consistently with the main streaming path.

Added a focused Anthropic web search request-shape regression test.

Fixes #2295
2026-06-11 08:14:46 +00:00
roboomp dba543f226 fix(retry): capped classifier fallback attempts
Kept classifier refusals eligible for model fallback, but restored the retry.maxRetries guard so fallback chains cannot consume extra provider calls after the turn budget is exhausted.

Fixes #2290
2026-06-11 05:44:20 +00:00
roboomp 37d9eaabe5 fix(retry): fell back on anthropic refusals
Preserved Anthropic stop_details on assistant messages so the agent can distinguish classifier refusals from transport failures.

Taught AgentSession to use configured retry fallback chains for refusal and sensitive stops without same-model retries, then pin the fallback for the conversation.

Fixes #2290
2026-06-11 05:37:53 +00:00
roboomp 46214c62f8 fix(hashline): clarified insert-after-block anchors
Updated the hashline edit prompt and internal edit docs to make insert-after-block anchors opener-only, and added regression coverage for closing-delimiter anchors and prompt guidance.\n\nFixes #2292
2026-06-11 05:36:44 +00:00
roboomp ae49f83913 fix(mcp): hid windows cmd stdio shims
Wrap Windows MCP .cmd/.bat stdio launches through a hidden cmd.exe invocation so PATH shims such as npx keep stdio attached without flashing a console.

Fixes #2287
2026-06-11 04:00:05 +00:00
can1357 e6ee124d7c chore: bump version to 15.11.0 2026-06-10 23:57:00 +02:00
can1357 98c6564db6 fix(coding-agent): fixed IRC handoff await behavior to prevent stale mailbox relays
- Fixed `IrcBus.send` to avoid queueing successful outbound messages and buffer only failures.
- Fixed IRC `send` await handling to use cancellable waiters with `drainPending: false` and abort-on-empty recipients.
- Fixed relay behavior to skip main-agent-originated messages and prevent duplicate outbound IRC relay cards.
- Added tests covering subagent-only relay routing, await-time fresh replies, and failure mailbox counts.
2026-06-10 23:56:38 +02:00
can1357 72c12ff9c2 feat(task): migrated task tool to batch-first mode with shared context
- Replaced task-simple-mode with a `task.batch` setting enabled by default.
- Updated task schema to use batch `{agent, context, tasks[]}` payloads.
- Migrated task execution to spawn one async job per task and merge outputs.
- Removed per-call schema passing while preserving legacy flat task calls.
2026-06-10 23:47:28 +02:00
can1357 0e92185217 Merge remote-tracking branch 'origin/farm/a61a3aee/fix-shake-loop-token-metric-divergence' 2026-06-10 23:46:59 +02:00
can1357 681479c8c9 feat(coding-agent): removed startup input buffering and simplified interactive initialization
- Removed `StartupInput` pre-TUI buffering and replay, and read startup input directly each loop.
- Removed pre-startup model/provider/LSP discovery and startup handoff into session setup.
- Updated `WelcomeComponent` to use per-instance tips and show `No recent sessions` when empty.
- Documented task option removals and startup splash/input behavior changes in `CHANGELOG.md`.
2026-06-10 23:42:39 +02:00
can1357 8e237183d6 feat(coding-agent): unified IRC transcript rendering through shared card helper
- Added an exported `createIrcMessageCard` renderer to `tools/irc.ts` for incoming and relay IRC traffic.
- Updated IRC message rendering in `UiHelpers` to use the shared card component instead of manual transcript block construction.
- Included `replyTo` and timestamp-derived age metadata in the IRC transcript card output.
2026-06-10 23:40:38 +02:00
roboomp dfc3ef52d5 style: bun run fix 2026-06-10 21:19:08 +00:00
roboomp 7fa0eeb43d fix(agent): break shake auto-continue loop on token-metric divergence
The shake-strategy post-shake threshold check was reading
#estimatePendingPromptTokens([]) while #checkCompaction triggered on
calculateContextTokens(assistantMessage.usage). The local estimator
ignored block.thinkingSignature payloads (OpenAI Responses encrypted
reasoning items, Anthropic signed thinking blocks, etc.), so on a
thinking-heavy session the estimate sat ~0.9–2× below provider-reported
usage. Once the two straddled the threshold, the #2119 dead-loop guard
never fired, shake reported 'handled', and #scheduleAutoContinuePrompt
re-injected the auto-continue developer prompt every turn — 53 injections
in a real 25-minute repro session before an external timeout.

Thread the trigger's provider-anchored contextTokens through
#runAutoCompaction → #runAutoShake for the threshold and incomplete
paths, then evaluate residual pressure as triggerContextTokens −
result.tokensFreed with an 80% recovery-band hysteresis. Re-checking
against the raw threshold (even on the corrected metric) would still let
shake reclaim a trickle of the previous turn's elidable blocks and land
just under the line every turn; the band closes that oscillation.

As defense in depth, estimateTokens() now charges thinkingSignature and
redactedThinking.data alongside the visible thinking text so every
other site that uses the estimator (idle compaction, pre-prompt check,
status line) tracks provider usage on replay.

New regression test pins the contract; existing dispatch test bumped
its mocked tokensFreed so its happy-path scenario lands inside the new
recovery band.

Fixes #2275
2026-06-10 21:18:46 +00:00
can1357 a4f83d6aad fix(coding-agent): respect screenshot format from save path extension 2026-06-10 23:17:00 +02:00
can1357 ad1c17fffd ux(coding-agent): combined ttsr rule notifications into one block 2026-06-10 23:15:40 +02:00
can1357 6836dc1193 fix(coding-agent/tools): kept the resolve result block color past the leading icon 2026-06-10 23:15:34 +02:00
can1357 86195d6944 refactor(cross-cutting): moved grouped path-tree helpers into pi-utils 2026-06-10 23:13:39 +02:00
can1357 dcda0e49b8 fix(coding-agent/tools): honored screenshot path extensions in image capture
- Added imageFormatForPath to map explicit save extensions to Puppeteer image formats.
- Derived screenshot capture type from explicit save paths and used it for both element and page screenshots.
- Updated MIME and extension handling so saved full-resolution image bytes and names match the chosen format.
2026-06-10 23:12:20 +02:00
can1357 6ac73655c8 feat(coding-agent): removed resume support and switched task execution to spawn-only
- Removed `resume` from task params and schema, requiring agent and assignment inputs.
- Dropped resume continuation paths in task execution and call rendering, always spawning a new agent.
- Removed the `irc.enabled` setting and computed IRC availability by task-depth rules.
- Updated task follow-up guidance to use IRC messaging/history links instead of `task(resume:)`.
2026-06-10 23:00:03 +02:00
can1357 1d73af19f8 fix(coding-agent/tools): stripped task-result envelope from job TUI previews
- Added a helper to strip model-facing `<task-result>` wrappers from job result text.
- Updated the job tool renderer to preview the unwrapped `<output>/<preview>` body instead of the envelope markup.
- Documented the settled-task preview fix in the coding-agent changelog.
2026-06-10 22:44:11 +02:00
can1357 9df951d667 Merge remote-tracking branch 'origin/farm/232e592f/fix-thinking-autopending-icon' 2026-06-10 21:50:38 +02:00
can1357 0fe75212b4 ux(hashline): appended context previews to unresolved block-edit errors
- Added a shared `formatAnchoredContext` helper and switched mismatch formatting to use it.
- Extended unresolved block-edit errors to append nearby numbered context with `*`-marked anchor lines.
- Updated unit and integration tests and docs to reflect the new unresolved-block preview behavior.
2026-06-10 21:50:19 +02:00
can1357 08a941a14e feat: added standalone snapcompact package and model-specific frame shaping
- Added a new @oh-my-pi/snapcompact package and redirected compaction call sites to it.
- Added provider-aware snapcompact shape resolution for model-specific mixed-frame behavior.
- Added optional image detail support by extending ImageContent and passing hints through OpenAI providers.
- Added native snapcompact render options, including 5x8/8x8 font loading and palette/geometry controls.
2026-06-10 21:50:03 +02:00
roboomp dab23f76a4 fix(tui): replaced thinking.autoPending question-mark glyphs with loading indicators
The status-bar auto-thinking pending indicator used `?`-bearing symbols
in all three presets (`▣?` Unicode, nf-md-help_box Nerd Font, `[?]`
ASCII), which is visually indistinguishable from a terminal missing-
glyph fallback. Users assumed the icon was broken and toggled presets
to no effect.

Replaced each preset with an unambiguous loading indicator:
- Unicode: `⟳` (Clockwise Open Circle Arrow)
- Nerd Font: `\uf1ce` (fa-circle-o-notch)
- ASCII: `[~]`

Fixes #2267
2026-06-10 19:27:19 +00:00
can1357 6ff1fe5caf docs(coding-agent): logged Unreleased entries and snapcompact compaction notes
Adds the [Unreleased] block to the coding-agent CHANGELOG covering the task tool single-call rewrite, IRC mailbox bus rework, eval agent() context drop, Agent Hub overlay, supersede pruning, soft request budgets, subagent salvage, repeat-read notice, inline byte cap, agent lifecycle, history:// protocol, snapcompact strategy, IRC tool renderer, compaction inline divider, and async.enabled scope narrowing. docs/compaction.md gets the snapcompact strategy section (rationale, frame budget, eviction policy, fallback to context-full).
2026-06-10 17:55:19 +02:00
can1357 32cb880668 chore(coding-agent): regenerated html export template for task resume and irc ops
Reflects the task tool's resume path (single-agent badge or resume=<id>) and the new irc op/receipt shapes (no awaitReply, op falls back to result.details.op) in the static html exporter.
2026-06-10 17:55:08 +02:00
can1357 9d99ae1af0 feat(coding-agent): rewrote the task tool to spawn one persistent subagent per call
The task tool now takes a single { agent, assignment, description, ... } and always runs the subagent in the background — the batch tasks[] array and shared context parameter are gone. Fan-out is parallel task calls; shared background flows through a '/Users/can/.omp/agent/sessions/-Projects-.tree-pi-commit/2026-06-10T15-36-32-782Z_019eb22d-970e-7000-8964-72c98becf3e8/local' file referenced in each assignment.\n\nIntroduces a persistent subagent lifecycle: finished subagents stay live as idle, the lifecycle manager parks them to disk after task.agentIdleTtlMs (default 7 minutes; 0 keeps them live until exit), and they revive automatically when prompted from the Agent Hub, messaged on IRC, or resumed via task. New task(resume: "<id>") revives an idle or parked subagent and runs a follow-up assignment in its existing session.\n\nAdds soft request budgets (explore/quick_task 40, others 90, configurable via task.softRequestBudget, 0 disables): crossing the budget injects a one-time wrap-up steer into the child; crossing 1.5× aborts the run gracefully. Cancelled/aborted subagent salvage replaces the old (no output) with the child's last activity snippet plus request/token stats; SingleResult tracks a per-child requests counter (assistant message_end events) used to sort agent lists in runtime-ascending order in both the live progress view (finished agents above pending/running) and the finalized result view, so rows no longer reshuffle on finalize. Adds a task gallery fixture variant for the resume path (renderer key separated from fixture key).\n\nAll task tests are reshaped around the single-call contract; tests for the discarded shared-context flow are removed, and new task-guards/task-resume/task-schema tests pin the new contract surface.
2026-06-10 17:54:47 +02:00
can1357 9613076e96 feat(coding-agent): added repeat-read notice to the read tool
Tracks successful file reads per resolved base path (selector stripped) for the session; once a path has been whole-file-read three times, every subsequent read for that path appends a one-line nudge suggesting narrower line-range re-reads or the context echoed in edit results. Non-file sources (URLs, internal resources, directories, archives, SQLite, images) are never counted.
2026-06-10 17:53:46 +02:00
can1357 3aa1cedd73 feat(coding-agent): enforced an inline byte cap at the bash and browser tool boundary
Adds enforceInlineByteCap() in streaming-output and applies it to bash and browser tool results: oversized outputs are elided head/tail with an artifact:// footer pointing at the full capture, closing paths that previously let 100KB+ inline results past the minimizer. Defense at the tool-result boundary (no-op for already-bounded output).
2026-06-10 17:53:26 +02:00
can1357 0f4f301a02 feat(coding-agent): made waiting job polls displaceable in the TUI
A job poll whose watched jobs are all still running and nothing was cancelled is pure 'still waiting' noise once a newer block exists. ToolExecutionComponent now detects isWaitingPollDetails on the result, leaves the block displaceable, and keeps its rows out of scrollback. EventController tracks the most recent displaceable poll and resolves it (sealing the block) on every event that proves another tool now owns the live region: a new tool call/result, a streaming arg start, an end-of-turn signal, or another job result that itself isn't displaceable. UiHelpers' transcript rebuild applies the same rule. Docs and the new job-poll-displacement test pin the behavior.
2026-06-10 17:53:07 +02:00
can1357 9f62c7904a feat(coding-agent): integrated snapcompact strategy and per-turn supersede pruning
Adds compaction.strategy: "snapcompact" to the schema and the AgentSession routing: when chosen, both manual /compact (without custom instructions) and auto compaction call snapcompactCompact() to archive history as PNG frames instead of an LLM summary. Falls back to context-full with a visible warning notice when the current model is text-only or when /compact gets custom instructions. CustomTool and shared-event payloads carry the new action through. \n\nAlso wires the per-turn supersede pass: #pruneSupersededReads() runs every turn before threshold gating (cache-aware: only fires when the post-candidate suffix is small or the prompt cache is cold), prunes older read results superseded by a newer read of the same file, rewrites the session, and accounts the saved tokens in the next compaction decision. Gated by compaction.supersedeReads (default on).\n\nsession/messages.ts now delegates the core role conversion to agent-core's convertMessageToLlm so snapcompact image blocks flow through the LLM-context conversion path.
2026-06-10 17:52:49 +02:00
can1357 a64ff00cb8 feat(coding-agent): added history:// internal URL for agent transcripts
Registers a HistoryProtocolHandler with the internal URL router: history:// lists every registered agent (id, status, kind, last activity) and history://<agentId> renders a concise markdown transcript (tool calls collapsed to one line each, thinking elided). Live refs render from the in-memory message array; parked refs load read-only from the JSONL session file via loadSessionMessagesReadOnly (no writer, no lock). System prompt + read tool prompt + docs/tools/read.md learn the new scheme.
2026-06-10 17:52:13 +02:00
can1357 2b28816010 feat(coding-agent): replaced session observer with Agent Hub and inline compaction divider
The session-observer overlay is gone. The Agent Hub (ctrl+s, alt+a, or double-tap left arrow on an empty editor) presents one overlay with two views: a live registry table (status, unread irc count, current task, last activity; j/k to navigate, r to revive, x to abort/release) and per-agent chat (transcript + input line) — submitting revives a parked agent and steers it via the normal prompt path. Main is the ambient chat and stays out of the table.\n\nrenderInitialMessages no longer takes a prebuilt context: every redraw now reaches for AgentSession.buildTranscriptSessionContext() (full-history transcript with each compaction emitted inline at the point it fired, snapcompact frames re-attached on rebuild). UiHelpers drops the deferred-compaction render and the IRC autoreply branch that the new mailbox bus deprecated. CompactionSummaryMessage renders as a slim divider (── 📷 compacted · ctrl+o ──), expanding to the summary + snapcompact frame count. session-manager.buildSessionContext gains a { transcript: true } mode; an exported buildSessionContextFromFile() reads a session file without taking the writer lock so the hub chat view can tail any agent (parked or live). Theme picks up icon.camera + tool.irc symbol entries.
2026-06-10 17:51:42 +02:00
can1357 a92d2ce989 feat(coding-agent): removed context argument from eval agent() spawn
Shared background now flows through a '/Users/can/.omp/agent/sessions/-Projects-.tree-pi-commit/2026-06-10T15-36-32-782Z_019eb22d-970e-7000-8964-72c98becf3e8/local' file referenced in each prompt instead of a context string forwarded into the subagent's system prompt. The JS and Python preludes drop the context kwarg from agent(), the subagent system prompt drops the {{#if context}} block and the conversation-context file pointer, and runEvalAgent no longer writes a per-call conversation context file. AgentSession sheds the now-unused formatCompactContext() helper that supplied the file's body, and ToolSession.getCompactContext is removed alongside it.
2026-06-10 17:49:01 +02:00
can1357 fcb8663de8 feat(coding-agent): reworked irc to a send/wait/inbox/list mailbox bus
Replaces the blocking auto-reply IRC turn with a process-global IrcBus and a four-op tool (send/wait/inbox/list). send is fire-and-forget with per-recipient delivery receipts (injected/woken/revived/failed); replies become real turns by the recipient, observed via wait (or the send await:true sugar). Bounded per-agent mailboxes (cap 100) drop oldest on overflow; AgentSession.deliverIrcMessage folds an in-flight delivery in as a non-interrupting aside at the next step boundary, or starts a real wake turn when idle. AgentRegistry/lifecycle handle the idle→woken / parked→revived transitions, so messaging a non-running peer brings it back. Adds a dedicated TUI renderer (directional headers, delivery-outcome coloring, quoted bodies, per-recipient receipt trees, status-badged peer lists with unread counts). irc.timeoutMs is now the default timeout for wait / send await:true. AgentSession sheds the agentRegistry config field, the dedupeIrcReply → dedupeEphemeralReply rename (now used by /btw and /omfg), and the background-channel exchange queue / forwardIrcRelayToMain plumbing the auto-reply model needed.
2026-06-10 17:47:47 +02:00
can1357 1654c759ca feat(coding-agent): added AgentLifecycleManager for idle/parked subagents
Introduces AgentLifecycleManager: when the task executor adopts a finished subagent the manager arms a TTL timer on idle, parks the agent on expiry (disposes the live session, keeps the AgentRef + sessionFile), and revives it on demand via an injected reviver. Only this manager flips parked ↔ idle. AgentRegistry now annotates session: AgentRef["session"] as null exactly when parked/aborted, and sdk.ts wires the lifecycle dispose into main-session teardown, derives agentKind once, and gates ref unregistration on parking so a parked agent stays addressable (history://, revive).
2026-06-10 17:46:02 +02:00
can1357 5406edeed0 refactor(coding-agent): made the job tool always available and dropped async-job gating
Removes isBackgroundJobSupportEnabled and JobTool.createIf; the tool is now registered unconditionally via `new JobTool(s)`. `async.enabled` now gates async bash commands only — the task tool runs asynchronously regardless. Deletes the async/support module and its barrel re-export.
2026-06-10 17:44:31 +02:00
can1357 84175ce4b2 fix(agent): preserved queued steering across externally aborted runs
Interrupting mid-tool execution (e.g. Enter with a pending steer) drained the steering queue into the dying run — it landed in history without a response and the post-abort resume saw an empty queue, so the agent stopped instead of continuing. Steering/follow-up/aside queue polls in runLoopBody and the post-tool-call check in executeToolCalls are now skipped once the run's abort signal fires, leaving the queue intact for Agent.continue().
2026-06-10 17:43:51 +02:00
can1357 03b5c48827 feat(agent): added supersedeReads pruning for redundant tool results
Adds pruneSupersededToolResults() and the opt-in PruneConfig.supersedeKey hook: when a tool call shares a key with a newer one (e.g. a re-read of the same file), the older result is pruned even inside the protectTokens window and replaced with a [Superseded by a newer read of this file] placeholder. Adds readToolSupersedeKey() and the shared splitReadSelector() implementing the read-tool path/selector grammar (including the .. range alias and L-prefix forms) so selector-free reads supersede range reads of the same file and URL-scheme paths are exempt. Strips selectors before tracking in <read-files> compaction lists, so reads dedupe to the base path and match write/edit paths when splitting read-only vs modified lists (selector-polluted lists from earlier compactions self-heal on the next pass). Gated by the new compaction.supersedeReads setting (default on).
2026-06-10 17:43:17 +02:00