Commit Graph
1820 Commits
Author SHA1 Message Date
roboomp ed6300b35e fix(agent): release parked subagent session memory on dispose
Keep-alive subagents are handed to AgentLifecycleManager.adopt, which stores
their reviver closure in the process-global #adopted map. The closure is
defined inside runSubagent's scope, which also captures the live AgentSession
(extension-runner callbacks, buildSubagentSessionOptions), so its lexical
environment pins the whole session graph. park() disposes and detaches the
session but leaves the adoption record indefinitely, and #doDispose never
dropped the in-memory transcript, session-manager entries, or the raw-SSE
debug buffer (whose trimmed records retain slice() views of full wire frames),
so every completed subagent's heavy state leaked for the process lifetime.

dispose() is terminal and every revival path reopens from disk, so #doDispose
now sheds retained conversation memory via agent.reset(),
RawSseDebugBuffer.clear(), and SessionManager.releaseRetainedEntries(). The
adoption record can still reference the session, but only as a husk.

Fixes #8003
2026-08-08 09:42:35 +00:00
can1357 0697e7f688 refactor(coding-agent): split secret obfuscator into domain modules
- Separated deterministic replacement generation, placeholder derivation,
  placeholder-range scanning and message-tree transforms out of the 2647-line
  module; obfuscator.ts now holds the types and SecretObfuscator.
- ephemeralPlaceholderKey stays a single instance and both global regexes stay
  beside the code that resets their lastIndex, so placeholder stability and
  the security argument in the moved comments are preserved verbatim.
- Repointed every importer at the real modules rather than leaving a re-export
  shim; the public ./secrets barrel exports the same 15 names as before.
2026-08-08 06:32:01 +02:00
can1357 38b61ae342 fix(session): honored explicit retry-after over reason backoff
- A provider-supplied retry-after now bypasses the transient rate/concurrency
  heuristic window instead of being overridden by it (regression from the
  subscription-cap retry change).
- Updated event-controller/ui-helpers test doubles for provenance-gated
  renderer selection (hasBuiltInTool), aggregated retryErrors on
  auto_retry_end, and Bedrock override compat gaining streamIdleTimeoutMs.
