Commit Graph
6100 Commits
Author SHA1 Message Date
usr_bin_roygbiv bddfd478ac fix(coding-agent/utils): remove extra closing brace in title-generator 2026-06-14 00:35:04 -05:00
usr-bin-roygbiv 82868435c3 fix(coding-agent/config): allow google-gemini-cli in models-config schema 2026-06-13 22:50:49 -05:00
can1357 4b37b79dcb fix(coding-agent/test): align merged tests with current session-context export and compaction-queue context 2026-06-14 03:39:38 +02:00
can1357 ca779a9eef Merge PR #2519: classify HTML export theme defaults by status-line luminance 2026-06-14 03:32:54 +02:00
can1357 9490c659b2 Merge PR #2508: add mnemopi embedding variant setting 2026-06-14 03:32:54 +02:00
can1357 afc0f8c2d2 Merge PR #2502: add guided-goal setup interview 2026-06-14 03:32:53 +02:00
can1357 caadf88953 Merge PR #2522: make /fast default scope configurable 2026-06-14 02:59:37 +02:00
can1357 90fe4995cf Merge PR #2513: /plan exits paused state back to mode none 2026-06-14 02:59:26 +02:00
can1357 0b4efb365d Merge PR #2524: stop AgentBusyError on plan approval and loop/goal continuations 2026-06-14 02:59:26 +02:00
can1357 98fc23899f Merge PR #2533: renumber image markers when restoring queued messages
# Conflicts:
#	packages/coding-agent/test/input-controller-compaction-image.test.ts
2026-06-14 02:59:17 +02:00
can1357 7ca0ca3b06 Merge PR #2530: restore compaction-queued messages on Alt+Up dequeue 2026-06-14 02:57:25 +02:00
can1357 83b00e79a1 Merge PR #2520: run plan-approval compaction on the plan model 2026-06-14 02:57:19 +02:00
can1357 4d01e5e703 Merge PR #2490: clean up compaction UI lifecycle 2026-06-14 02:57:18 +02:00
can1357 81bf6ee965 Merge PR #2506: glow magic keywords through cursor seam + focused shimmer 2026-06-14 02:57:08 +02:00
can1357 0c8cee3080 Merge PR #2521: clamp editor height and overlays on small terminals 2026-06-14 02:56:57 +02:00
can1357 eb5cc85eed Merge PR #2528: emit per-turn token-usage row as standalone block 2026-06-14 02:56:50 +02:00
can1357 dddfc3320c Merge PR #2526: phase-lock tool-call spinners across parallel calls 2026-06-14 02:56:44 +02:00
can1357 f66b14958d Merge PR #2489: memoize tool-result rendering 2026-06-14 02:56:37 +02:00
can1357 686f23a925 Merge PR #2488: TUI event-loop watchdog + phase breadcrumbs 2026-06-14 02:56:31 +02:00
can1357 4fe11fcbf5 Merge PR #2481: work-aware subagent roster (role + activity) [#2478-2481] 2026-06-14 02:56:21 +02:00
can1357 19766762cd chore: bump version to 15.12.6 2026-06-14 02:35:06 +02:00
can1357 f44cf57f9b test(coding-agent): stop auto-compaction queue test from OOM-looping
The continue() mock used mockResolvedValue(), which never consumed the
queued follow-up. After threshold compaction, #endInFlight ->
#drainStrandedQueuedMessages -> #scheduleQueuedMessageDrain reschedules a
zero-delay continue whenever messages remain queued, so the no-op mock spun
the drain into an unbounded microtask loop that allocated until the test
worker OOM'd (~101GB) and segfaulted, taking sibling tests down with it.

