Commit Graph

103 Commits

Author SHA1 Message Date
can1357 12238f55ca feat: implemented native ctok tokenization engine with model scopes
- Implemented the `ctok` Rust native tokenization engine with offline support for Claude V3, V47, V5, and V5Sonnet families.
- Replaced global token estimation with model-scoped `Tokenizer` instances and provider-anchored transcript accounting across packages.
- Added vocabulary generation scripts, test fixtures, and comprehensive unit tests for tokenizer routing and matching modes.
2026-08-19 23:27:29 +02:00
can1357 7e8be71ead Merge PR #7247: fix(advisor): prevent false full replays and preserve cache growth (@cuipengfei) 2026-08-11 15:07:43 +02:00
can1357 7ca140f66e fix(ai): routed policy-rejected accounts through sibling rotation
- Added account-scoped policy error detection to correctly identify Codex cyber-policy rejections.
- Updated credential storage and retry logic to route denied accounts through sibling rotation instead of bypassing it.
- Ensured coding-agent sessions exhaust all sibling accounts before falling back on cyber denials.
- Added comprehensive test coverage for credential rotation and retry behavior on policy errors.
2026-08-08 19:29:49 +02: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 6d1bd624df fix(advisor): reset completed refusal cascades 2026-08-05 21:50:23 +02: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
cuipengfei d92632cdde fix(advisor): preserve split update safety 2026-08-05 00:16:22 +08:00
cuipengfei ccf9f1381c fix(advisor): log quarantine context resets 2026-08-04 22:36:42 +08:00
cuipengfei 3c7d884da9 fix(advisor): avoid double-folding first-time primary context on recovery retries 2026-08-04 22:36:42 +08:00
cuipengfei 21d0db72cf feat(advisor): log reset reason on every advisor context re-prime (issue #7226) 2026-08-04 22:36:41 +08:00
cuipengfei 5b25030720 fix(advisor): address review — dedupe obfuscation, restore dedup map on rollback, complete fingerprint fields 2026-08-04 22:36:41 +08:00
cuipengfei b506c8ee65 fix(advisor): split Session update into per-message user messages to keep prompt cache growing
The advisor sends its whole Session update as a single ever-growing user
message. Provider prompt caches are prefix-based: a single user message whose
text keeps growing invalidates the entire message on every turn, so cache_read
stays pinned at the instructions/tools boundary (observed 14491 tokens in
production, 11066 in tests) instead of growing with the session.

Split the update into multiple user messages — one per source message —
delivered via a single Agent.prompt(AgentMessage[]) call, so the provider
caches each appended message incrementally. Verified end-to-end: cache_read
grows 0 -> 11126 -> 11457 -> 11583 across turns with the split, versus pinned
11066 on the old single-message behavior.

- delta-split.ts: pure renderAdvisorDeltaChunks using chunked
  formatSessionHistoryMarkdown (shared toolResultIndex/consumedToolCallIds/
  watchedRoleState) so toolCall/result pairing and role collapsing stay
  byte-identical to the old single-block render (equivalence-tested).
- session-history-format.ts: add HistoryFormatOptions.watchedRoleState so
  chunked renders collapse consecutive same-role messages exactly like the
  single-block render.
- runtime.ts: #prepareBatch does a single dedup+render pass; #drain delivers
  agent.prompt(preparedMessages) (array), falling back to the string.
- Keep field-selective fingerprint (candidate 1) + wip-marker-at-tail
  (candidate 3) as complementary wins.

Tests: advisor suite 209 pass / 0 fail; type check clean; lint clean.
Affected subsets (342 tests) green; full suite hits WSL EMFILE fd limit.
2026-08-04 22:36:41 +08:00
Wolfgang Schoenberger 26e422a00a fix(coding-agent): suppress WIP advisor non-blockers 2026-07-30 15:18:06 -07:00
can1357 09545697ee fix(advisor): capture model identity lazily and drop duplicated release notes 2026-07-30 02:01:03 +02:00
can1357 1b25ff01a2 style: apply biome formatting to merged changes 2026-07-30 02:01:03 +02:00
can1357 c9a5605b5b fix(advisor): degraded reasoning on provider refusals
(cherry picked from commit 776f244d810ac152eb0bd130b36c8474201d0b85)
2026-07-30 02:01:02 +02:00
can1357 3a61aa727f fix(coding-agent): keep Advisor retry sleep on Bun
(cherry picked from commit 31b9090f901b520b57d5dacec3f8c7dba271decc)
2026-07-29 23:08:23 +02:00
Paolo Mazzitti 3c7233af44 fix(coding-agent): scope advisor cost to active session 2026-07-29 07:18:48 +00:00
can1357 641d20fa5c refactor(coding-agent/advisor): removed stale-review-window warning from advisor notes
- Remove `annotateForStaleness` and `hasFreshBacklog` from the advisor runtime.
- Stop appending staleness warnings to delivered advisor notes when newer primary turns queue.
2026-07-28 04:25:41 +02:00
roboomp 7ac1e69f9f fix(advisor): kept quarantine failure latched until recovery
Internal advisor context resets cleared failureNotified immediately after the quarantine warning, causing the status to return to running and repeated warnings every two quarantines.

Keep the notification latch through internal context re-primes. Clear it only on a successful advisor turn, explicit reset, or seed, and cover both deduplication and recovery in the quarantine regression test.
2026-07-26 03:17:33 +00:00
roboomp 377e9ff5d9 fix(advisor): notified the user when a quarantined turn drops advice
The advisor drain loop's quarantine branch reset context and re-primed silently with no bound, so an advisor that called an ungranted tool (e.g. bash) had its whole turn discarded before dispatch and its advice never reached the primary. Every other non-recovering failure branch calls notifyFailure -> emitNotice; quarantine was the one path with no main-UI signal, leaving supervision failures visible only in advisor diagnostics.

Count consecutive quarantines and, past MAX_QUARANTINE_RETRIES, surface the failure via notifyFailureOnce and drop the batch instead of looping silently. Reset the counter on any successful turn and on reset().

Fixes #6661
2026-07-26 03:12:59 +00:00
can1357 2ffb67e3c7 fix: reconciled merged tests and dead code with current main structure
- warp completion test updated to event-taking notification signature
- hindsight test config gained required timeout fields
- dropped orphaned parseBillingConfig and advisor secret-collection dupes
- deduped fixture key; formatter pass on merged files
2026-07-23 18:02:31 +02:00
can1357 c0c1622012 Merge PR #4636: feat(secrets): add friendly names to secret placeholders (@Mathews-Tom)
# Conflicts:
#	packages/ai/test/pi-native-client.test.ts
#	packages/coding-agent/src/advisor/runtime.ts
#	packages/coding-agent/src/prompts/tools/eval.md
2026-07-23 17:56:24 +02:00
can1357 735a345086 Merge PR #5902: fix(advisor): keep advise when Cursor emits ungranted native tools (@roboomp) 2026-07-18 19:57:44 +02:00
Christian Stewart c8f1972c8c fix(coding-agent): drain advisor reviews in print mode 2026-07-18 01:51:00 -07:00
roboomp 3d72284de5 fix(advisor): kept advise when cursor emits ungranted native tools
Cursor selects server-native tools (bash, grep, ...) outside the advisor's grant. Those exec-channel blocks are stamped kCursorExecResolved: they already ran server-side through the advisor-scoped CursorExecHandlers bridge, which rejects ungranted tools in-band. quarantineAdvisorUnsafeOutput was flagging them as pre-dispatch hazards and discarding the entire turn, dropping the legitimate advise emitted alongside them.

Skip exec-resolved native blocks in the unavailable-tool check so the scoped bridge stays the grant gate and the advisor can still deliver advice.

Fixes #5900
2026-07-17 19:18:42 +00:00
can1357 eac51b6a04 Merge: darkphilosophy/feat/advisor-per-agent-toggle
Brings the per-advisor toggle, status-line glyphs, quota display, and the
failing-advisor stall/abort fix (f4c8143) onto main's rewritten advisor
runtime. Conflict reconciliation kept main's architecture (fingerprint
prefix reconciliation, host-level onTurnError recovery + fallback chains,
terminal-failure classification) and ported the branch semantics onto it:

- #failing latch: waitForCatchup resolves immediately while an advisor is
  mid-failure; parked waiters wake the moment a turn fails, before any
  async hook or retry sleep.
- Turn-end render containment: a formatter bug restores the cursor/prefix/
  dedup snapshot and never propagates into the primary's turn-end callback
  (per-advisor try/catch boundary in AgentSession).
- Quota pause: when host recovery declines a usage-limit failure, the
  runtime latches quotaExhausted, requeues the batch, and notifies —
  cleared only by an explicit reset.
- Hard halt after a permanent rejection or three backlog-drop cycles.
- #recoverAdvisorTurn also marks usage limits for structural errors thrown
  before any assistant turn is recorded.
2026-07-17 07:37:29 +02:00
DarkPhilosophy f4c81434d0 fix(advisor): never let a failing advisor stall or abort the primary agent
A broken advisor could hold the primary agent on the per-turn catch-up
gate for its full 30s budget while retrying, and an exception thrown from
onTurnEnd propagated into the primary's turn-end callback.

- waitForCatchup resolves immediately while the advisor is mid-failure
  (new #failing latch, set at the failure catch BEFORE any async hook,
  cleared on the next successful turn or reset/seed).
- Every parked waiter is woken the moment an advisor turn fails.
- The turn-end boundary isolates advisor exceptions per advisor: a
  throwing advisor loses its delta, the primary and sibling advisors
  continue untouched.
- A failed render (poisoned message, formatter bug) restores the delta
  cursor and dedup state, so the delta is re-rendered next turn instead
  of silently lost; the size probe itself is guarded and falls back to
  the deferred renderer.