2026-08-07 23:38:25 +02:00
roboompandcan1357 7d4b2e7998 fix(agent): re-check context on cooldown-expiry revert in auto-continue path
A cooldown-expiry model revert runs at a turn boundary. The user-prompt
path reverts then re-checks accumulated context against the restored
model via runPrePromptCompactionIfNeeded, but the automatic
agent.continue() path (#scheduleAgentContinue) reverted and issued the
next request with no such check. When a transient failure had fallen
back to a larger-window model and the conversation then grew past the
original model's window, restoring the primary once its cooldown expired
sent a predictably oversized request to the smaller model.

maybeRestoreRetryFallbackPrimary now reports whether it actually
switched, and the auto-continue path runs the same post-revert
context-fit maintenance (compaction/promotion) the prompt path already
runs, but only when a revert occurred.

Fixes #7952
2026-08-07 23:38:24 +02:00
can1357 0e8142ad0e Merge PR #7904: fix(session): surface real handoff errors instead of false cancel (@roboomp) 2026-08-07 14:52:57 +02:00
roboomp 1e6638d8cd fix(session): surfaced real handoff errors instead of false cancel
The handoff catch in session-handoff.ts and the /handoff handler in
command-controller.ts mapped any error named AbortError to "Handoff
cancelled" regardless of whether the handoff signal was actually
aborted. Providers throw name-AbortError errors on non-user conditions
(stalls, idle timeouts, nested resolution failures), so a genuine
generation failure surfaced as a user cancellation and hid the cause.

Only report "Handoff cancelled" when handoffSignal.aborted is set;
re-throw the real error otherwise. The controller now trusts the
normalized "Handoff cancelled" message and drops its own AbortError
check so re-thrown provider failures render as "Handoff failed: ...".

Fixes #7903
2026-08-07 12:00:06 +00:00
can1357 a8a8188e4b Merge PR #7756: fix(coding-agent): preserve before_agent_start prompt override across base rebuilds (@roboomp) 2026-08-07 13:39:53 +02:00
can1357 fe7774a1aa Merge PR #7806: fix(coding-agent): detect non-English questions in todo reminder guard (@roboomp) 2026-08-07 13:39:52 +02:00
can1357 e8e47a3b34 fix(coding-agent): report only matching prewalk arms 2026-08-07 13:39:51 +02:00
can1357 5f758778b8 Merge PR #7785: fix(coding-agent): make prewalk lifecycle one-shot (@eggpeat) 2026-08-07 13:39:51 +02:00
can1357 68dece477f Merge PR #7772: fix(session): handle subscription-cap retry exhaustion (@roboomp) 2026-08-07 13:37:54 +02:00
Brent 2efe8896ea fix(coding-agent): make prewalk lifecycle one-shot 2026-08-06 19:57:10 +00:00
roboomp 181f63ebc0 fix(coding-agent): detect non-English questions in todo reminder guard
The isAwaitingUserAnswer guard that suppresses the todo completion reminder while the agent waits on a user question only recognized English question words and pronouns. A '?'/'?'-terminated Chinese, Japanese, Korean, or Spanish prompt went undetected, so the <system-reminder> interrupted the pause and the model misread it as the user's answer.

isQuestionPromptLine now also treats a question-mark-terminated line containing any non-ASCII character as a pending user question.

Fixes #7803
2026-08-06 06:47:27 +00:00
roboomp f6c5a43a1f fix(session): handled subscription-cap retry exhaustion
- Classified subscription and plan rate caps as credential-rotatable usage limits while preserving transient per-minute throttles.

- Applied reason-specific backoff to transient rate limits and collapsed exhausted retry attempts behind one budget-labeled terminal error.

- Covered classification, delay selection, persisted transcript aggregation, and retry event propagation.

Fixes #7767
2026-08-06 01:31:22 +00:00
roboomp 3df56506c7 fix(coding-agent): preserve before_agent_start prompt override across base rebuilds
The per-turn systemPrompt returned by before_agent_start was applied only to the agent state, so any base-prompt rebuild firing in the prompt window (context-overflow compaction/promotion, memory promotion, MCP/RPC tool refresh, hindsight MM-TTL refresh) re-pushed the rebuilt base via setSystemPrompt and silently dropped the override before the request.

SessionTools now tracks the active per-turn override and re-applies it on every base rebuild during the turn, clearing it when the turn ends.

Fixes #7755
2026-08-05 21:28:37 +00:00
can1357 0474e797da Merge PR #7678: fix(session): migrate hashed session dirs back to legacy names (@roboomp) 2026-08-05 22:16:28 +02:00
can1357 677b6f10f5 Merge PR #7735: fix(coding-agent): return ToolInfo[] from getAllTools extension API (@roboomp) 2026-08-05 22:15:46 +02:00
can1357 3de6dabf98 Merge PR #7740: fix(session): isolate rewind reports by checkpoint cycle (@roboomp) 2026-08-05 21:50:23 +02:00
can1357 a11eacc9d6 fix(advisor): drop unreachable status guard 2026-08-05 21:50:23 +02:00
can1357 c19665ef90 Merge PR #7745: fix(advisor): fail a refusal over to the model fallback chain (@mvid) 2026-08-05 21:50:23 +02:00
Mantas Vidutis a650938d3f Merge upstream/main into fix/advisor-refusal-fallback 2026-08-05 11:43:16 -07:00
roboomp 2cf500dcc0 fix(session): isolated rewind reports by checkpoint cycle
- Bounded rewind report recovery to messages created after the active checkpoint.

- Added resumed-context regression coverage for late stale rewind results.

Fixes #7739
2026-08-05 16:26:56 +00:00
roboomp 83496b8211 fix(coding-agent): returned ToolInfo[] from getAllTools extension API
The ExtensionAPI getAllTools() wired to session.getAllToolNames(),
returning bare tool-name strings. Upstream @earendil-works/pi-coding-agent
promises ToolInfo[] with sourceInfo, so extensions loaded through the
legacy-pi shim (e.g. gentle-pi) crashed on t.sourceInfo.source at every
session start.

Added SourceInfo/ToolInfo types plus SessionTools.getAllToolInfos(), which
returns { name, description, parameters, sourceInfo } and classifies each
tool as builtin/mcp/sdk/extension. Rewired every getAllTools action site
(interactive, acp, print/rpc, subagent executor) and the example extension.

Fixes #7732
2026-08-05 15:42:06 +00:00
can1357 e9888367d1 refactor: migrated packages to internal utility modules and removed external dependencies
- Implemented in-house, zero-dependency utility modules in `pi-utils` covering DOM manipulation, markdown parsing, templating, browser automation helpers, and terminal buffers.
- Migrated packages across the repository to consume the new internal utilities and `omptype` schema validators instead of external dependencies.
- Removed multiple external runtime and development dependencies including Zod, Marked, LRU cache, Turndown, and Puppeteer browser packages.
2026-08-05 13:39:09 +02:00
Can BölükandGitHub 1e492d6ff9 Merge pull request #7354 from brymko/fix/browser-timeout-crash-recovery
Fix/browser timeout crash recovery
2026-08-05 12:39:14 +02:00
brymko 56931915f1 feat(coding-agent): added fatal session recovery hints
Registered live session resume commands with postmortem handling so a
fatal rejection or exception identifies every recoverable agent before
cleanup. Escaped terminal control characters in recovery output.
2026-08-05 14:31:03 +08:00
roboomp 338451ffdb fix(session): migrate hashed session dirs back to legacy names
The 17.2.9 revert (172ce9b) restored the legacy path-based session
directory names but removed all migration, including the reverse path.
Sessions written under the short-lived hashed scheme (17.2.5-17.2.8,
`<scope>-<readable>-<sha256>`) were left orphaned, so `omp -r`
current-folder scope reported no sessions.

computeDefaultSessionDir now reconstructs the hashed dir name for the
cwd and performs a one-way best-effort migration into the legacy name,
alongside the existing legacy-absolute migration.

Fixes #7677
2026-08-05 06:22:22 +00:00
Kyle McCleary 5cc4f5c93a Merge main into refactor/agent-hub-fullscreen 2026-08-04 18:15:42 -07:00
can1357 eb56330c9c chore(changelog): normalized unreleased entries after merges 2026-08-05 02:32:48 +02:00
roboompandcan1357 99748bbe61 fix(ai): omitted codex optional response defaults
Stopped OpenAI Codex requests from sending reasoning.summary, reasoning.context, and text.verbosity unless explicitly configured, matching the safer native Codex request shape for GPT-5.x models.

Preserved explicit overrides and added regression coverage for transformer and settings-aware stream behavior.

Fixes #4949

(cherry picked from commit 15d86667d6572faf453e74b922eed33dd2d3f3c9)
2026-08-05 02:32:36 +02:00
can1357 a6eafcbf6b fix(ai): keep concurrency caps out of auth rotation
(cherry picked from commit bd6285ad9b16ae6f0a75e336a1c4bf961d3e43c7)
2026-08-05 02:32:36 +02:00
metaphoricsandcan1357 5726fac646 fix(ai): tighten concurrency-cap classification and account-cap gating
Reset-window rotation requires account-specific wording; concurrency caps require an actual cap signal; credential removal gated on AuthFailed without UsageLimit so a valid-but-blocked 403 credential is retained.

(cherry picked from commit 2f72752c2586352a4f7e9e814af1cdb0cf192af4)
2026-08-05 02:32:35 +02:00
metaphoricsandcan1357 7262d9762e fix(ai): honor account reset windows and statusless concurrency caps
Account-reset hint evaluated before short retry hints; account-scoped caps rotate on status 403 or undefined (Devin statusless trailer); statusless concurrency caps marked transient; transient same-model retries use the concurrency backoff.

Refuted: quota-worded concurrency caps were already excluded from rotation before the usage-limit text match.
(cherry picked from commit f2b9a18d715ddbcb6ae703670f2212da36bb2826)
2026-08-05 02:32:35 +02:00
Kyle McCleary 5b68e99796 Merge main into refactor/agent-hub-fullscreen 2026-08-04 17:23:50 -07:00
Kyle McCleary 8e5f619502 fix(coding-agent): harden Agent Hub lifecycle and persistence 2026-08-04 16:29:15 -07:00
can1357 89931e109a fix(session): preserve colliding legacy sessions 2026-08-05 01:12:54 +02:00
can1357 94c838faea Merge PR #7539: fix(coding-agent): complete usage-aware fallback integration (@eggpeat) 2026-08-05 01:12:02 +02:00
can1357 975d0a2e9d Merge PR #7501: fix(agent): classify thinking-only unexpected stops (@roboomp) 2026-08-05 01:12:00 +02:00
can1357 0cf5d55ac0 Merge PR #7629: fix(coding-agent): retry buffered print streams (@roboomp) 2026-08-05 01:12:00 +02:00
roboomp 172ce9bf6c revert(session): restored legacy project directory names
Reverted PR #7397 session directory hashing and automatic migration.

Restored existing script compatibility with the legacy cwd-derived naming scheme.

Fixes #7646
2026-08-04 21:10:54 +00:00
Mantas Vidutis 6e32705e71 fix(advisor): fail a refusal over to the model fallback chain
A classifier refusal returned before the `onTurnError` hook that owns
model fallback, so `AdvisorRuntime` treated one provider's policy verdict
as terminal: `Refusal (cyber)` on the advisor model disabled the advisor
outright even with a fallback chain configured. Its only recovery was
stripping echoed primary reasoning and resending once, which does nothing
for a refusal about the content itself.

Route a refusal that outlives the strip through the same hook the generic
failure path uses, mirroring its epoch guard, session-transition requeue,
and requeue-on-recovery. The cascade walks the chain to exhaustion and
only reports the advisor unavailable once the host runs out of candidates,
matching what turn-recovery already allows for the primary.

Each cascade visits a model at most once. A switch re-arms
`#includeThinking` through `#syncModelIdentity`, so chain keys that point
back at each other (A to B, B to A) would otherwise strip-and-resend
against the same pair forever. A successful turn or a reset starts a
fresh walk.

Also stop `/advisor status` throwing when a live advisor has no roster
entry: `formatAdvisorStatus` guarded only the inactive case before
dereferencing `stats.advisors[0]`, and `#ensureAdvisors` clears
`#advisorStatuses` before repopulating it, so a status call landing in
that window hit `undefined.contextWindow`.
2026-08-04 11:47:54 -07:00
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
Kyle McCleary 91467c2f27 fix(coding-agent): restore Agent Hub lineage metrics 2026-08-03 19:42:11 -07:00
Brent 2da96d77a7 fix(coding-agent): close fallback lifecycle races 2026-08-03 17:51:32 +00:00
Brent 353bbc034b fix(coding-agent): harden usage fallback review races 2026-08-03 17:15:57 +00:00
can1357 1a8caad23e chore: update docs + rename reset to clear 2026-08-03 18:37:23 +02:00
Brent db97103c32 fix(coding-agent): complete usage-aware fallback integration 2026-08-03 16:34:35 +00:00
can1357 fc04aa6fa7 refactor(coding-agent): deferred startup parsing and schema compilation
- Wrapped security contract schemas in a lazy initializer with jitless scopes to eliminate startup JIT compilation tax.
- Enabled jitless scope configuration in auth-broker wire schemas to skip definition-time codegen.
- Deferred startup changelog parsing to overlap with interactive session creation.
2026-08-03 16:31:27 +02:00
can1357 a418920ec1 feat: made /reset semantically different
Closes #4447
2026-08-03 15:46:46 +02:00
roboomp 50228c3656 fix(agent): gate thinking-only stops on signature
Align isUnexpectedStopCandidate with #isEmptyAssistantStop: only a signed (non-whitespace thinkingSignature) thinking-only stop is a candidate. Unsigned thinking-only stops stay with the empty-stop retry path and its cap, so unexpected-stop classification no longer re-handles a turn the empty-stop cap already gave up on.

Fixes #7499
2026-08-03 13:18:54 +00:00