Mirror real continue() semantics (it polls and consumes the queue) by
clearing the queues in the mock, matching the sibling steer-idle-drain
tests. The drain now settles after one resume.
2026-06-14 02:34:24 +02:00
roboomp f41007d7da style: bun run fix 2026-06-14 00:24:34 +00:00
roboomp 2e431c0c21 fix(coding-agent): renumber image markers when restoring queued messages
`restoreQueuedMessagesToEditor` prepended queued text but appended queued
images to `pendingImages`. Positional `[Image #N]` lookup at submit time
therefore broke whenever the editor draft already held pending image(s):
queued markers (numbered 1..K against their own image list) collided with
draft markers (1..M) and resolved to the wrong images; queued images
landing past slot M were orphaned.

Add `shiftImageMarkers(text, offset)` to `image-references.ts` and have
`restoreQueuedMessagesToEditor` walk each queued message in order,
shifting its markers by the running pending-image count (existing draft
images plus images already pulled in from earlier queued messages). Draft
markers stay untouched because draft images keep their original slots.
Paste markers are left alone — those are owned by the editor's paste store,
not the pending-image buffer, and queued message text never carries
unmaterialized `[Paste #N]` because the editor expands paste markers in
`getExpandedText()` before `onSubmit` fires.

Regression test seeds a draft image + a queued image-message in
`input-controller-compaction-image.test.ts` (per acceptance) and locks the
marker -> image mapping after restore. Unit tests for
`shiftImageMarkers` cover the WxH tail, Paste-marker passthrough, and
the zero-offset no-op.

Fixes #2531
2026-06-14 00:24:28 +00:00
can1357 24c8bb24c6 feat(session): added modular session APIs and rebuilt listing/persistence behavior
- Added session-domain modules and exports for session-entries, context, listing, loader, and migrations.
- Changed persistence to async append writes plus writeTextAtomic, removing sync line APIs.
- Added compaction-aware session context rebuild with dangling tool-call cleanup.
- Added resumable session resolution with status inference, id/stem/suffix matching, and backup recovery.
2026-06-14 02:02:53 +02:00
metaphorics 39883fd8bf test(coding-agent): type clearQueue stub to drop unsafe cast in restore test
Address PR review: the makeCtx session stub typed clearQueue() as
returning string[], forcing an `as unknown as` cast when the ordering
test overrode it with message objects. Type the stub to the real
RestoredQueuedMessage[] shape so the override needs no cast and shape
drift is caught at compile time.
2026-06-14 08:54:29 +09:00
metaphorics 219fa0765c fix(coding-agent): obfuscate guided-goal transcript before provider calls
runGuidedGoalTurn sent the rendered interview transcript to the plan/slow
provider as raw text, so a secret typed into the rough goal or an answer
bypassed the session's redaction contract. Route the transcript through the
session obfuscator before the request and deobfuscate the echoed question /
objective before it is displayed or the goal starts (no-op when no secrets
are configured).
2026-06-14 08:51:59 +09:00
metaphorics aeebcbb6c2 feat(irc): work-aware peer roster with role and activity
Add a display-only `activity` field to AgentRef plus `setActivity`, fed
from the subagent progress chokepoint with a short gist of the agent's
latest intent (or current tool). Render it in the `irc list` output, the
subagent peer roster, and the TUI peer card, beside the role-derived
display name. setActivity emits no event — the roster reads on demand —
so the per-tool-call rate stays off the registry listener path. Peers
with no activity render without a dangling clause.

Refs #2470

Op: extend
2026-06-14 08:47:01 +09:00
metaphorics a6cce473ac feat(task): nudge generic spawns toward specialization
When a spawner with remaining depth capacity spawns generic role-less
workers (a task/quick_task spawn without a `role`, or the same agent
cloned >=2x all without roles), TaskTool.execute appends a non-blocking
advisory steering it toward tailored specialists. Gated on DepthCapacity
so a leaf at max recursion is never nudged; the task-tool depth gate is
extracted into a shared `canSpawnAtDepth` helper reused by both the tool
gate and the advisory.

Refs #2469