2026-07-17 07:24:30 +03:00
can1357 2594ae352b style: formatted conflict-resolved files with biome 2026-07-17 05:01:19 +02:00
can1357 dd84ec57ce apply PR #5468: fix(advisor): stop retrying terminal failures
Grafted the evaluator's port (ec2c1e632) onto the merged advisor
runtime: terminal provider failures classified non-retriable (and not
context overflow) drop the bounded batch after one attempt with a
single notification; fallback-chain recovery and overflow recovery
retain precedence. Includes the one-prompt regression test and tags the
rollback-retry fixture's synthetic failure as transient.
2026-07-17 05:00:06 +02:00
can1357 11a879e993 merge PR #5463 via eval/pr-5463: fix(advisor): anchor context maintenance on provider usage
Semantic merge with #5734 (delivered-prefix reconciliation) and #5748
(fallback chains): kept the coalescing round cap and wip threading,
adopted bounded cursor-preserving maintenance resets and overflow
recovery, and gated late-arrival consumption on coalescing rounds so
both suites' backlog and preserved-updates contracts hold.
2026-07-17 04:55:49 +02:00
DarkPhilosophy 3be0663bf2 fix(advisor): halt permanently rejected advisors and chunk large delta renders
Two shared failure modes with a single misbehaving advisor:

- A permanently rejected request (invalid_request_error, e.g. a model the
  account no longer supports) retried forever: one notice, then silent
  re-attempts on every turn, rebuilding heavy context each cycle. Quota
  exhaustion already paused with a notice; this class now hard-stops the
  runtime after a permanent rejection or three consecutive backlog-drop
  cycles, with a visible notice. An explicit reset (/new, config rebuild,
  restart) re-enables it, and waitForCatchup resolves while halted so the
  primary agent never parks on a runtime that cannot drain.

- The delta render ran synchronously on the event loop; replaying a
  multi-MB transcript after a reset blocked it for 600ms+ per render
  (measured 675ms at ~54MB). Large deltas now render in size- and
  count-bounded chunks that yield between slices (675ms -> single-digit
  ms stalls). Tool call/result pairing survives chunk boundaries via a
  shared whole-delta result index in formatSessionHistoryMarkdown; small
  per-turn deltas keep the synchronous fast path.
2026-07-17 05:47:01 +03:00
can1357 6f42a4375f merge PR #5748 via eval/pr-5748: fix(advisor): apply configured fallback chains 2026-07-17 04:45:46 +02:00
roboomp 777e5e0982 fix(advisor): applied configured fallback chains
- Switched advisor turns to the next configured model after provider quota or rate-limit failures.
- Emitted fallback applied and succeeded lifecycle events without reporting advisor unavailability after recovery.
- Added an end-to-end advisor quota fallback regression test.

Fixes #5740
2026-07-16 19:56:24 +00:00
roboomp 4d0f9c1b66 fix(advisor): reconciled rewritten transcript prefixes
- Tracked delivered message identities alongside the numeric cursor.
- Re-primed advisor context when a live transcript prefix diverged.
- Covered accepted empty-stop pruning before the next real user turn.

Fixes #5731
2026-07-16 17:37:40 +00:00
DarkPhilosophy 1d69621776 fix(advisor): preserve watchdog configuration 2026-07-16 02:07:51 +03:00
Mathews-Tom 0e3eaab137 fix(advisor): preserve history tool arguments 2026-07-16 02:08:42 +05:30
Mathews-Tom c4ef142581 fix(advisor): scan raw primary context 2026-07-16 01:54:55 +05:30
Mathews-Tom d27c9f1bbe fix(advisor): redact rendered transcript only 2026-07-16 01:42:48 +05:30
Mathews-Tom a548c44670 fix(advisor): redact only rendered tool previews 2026-07-16 01:21:53 +05:30
Mathews-Tom 41d2b40555 fix(advisor): scan only rendered tool previews 2026-07-16 01:07:09 +05:30
Mathews-Tom e8ac3b54de fix(advisor): limit execution redaction previews 2026-07-16 00:54:40 +05:30
Mathews-Tom 4fa34d07b9 fix(advisor): clear rewritten thinking signatures 2026-07-16 00:43:59 +05:30
Mathews-Tom cd2047ba81 fix(advisor): skip hidden tool result bodies 2026-07-16 00:35:04 +05:30
Mathews-Tom 39e95bdf43 fix(advisor): rescrub coalesced secret prefixes 2026-07-16 00:22:46 +05:30
Mathews-Tom 71d609d635 fix(advisor): skip hidden custom payloads 2026-07-15 23:09:45 +05:30
Mathews-Tom 93530e0cd6 fix(advisor): retain regex collision values 2026-07-15 22:16:44 +05:30
Mathews-Tom c41dc368cc fix(advisor): skip hidden file body redaction 2026-07-15 22:13:17 +05:30
Mathews-Tom 68d712be4f fix(advisor): ignore hidden file mention content 2026-07-15 21:58:52 +05:30
Mathews-Tom d294cba91c fix(advisor): skip hidden execution output 2026-07-15 21:44:38 +05:30