Op: extend
2026-06-14 08:47:01 +09:00
metaphorics ecb46fc72b feat(task): advertise role and tailored delegation in task prompts
Document the `role` parameter in the task-tool description (both the
batch and single-spawn shapes) and make tailored specialists the default
rule, not the exception. Direct a recursing worker to pass a `role` for
each sub-specialist. Activates the role field from #2467 for the model.

Refs #2468

Op: extend
2026-06-14 08:47:01 +09:00
metaphorics 5e5e237005 feat(task): inline role specialization for spawned subagents
Add an optional `role` field to the task spawn contract, threaded end to
end through resolveSpawnItems/spawnParamsFor into the executor. A role
injects a specialization preamble into the subagent system prompt and
becomes the subagent's display name and telemetry identity (label
normalized, length capped), so delegated trees stop being clones of one
generic worker. Empty/absent roles fall back to the agent type name.

Refs #2467

Op: extend
2026-06-14 08:47:01 +09:00
metaphorics d2f3c6ea7e refactor(coding-agent): extract /fast status label into a helper
Addresses Copilot review on #2522: the nested ternary building the /fast
status label was duplicated across the ACP and TUI handlers. Extracted
formatFastModeStatus(session) (a switch over serviceTier) so the wording
stays consistent and new tiers/scopes are added in one place. No behavior
change.
2026-06-14 08:42:23 +09:00
metaphorics a95be2860f fix(tui): honest editor-height floor and dead-branch cleanup
Addresses Copilot + Codex review on #2521:

- computeEditorMaxHeight returned 1 on terminals too small to host both the
  editor and the chrome reserve, but the bordered editor never renders fewer
  than 3 rows (2 border + 1 content). The cap now floors at that real minimum
  (EDITOR_MIN_RENDERED_ROWS) so it no longer misreports the rows the editor
  occupies; rendering is unchanged, and the contract is documented honestly
  (reserve holds once terminalRows >= 7).
- #resolveOverlayLayout now always resolves maxHeight (?? availHeight), so the
  maxHeight !== undefined branch in effectiveHeight, the composite slice guard,
  and the number | undefined return type were dead. Tightened all three.
- Mirrored the maxHeight-default contract in the render stress oracle
  (resolveExpectedOverlayLayout + compositeExpectedOverlays) so the randomized
  sweep validates the real clipped geometry instead of the obsolete unclipped
  one; updated the oracle helper test expectation accordingly.

Editor-height tests rewritten to assert the real contract (reserve when the
terminal can host both; pinned to the bordered minimum below that).
2026-06-14 08:40:12 +09:00
metaphorics f6d69620f9 fix(coding-agent): restore compaction-queued messages on Alt+Up dequeue
restoreQueuedMessagesToEditor only drained the agent steering/follow-up
queue via session.clearQueue(), but the "Alt+Up to edit" pending-bar
hint is rendered for both that queue and ctx.compactionQueuedMessages.
Messages typed while the session was compacting -- including /skill:*
follow-ups, which the follow-up path routes to the compaction queue
before its skill check -- were advertised by the hint yet unreachable,
so Alt+Up reported "No queued messages to restore".

Drain compactionQueuedMessages alongside the agent queue, merged in the
same order the pending bar renders (session-steer, compaction-steer,
session-follow-up, compaction-follow-up). The existing text-join, image
hand-back, and abort paths operate on the merged list unchanged.
2026-06-14 08:39:18 +09:00
metaphorics 0ad4c8525c fix(coding-agent): restore model on compaction cancel and before queue flush
Addresses Codex review on #2520:

- Cancel path: `#approvePlan` returned on `compactOutcome === "cancelled"`
  without restoring the deferred pre-plan model, stranding the next turn on
  the plan model and leaking `#planModePreviousModelState`. The model
  transition now runs for the cancelled outcome too (the operator aborted
  only the compaction, not the approval) before the early return.
- Queue-flush ordering: `executeCompaction` flushes input queued during
  compaction before returning, so the post-return model switch landed after
  the queued turn began streaming (deferred one turn via #pendingModelSwitch).
  Added a `beforeFlush(outcome)` hook to `executeCompaction`/`handleCompactCommand`;
  `#approvePlan` runs the transition through it (and idempotently re-runs it
  afterward to cover the message-count short-circuit).

Tests cover the cancel restore and the before-flush ordering.
2026-06-14 08:33:10 +09:00
can1357 17ba881c5a feat(coding-agent/utils): added title marker fallback for non-forced tool-choice models
- Added new system prompts that ask models to emit titles inside `<title>` markers when forced tool calls are unavailable.
- Updated `generateTitleOnline` to use marker-based prompting and disable required `set_title` tool calls for models that do not support forced tool choice.
- Adjusted title parsing to extract the `<title>...</title>` value and fall back to stripped marker text when wrapping tags are incomplete.
2026-06-14 01:32:47 +02:00
can1357 9a26a945a7 fix: dropped unavailable forced toolChoice and added runtime fallback recovery
- Validated queued toolChoice against active tools in agent and coding-agent sessions.
- Rejected queued forced choices with reason "unavailable" when selected tools were inactive.
- Dropped provider toolChoice payloads when requested function tools were not offered.
- Probed Tokio worker-thread support and fell back to current-thread runtime creation.
2026-06-14 01:32:47 +02:00
can1357 65880477fe docs(coding-agent/modes): documented fix for unmatched OSC 133 command markers
- Added a changelog entry describing that submitted user messages no longer pair OSC 133 command-start markers with missing end markers.
- Annotated the user-message component with guidance to avoid emitting OSC 133 command-start markers for submitted prompts.
2026-06-14 01:32:46 +02:00
can1357 ef2304aaca fix(coding-agent/modes): removed redundant OSC133 final zone marker
- Removed the unused OSC133 final zone marker constant from the user message component.
- Stopped appending the final OSC133 marker so rendered messages now end with only the shell integration close code.
2026-06-14 01:32:46 +02:00
metaphorics d7f4d7c679 fix(mnemopi): address review — read-only opens skip reconcile; preserve MNEMOPI_EMBEDDING_MODEL precedence (#2476) 2026-06-14 08:27:15 +09:00
metaphorics 67cf33ed2d fix(coding-agent): clean up compaction UI lifecycle
executeCompaction added a transcript Spacer(1) the handoff path never adds; it leaked as an orphan blank line on cancelled/failed compaction (only the OK branch cleared it via rebuildChatFromMessages). Removed it, and on the OK branch the loader is stopped + statusContainer cleared before the rebuild so the live loader no longer composites over the reconciled transcript. The finally block stays as the idempotent cancel/fail safety net.
2026-06-14 08:25:57 +09:00
metaphorics ee45472c05 fix(coding-agent): memoize tool-result rendering to stop per-frame re-shape stalls
ToolExecutionComponent.#updateDisplay() re-ran renderResult (O(result-size)) on every invalidate - spinner ticks, stream chunks, resizes, keystrokes - so large results blocked the loop for seconds and typing lagged. It now early-returns on an unchanged dirty key (result version, expanded, partial, spinner frame, image visibility, theme epoch), and theme.ts exposes getThemeEpoch() bumped on every theme swap so cached blocks re-render on theme change.
2026-06-14 08:23:57 +09:00
metaphorics 2b126ffb80 feat(tui): add event-loop watchdog and phase breadcrumbs for stall diagnosis
Always-on LoopWatchdog (armed in TUI.start/stop) logs ui.loop-blocked with blockedMs and the current loop phase on the rising edge of a late probe tick. New pushLoopPhase/popLoopPhase/currentLoopPhase stack in pi-utils feeds it; breadcrumbs at in-process subagent dispatch (subagent:<id>) and the SelectList fuzzy filter (ui.select-filter) attribute residual main-thread stalls.
2026-06-14 08:23:05 +09:00
metaphorics 35307b60a7 fix: emit per-turn token-usage row as a standalone block
With display.showTokenUsage on, the usage row was rendered inside the
assistant block above the turn's tool blocks. Finalizing the assistant
block was therefore deferred, and the late append recommitted the
already-committed tool rows, duplicating them in scrollback (worst with
parallel tool calls).

The assistant block now always finalizes as soon as a tool-call appears,
and the usage row is emitted as a standalone finalized block below the
turn's tool blocks across all three render paths (live event-controller,
transcript rebuild, agent-hub). The now-dead setUsageInfo/#usageInfo path
on AssistantMessageComponent is removed.
2026-06-14 08:17:36 +09:00
metaphorics 34746ceaf5 fix: stop AgentBusyError on plan approval and loop/goal continuations
Plan approval dispatched the executor's first synthetic prompt without
checking whether the agent was still streaming the post-resolve
continuation (or a turn started by the approve-time compaction/clear),
surfacing "Failed to finalize approved plan: ... Agent is already
processing". Loop auto-submit and goal continuations hit the same throw
via submitInteractiveInput, which always called prompt/promptCustomMessage
without a streamingBehavior.

#approvePlan now aborts any in-flight turn before the synthetic prompt,
and submitInteractiveInput routes submissions through the steer/follow-up
queue (streamingBehavior: "followUp") when the session is streaming.
Non-streaming call shapes are unchanged. Extends the manual-/goal fix
(#2454) to the continuation and plan-approval paths.
2026-06-14 08:17:00 +09:00
metaphorics b85f599917 fix: phase-lock tool-call spinners across parallel calls
Each live ToolExecutionComponent advanced its spinner glyph from its own
per-instance start time, so concurrent tool spinners showed different
frames and read as janky. Derive the glyph from a single shared monotonic
clock (sharedSpinnerFrame) so every live block animates in lockstep; the
per-instance interval still drives requestRender. The unused
#lastSpinnerAdvanceAt anchor is removed; the todo-strike counter is
untouched.
2026-06-14 07:38:37 +09:00
metaphorics 18b2bef00e feat(coding-agent): make /fast default scope configurable
Adds a fastModeScope setting (both|openai|claude, default both). setFastMode(true)
derives the service tier from it (both->priority, openai->openai-only,
claude->claude-only) instead of hardcoding unscoped priority; the off path and
the already-on no-op are unchanged. /fast status now reports the active scope.
Default both preserves existing behavior.
2026-06-14 07:00:46 +09:00
metaphorics b28ad9a1dc fix(tui): clamp editor height and overlays on small terminals
Two bounded TUI overlap fixes:

- Editor max-height (coding-agent): the [6,18] clamp's floor of 6 exceeded
  available space on terminals <=18 rows, letting the editor crowd the
  transcript/status. Extracted a pure computeEditorMaxHeight(rows) with an
  EDITOR_MIN_CHROME_ROWS=4 upper bound; identical for rows >=18.
- Overlay overflow (tui): #resolveOverlayLayout left maxHeight undefined when
  the option was unset, so a tall overlay's bottom rows were dropped
  off-screen. maxHeight now defaults to availHeight so every overlay is
  sliced to fit and re-clamps on resize.
2026-06-14 06:59:58 +09:00
roboomp 70cc306f05 style: bun run fix 2026-06-13 21:58:44 +00:00
metaphorics 44b9d70c6f fix(coding-agent): run plan-approval compaction on the plan model
When a plan is approved via "Approve and compact context", #exitPlanMode
restored the pre-plan model before the compaction summarizer ran, so the
request cold-missed the plan model's warm prompt cache. The model switch is
now deferred: compaction runs on the plan model, and the switch to the
execution (slider) or pre-plan model happens only after a successful
compaction. A failed compaction stays on the plan model; cancellation is
unchanged. Also clears any queued plan-role model switch when deferring the
restore so it cannot later clobber the restored model.
2026-06-14 06:58:36 +09:00