@vib-rato/agent-core 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +852 -0
  2. package/README.md +493 -0
  3. package/dist/types/agent-loop.d.ts +229 -0
  4. package/dist/types/agent.d.ts +533 -0
  5. package/dist/types/append-only-context.d.ts +141 -0
  6. package/dist/types/attempt-scope.d.ts +84 -0
  7. package/dist/types/compaction/adaptive.d.ts +31 -0
  8. package/dist/types/compaction/branch-summarization.d.ts +103 -0
  9. package/dist/types/compaction/compaction.d.ts +330 -0
  10. package/dist/types/compaction/entries.d.ts +124 -0
  11. package/dist/types/compaction/errors.d.ts +26 -0
  12. package/dist/types/compaction/index.d.ts +12 -0
  13. package/dist/types/compaction/messages.d.ts +61 -0
  14. package/dist/types/compaction/openai.d.ts +65 -0
  15. package/dist/types/compaction/pruning.d.ts +130 -0
  16. package/dist/types/compaction/utils.d.ts +32 -0
  17. package/dist/types/compaction.d.ts +1 -0
  18. package/dist/types/harmony-leak.d.ts +100 -0
  19. package/dist/types/heap-eviction-retainers.test.d.ts +1 -0
  20. package/dist/types/image-placeholder-guard.d.ts +4 -0
  21. package/dist/types/index.d.ts +13 -0
  22. package/dist/types/proxy.d.ts +95 -0
  23. package/dist/types/run-collector.d.ts +223 -0
  24. package/dist/types/run-resource-ledger.d.ts +2 -0
  25. package/dist/types/telemetry.d.ts +605 -0
  26. package/dist/types/thinking.d.ts +18 -0
  27. package/dist/types/tool-dispatch-identity.d.ts +27 -0
  28. package/dist/types/types.d.ts +790 -0
  29. package/package.json +72 -0
  30. package/src/agent-loop.ts +5632 -0
  31. package/src/agent.ts +2437 -0
  32. package/src/append-only-context.ts +496 -0
  33. package/src/attempt-scope.ts +195 -0
  34. package/src/compaction/adaptive.ts +92 -0
  35. package/src/compaction/branch-summarization.ts +358 -0
  36. package/src/compaction/compaction.ts +1569 -0
  37. package/src/compaction/entries.ts +158 -0
  38. package/src/compaction/errors.ts +31 -0
  39. package/src/compaction/index.ts +13 -0
  40. package/src/compaction/messages.ts +212 -0
  41. package/src/compaction/openai.ts +580 -0
  42. package/src/compaction/prompts/auto-handoff-threshold-focus.md +1 -0
  43. package/src/compaction/prompts/branch-summary-context.md +5 -0
  44. package/src/compaction/prompts/branch-summary-preamble.md +2 -0
  45. package/src/compaction/prompts/branch-summary.md +30 -0
  46. package/src/compaction/prompts/compaction-short-summary.md +9 -0
  47. package/src/compaction/prompts/compaction-summary-context.md +5 -0
  48. package/src/compaction/prompts/compaction-summary.md +38 -0
  49. package/src/compaction/prompts/compaction-turn-prefix.md +17 -0
  50. package/src/compaction/prompts/compaction-update-summary.md +45 -0
  51. package/src/compaction/prompts/file-operations.md +10 -0
  52. package/src/compaction/prompts/handoff-document.md +56 -0
  53. package/src/compaction/prompts/summarization-system.md +3 -0
  54. package/src/compaction/pruning.ts +1026 -0
  55. package/src/compaction/utils.ts +189 -0
  56. package/src/compaction.ts +1 -0
  57. package/src/harmony-leak.ts +457 -0
  58. package/src/heap-eviction-retainers.test.ts +293 -0
  59. package/src/image-placeholder-guard.ts +20 -0
  60. package/src/index.ts +23 -0
  61. package/src/prompts/escaped-nonascii-recovery.md +3 -0
  62. package/src/prompts/repeated-tool-failure-recovery.md +1 -0
  63. package/src/proxy.ts +408 -0
  64. package/src/run-collector.ts +728 -0
  65. package/src/run-resource-ledger.ts +345 -0
  66. package/src/telemetry.ts +2161 -0
  67. package/src/thinking.ts +20 -0
  68. package/src/tool-dispatch-identity.ts +87 -0
  69. package/src/types.ts +882 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,852 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
4
+
5
+ ## [0.16.0] - 2026-09-02
6
+
7
+ ## [0.15.6] - 2026-08-30
8
+
9
+ ## [0.15.5] - 2026-08-29
10
+
11
+ ## [0.15.4] - 2026-08-29
12
+
13
+ ### Added
14
+
15
+ - Added opt-in adaptive compaction thresholding based on context fullness and recent call rate. The default remains disabled, fixed token thresholds keep precedence, and the bounded tracker resets after successful compaction to avoid repeated immediate compactions.
16
+
17
+ ## [0.15.3] - 2026-08-27
18
+
19
+ ### Changed
20
+
21
+ - Current provider adapters no longer mark syntactically valid `\uXXXX` arguments as guarded: JSON parsing has already produced the canonical string, so valid escaped Hangul, emoji, ASCII, and other scalars execute like literal UTF-8 in every tool. The existing `displaySafeEscapedArgFields` path remains only for compatibility with legacy producers that still attach non-malformed positional evidence. Malformed evidence, unauthenticated managed evidence, incomplete/conflicting arguments, and unpaired surrogates remain fail-closed.
22
+ ### Fixed
23
+
24
+ - Managed fallback snapshots now convert unauthenticated Unicode evidence into `incompleteArgumentsReason: "malformed"` instead of preserving a boolean-only guard that could lose the evidence needed by terminal validation.
25
+ - Compaction no longer crashes on a persisted tool call whose `arguments` payload is null. `serializeConversation` passed that value straight into `Object.entries`, which threw `TypeError: Object.entries requires that input parameter not be null or undefined`. Because this runs inside compaction — itself the recovery path for context overflow — the failure surfaced as `Context overflow recovery failed: Object.entries requires ...`, and the next request went out uncompacted until the provider rejected it with `prompt is too long`. Malformed argument payloads now serialize as an empty argument list instead of aborting the summary.
26
+
27
+ ## [0.15.2] - 2026-08-25
28
+
29
+ ### Changed
30
+
31
+ - Version 0.15.1 was tagged but never published: release automation failed while deriving release notes, before any package reached npm. Everything listed under `## [0.15.1]` below ships in this release.
32
+
33
+ ## [0.15.1] - 2026-08-25
34
+ - Display-safe escaped tool calls now require bounded raw escape-position/scalar evidence before the post-resample U+2014 exemption can execute. Printable ASCII escapes are retained too, so one-nibble mutations such as `\u00b7` → `\u0077` and `\u2026` → `\u0026` fail closed instead of disappearing after JSON decoding. Evidence carries only raw/decoded offsets, ordinals, location kinds, process-keyed scalar/path tags, a bounded total, and a process-local integrity tag; it is stripped before discarded, rejected, or executed calls can become durable. Exact decoded U+2014 positions/counts must correspond to the complete envelope. Overflow, malformed or duplicate-key JSON, missing/altered evidence, escaped keys, dotted-key ambiguity, excessive nesting, and every other scalar reject terminally. Existing resample/terminal debug records remain shape-only and never include argument payloads.
35
+ - Escaped-non-ASCII turn discards and terminal per-call rejections are now logged at debug severity with bounded shape-only fields. Diagnostics distinguish managed policy handoff from in-loop resampling, type in-loop attempt/budget values as numbers, cap tool-call counts, and report only fixed booleans for registration/display-field contracts; tool names, call ids, arguments, steering text, and payload content never enter the log. The discarded turn never reaches durable history, so the defect previously left no trace anywhere except the surfaced tool error, and its fire rate could only be recovered by scraping session transcripts.
36
+ - `normalizeTools` now converts every Zod-authored tool schema to the wire JSON schema even when intent tracing is off. Previously the conversion ran only inside the `_i` intent-injection branch, so canonical sub-sessions (role agents spawned via `task`, where `resolveIntentTracingEnabled` forces `_i` off) sent a live `ZodObject` across the provider boundary. On append-only context providers (`anthropic`, `deepseek`; auto-enabled) the stable-prefix clone JSON-round-trips tools, and a `ZodObject` without `toJSON` reduces to a bare `{def, type}` object with no `properties`/`required` — the model is then advertised a tool with no parameters and omits required arguments. This is the root cause of issue #4837: every subagent `bash` call failing with `command: Invalid input: expected string, received undefined` while the parent session's identical call worked. Tool argument validation itself is unchanged: executors still validate against the original Zod schema.
37
+ - Managed fallback now transfers safety-stop authority only to the adjudicated final assistant shell; intermediate partial snapshots and hostile accessor-backed final messages cannot retain or bypass the provenance boundary (#4777 review).
38
+
39
+ - Managed assistant reconstruction now copies provider metadata through guarded property reads instead of an unguarded spread, so accessor-trapped metadata degrades without aborting the attempt or creating managed retry authority (#4777 review).
40
+ - Hostile Proxy-wrapped final messages no longer reintroduce a forged `provider_safety_stop` label through the sanitizer fallback shell; discarded failure outcomes are now label-free before session policy can suppress provider fallback (#4777 review).
41
+
42
+
43
+ ## [0.15.0] - 2026-08-22
44
+
45
+ ### Fixed
46
+ - Staged-payload sizing no longer materializes what it is bounding (#4602 fix-forward of the exact-head 078e22c0 review). All staging measurements now walk the JSON surface directly: exact byte counts come from a code-point walk (quotes, escapes, separators, delimiters, nulls, array holes, and keys all charged) instead of building the full `JSON.stringify` string plus its UTF-8 encoding, and lone surrogates are charged as the six-byte `\udXXX` escape JSON emits rather than their three-byte UTF-8 form, closing a ~2x undercount on surrogate-heavy strings. `structuredClone` is additionally preflighted by a clone-surface walk that never dispatches `toJSON`, accessors, or proxy traps: a live payload class whose compact `toJSON` hides an oversized own payload is rejected as the typed `local_buffer_overflow` at `overflow.preMeasure` — before the duplicate is allocated — instead of being cloned first and rejected at `overflow.staged`. Accessors are no longer invoked at all while sizing (a staged witness getter is read zero times), `undefined`-valued record properties are skipped exactly as `JSON.stringify` omits them, an unmeasurable assistant pair now fails closed like its `#stage` twin instead of being retained with a zero-byte charge, the `overflow.preMeasure` diagnostic reports the incoming event's real bounded size instead of a constant fabricated after `discard()`, and above-ceiling clamp warnings are logged once per distinct knob value with a bounded digest. |
47
+ - Queue-removal paths (`queue.message.remove`, positional editing, `clearQueue`, the terminal-abort purge) now fire the stored promotion hook with a removal disposition so an accepted SDK submission terminalizes boundedly instead of staying accepted forever (#4668).
48
+ - Provider safety-stop messages now retain their explicitly allowlisted `errorKind: "provider_safety_stop"` through managed assistant snapshots and remain terminal even when transport facts are present on a multi-model fallback chain, while provider payloads still cannot forge the runtime-owned local diagnostic kinds (#4777).
49
+ - Terminal safety-stop authority is now provenance-bound instead of data-bound: a provider or custom stream payload that self-labels `errorKind: "provider_safety_stop"` without the adapter-minted mark is stripped at the stream exit before any retry/discard gate or the managed snapshot shell reads it, so a compromised provider can no longer force refusal by naming the field (#4777 review). Authenticated first-party envelopes (structured refusal signals parsed by the anthropic, openai-completions, and google adapters) keep terminal treatment, and only the agent loop's module-private rebuild set carries that authority onto its own destination — clones, JSON/persistence round-trips, and re-emitted payloads are all unauthenticated.
50
+ - Safety-stop minting is now limited to the package-private adapter capability, and public AI consumers cannot transfer authority from a genuine marked source to an arbitrary destination. The trailing stream-completion path also sanitizes provenance before rebuilding managed assistant messages, covering streams that end without a `done` or `error` event and keeping forged labels fallback-eligible (#4777 review).
51
+ - Safety-stop authority now expires at every stream dispatch entry: committed assistant messages (including a previously adjudicated stop) are handed to the next — possibly custom — stream through `convertToLlm`, and the dispatch-entry expiry guarantees no live authority mark is ever exposed to a stream, so re-use of a committed stop object cannot forge a terminal failure (#4777 review). The provenance strip is also stopReason-independent and rebuilds frozen or Proxy-trapped final messages as plain mutable copies, so a forged label on a nominally successful response cannot survive into the committed message (where it could skip session compaction checks) and cannot abort the run through a rejection trap.
52
+ - A foreign error that self-declares a local failure kind no longer gets one either (#4618). `errorKind` and the structured `bufferOverflow` shape now come from a single identity-checked extractor (`managedLocalErrorDiagnostic`) used by both terminal-message producers — `managedFailureMessage` and the `Agent` run catch. Previously the shape was identity-gated but the label was not, so a provider or custom-stream failure carrying `errorKind: "local_buffer_overflow"` reached the parent receipt preview as `Local staging-buffer overflow; structured diagnostic unavailable.` and pointed whoever read it at the wrong subsystem.
53
+ - Local diagnostic authority fields are no longer foreign-settable through the managed snapshot shell (#4618). `managedAssistantShell` spreads the provider/stream message snapshot into the rebuilt assistant message; a payload that smuggled a local `errorKind` or `bufferOverflow` through that spread could masquerade as the runtime's own identity-checked diagnostic at the parent boundary. Local kinds and `bufferOverflow` remain stripped from the snapshot spread, while the provider-owned safety-stop kind is copied only through its explicit closed-literal guard.
54
+
55
+ - Documented the accepted-prompt lifecycle hooks: `onFollowUpConsumed` and `onSteeringConsumed` now report `startsOwnRun` so integrations can distinguish new-run ownership from in-run or maintenance consumption. The agent also emits the typed `agent_failed` lifecycle event before an error terminal, allowing SDK hosts to reconcile failure causes and teardown ownership deterministically.
56
+ - `Agent.waitForSteeringArrival(signal)` resolves when steering is queued without consuming it, so wait-style tools can end their observation early.
57
+ - Managed fallback provisional-buffer caps are now operator-configurable: `GJC_FALLBACK_MAX_STAGED_EVENTS` (default 10000, hard ceiling 2000000) and `GJC_FALLBACK_MAX_STAGED_BYTES` (default 16 MiB, hard ceiling 1 GiB) bound the events/bytes staged by the provisional staging transaction in both managed fallback and ordinary (non-managed lossless) sessions; in non-managed sessions the cap only decides how much reasoning buffers before the batch flushes and streams through. Values are read once per attempt; the trusted environment resolver ignores surrounding whitespace, while invalid or non-positive values fall back to the defaults, and values above the ceiling clamp to it with a warning so the staging guard stays bounded instead of trading a typed `local_buffer_overflow` for a process OOM. Every retained batch item — including the assistant message/event pair staged for streaming callbacks — is measured and charged against the caps BEFORE it is retained, so actual retention can never exceed the counted bounds, and the ceilings are set from total retained memory (2,000,000 events / 1 GiB) at values an ordinary host survives. The knobs resolve from trusted environment sources only (`$credentialEnv`, which excludes the repository `cwd/.env` overlay), so a project cannot weaken or weaponize the staging guard. Raise both to survive reasoning-heavy streaming in long-running sessions and `gjc team` workers (#4602, #4618).
58
+
59
+ ### Fixed
60
+ - The escaped-non-ASCII argument guard keeps its fail-closed terminal rejection and its unconditional two-resample budget for every tool and every field. After the budget is spent, one narrowly scoped exemption applies: a tool that enumerated its user-facing display fields (`displaySafeEscapedArgFields`; `ask` exempts only `questions.question` and `questions.options.label`) executes when every non-ASCII character lives inside those fields and is benign typographic punctuation (curated set: U+2014 em-dash). Escaped non-ASCII anywhere else — ids, deep-interview metadata, persisted records, non-ASCII object keys — and every other tool stays rejected terminally (#4627, reduced per both maintainer reviews: guard retained, exemption post-budget and field-scoped).
61
+
62
+ - Escaped-non-ASCII turn resamples are now steered instead of blind: each unmanaged resample carries a transient synthetic instruction naming the `\uXXXX` defect and demanding literal UTF-8, so a model that escapes deterministically (observed with Hangul-heavy `ask` payloads exhausting the whole resample budget every turn) has a reason to change its spelling on the retry. The instruction never lands in durable history, tools stay enabled, and the captured logical-turn tool choice is still replayed across the steered attempts; a pending one-shot malformed-tool-call recovery is never displaced by the steering. Managed fallback retries receive the same steering: the typed `escaped_arguments_discarded` outcome now reports whether the discarded attempt still lacked an instruction, and the session's retry continuation attaches the same transient message through the new `transientRecoveryMessage` prompt option, so coding-agent sessions (which run managed) also get exactly one steered re-request before the budget ends.
63
+
64
+ ## [0.14.1] - 2026-08-18
65
+ - Compaction pruning no longer kills the turn when a persisted `toolCall.arguments` is `null`. Sessions written by an earlier cold-spill eviction path store `null` where the spill sentinel belongs, and the staleness index dereferenced that payload unguarded, so reloading such a session threw `null is not an object (evaluating 'args.path')` as a turn-fatal error instead of skipping the one unusable call. `ToolCall.arguments` is typed non-nullable, so no type check flagged the gap. Every read of a persisted argument bag — path extraction, `apply_patch` header parsing, idempotent-bash keys, and search target keys — now treats a non-object payload as absent. The original arguments are not lost: the eviction marker still names the blob and rehydration restores them.
66
+ - Managed fallback attempt snapshots no longer fail the whole run on benign provider shape variations: an assistant message whose `content` is a bare string, is missing, or is a primitive scalar (null/number/boolean) now degrades to an empty content array; staged `*_delta`/`*_end` events whose `delta`/`content` is missing or a primitive scalar degrade to an empty string; and staged assistant events with out-of-vocabulary `done`/`error` reasons or an unknown string `type` degrade to schema-valid values instead of throwing a non-retryable `ManagedAttemptSnapshotError`. Object-shaped or other plain-object `content`/`delta` stays fail-closed under the named `shell.content`/`event.delta`/`event.content` diagnostic, as does sanitizer-sentinel string content (`[unserializable]`/`[accessor]`/`[truncated]`/`[Circular]`, which marks a non-cloneable original rather than provider string variance — degrading those would silently drop real tool-call or streamed content behind a successful empty turn), and hostile inputs keep failing fast with no retry authority: a live proxy root, a throwing `get`/`getOwnPropertyDescriptor` trap, and a non-string event `type` all remain local snapshot failures.
67
+
68
+ ### Added
69
+
70
+ - `toolFailureEnvelope` / `isToolFailureEnvelope` / `ToolFailureEnvelope` name the result details the loop attaches when a tool call fails without the tool returning details of its own. The guard matches only that envelope, so a consumer can tell it apart from a tool that reports a `failureKind` alongside its own details before dereferencing a tool-owned detail shape.
71
+ - `ManagedAttemptBufferOverflowError` (`local_buffer_overflow`) now reports its full shape everywhere it can reach: the rejecting `stage`, which cap tripped (`exceeded: events|bytes|both`), the retained post-compaction staged event/byte counts, the rejected event's own serialized size, and both caps. The typed error carries this as a structured object, the terminal `AssistantMessage` carries an identity-checked `bufferOverflow` copy (only the module-private error class can attach it, so a foreign self-labeled error cannot), and the surfaced message keeps its stable prefix and appends the same shape-only values stating this is a local staging-buffer limit that reproduces on re-issue, not a provider or context-window failure. Previously every overflow surfaced as one static sentence with no way to tell an event-cap from a byte-cap trip or to distinguish it from a model-context problem (#4618).
72
+
73
+ ## [0.14.0] - 2026-08-17
74
+
75
+ ### Fixed
76
+
77
+ - Managed fallback no longer kills a long turn with `Managed fallback attempt exceeded the provisional event buffer limit`. Every staged streaming frame carries the whole accumulated partial (once as `message`, once as `assistantMessageEvent.partial`), so staged bytes grew quadratically with the response length and a reasoning-heavy turn of a few thousand tokens crossed the 16 MiB cap even though no single event came close to it. Reaching the cap now first reclaims the staged `*_delta` increments, whose complete value is re-published by the retained `*_end` and terminal `message_end`/`done` frames, and only a batch that still cannot fit fails. Attempt atomicity is unchanged: nothing is published early, so a discarded attempt stays unobservable, and a single oversized event keeps its pre-clone rejection with no provider-fallback authority.
78
+ - Non-managed lossless response staging now commits its buffered lifecycle and switches to ordinary pass-through publication when the provisional event cap is reached, instead of turning a large reasoning-only response into a fatal `local_snapshot_failure`. Managed fallback attempts keep the strict bounded-buffer rejection required for atomic retry and provider-fallback isolation.
79
+ - Managed snapshot machinery no longer fails runs on benign payload-class or readable-proxy roots: an assistant message or stream event whose fields live on prototype getters (which `structuredClone` drops — it copies only own enumerable properties) or behind a proxy whose gets are readable is repaired through the existing guarded-read path instead of throwing a deterministic `shell.role`/`event.unknownType`/`event.snapshot` local snapshot failure. The run-loop message_update replay also builds its event through the managed event snapshot instead of a naive `{ ...event }` spread, which silently dropped prototype-carried fields before the snapshot boundary could see them. Hostile shapes (throwing get traps, sentinel-marked degraded content, malformed non-string event types) keep their named fail-fast diagnostics with no retry authority.
80
+
81
+ - Managed fallback now validates and byte-measures the detached event snapshot rather than trusting the live payload's JSON result. Custom payload classes whose prototype `toJSON()` hides bigint state are sanitized after `structuredClone` removes that serializer, so every accepted snapshot stays detached, JSON-serializable, and bounded; residual typed `local_snapshot_failure` diagnostics remain outside provider fallback authority and surface without deterministic retry amplification.
82
+ - Managed fallback buffer overflows now retain a typed `local_buffer_overflow` error kind on the terminal assistant message, so session retry policy surfaces them immediately without provider-fallback attribution instead of admitting them to the bounded `unknown` retry class.
83
+ - Managed local-failure diagnostics: `ManagedAttemptSnapshotError` and `ManagedAttemptBufferOverflowError` now carry a stable `stage` discriminator naming the exact rejecting site (`shell.role`, `shell.content`, `event.snapshot`, `event.contentIndex`, `event.delta`, `event.content`, `event.toolcall`, `event.done.reason`, `event.error.reason`, `event.unknownType`, `staging.losslessSnapshot`, `staging.measure`, `staging.sanitize`, `staging.overflow`, `overflow.preMeasure`, `overflow.staged`), and the run-loop failure boundary emits ONE bounded shape-only `logger.warn` per stream invocation (stage, error kind, model, provider, snapshot mode, staged event count/bytes, and content block count for the content stage). The diagnostic is gated on the module-private local error identities and its stage is whitelisted against the closed vocabulary, so neither a foreign error that self-labels a local failure kind nor an in-module regression can route arbitrary text into the log; it never records raw text, thinking, tool arguments, or any provider payload, and the user-facing message string is unchanged so session-side classification keeps matching. Previously all 14 rejecting sites shared one static message, leaving no way to identify which provider shape a normalizer must be taught to accept.
84
+ - A turn whose tool arguments arrive flagged `escapedNonAsciiArguments` is now resampled instead of being reported as a tool failure: the defective assistant turn is dropped from history and the request is re-issued, up to twice per turn, before the terminal per-call rejection takes over. Hand-spelled `\uXXXX` arguments decode into valid-looking but silently wrong text (observed as garbled Hangul in `ask` prompts) and no post-parse repair can recover them, but the defect is a wire-format accident that resampling clears - surfacing it as a tool error instead burned the whole turn and fed the literal escape syntax back into the context the model samples from next. Scoped to the non-managed session path, matching the existing `invalid_prompt` and reasoning-content repairs; managed fallback keeps owning its own retry policy.
85
+ - Visible-text Harmony leak retries now close the already-published assistant lifecycle with an empty aborted terminal stripped of raw provider payload before contaminated history is removed and a replacement request begins, preventing both orphaned streaming updates and leaked control text in durable history or replay.
86
+ - Unmanaged escaped-non-ASCII resampling now stages a detached, provider-metadata-preserving assistant lifecycle until validation, publishes live safety updates before dispatch, and defers terminal `message_end` publication until subscriber-triggered cancellation is resolved so persisted assistant state and aborted tool-result pairing cannot disagree.
87
+ - The agent loop still rejects a tool call flagged `escapedNonAsciiArguments` before execution once the resample budget is spent, with a retryable error telling the model to re-issue the call writing non-ASCII characters literally.
88
+ - Managed fallback attempt snapshots no longer fail the whole run on benign provider shape variations: an assistant message whose `content` is a bare string or is missing now degrades to an empty content array, and staged assistant events with out-of-vocabulary `done`/`error` reasons or an unknown string `type` degrade to schema-valid values instead of throwing a non-retryable `ManagedAttemptSnapshotError`. This matches the closed `StopReason` vocabulary already normalized elsewhere in the shell. Object-shaped and other exotic non-array `content` stays fail-closed under the named `shell.content` diagnostic, as does sanitizer-sentinel string content (`[unserializable]`/`[accessor]`/`[truncated]`/`[Circular]`, which mark a non-cloneable original value such as a proxy-wrapped content array rather than provider string variance — degrading those would silently drop real content behind a successful empty turn), and hostile inputs keep failing fast with no retry authority: a live proxy root, a throwing `get`/`getOwnPropertyDescriptor` trap, and a non-string event `type` all remain local snapshot failures.
89
+
90
+ ### Added
91
+
92
+ - Reassignable `onFollowUpConsumed` hook on `Agent`: invoked with the follow-up messages the loop dequeues for the next turn, so consumers can attach per-turn state (e.g. a fresh owned-completion lineage) at actual resume admission.
93
+ - `AgentPromptOptions.onRunAccepted` now receives a typed acceptance payload containing `consumedQueuedMessages`, allowing consumers to bind ownership and other per-message state only to the queued messages actually claimed by the accepted run.
94
+ ## [0.13.3] - 2026-08-15
95
+
96
+ ### Fixed
97
+ - Emergency compaction now considers managed transcript file size so sessions compact before the managed per-file limit (#4411).
98
+ - Managed runs discard assistant turns whose tool calls carried `\uXXXX`-escaped arguments and report them through the typed `escaped_arguments_discarded` outcome instead of executing unverifiable text; unmanaged runs reject such calls per-call with an actionable error (#4515).
99
+
100
+ ## [0.13.2] - 2026-08-13
101
+
102
+ ## [0.13.1] - 2026-08-11
103
+
104
+ ## [0.12.21] - 2026-08-09
105
+
106
+ ## [0.12.20] - 2026-08-09
107
+
108
+ ## [0.12.19] - 2026-08-08
109
+
110
+ ## [0.12.18] - 2026-08-08
111
+
112
+ ## [0.12.17] - 2026-08-08
113
+
114
+ ## [0.12.16] - 2026-08-08
115
+
116
+ ### Fixed
117
+
118
+ - Forked-session restore no longer crashes when the seeded append-only prefix includes a tool whose `intent` policy is a deferred function (e.g. `eval`, `bisect`, `checkpoint`, `rewind`). `StablePrefix.importSnapshot` re-normalized the cloned tool JSON, which loses function-valued `intent` fields, so those tools flipped from `omit` to `optional` intent injection and the recomputed fingerprint diverged from the stored one (`StablePrefix.importSnapshot() fingerprint mismatch`). Import now verifies against the stored, already-normalized tools instead of re-normalizing.
119
+
120
+ ## [0.12.15] - 2026-08-06
121
+
122
+ ## [0.12.14] - 2026-08-06
123
+
124
+ ## [0.12.13] - 2026-08-06
125
+
126
+ ### Fixed
127
+
128
+ - An aborted run whose tool ignores its `AbortSignal` now terminates on its own (#3894). `Promise.allSettled` waited on the unresolved call forever, so the turn only ended when the session's force-abort budget expired; the loop now emits a synthetic aborted result for the outstanding calls and `waitForIdle` settles immediately. Session dispose consequently reaches idle through the cooperative path instead of force-invalidating the run.
129
+
130
+ ### Changed
131
+
132
+ - Telemetry configured with `spans: false` now skips span and attribute construction while preserving usage and cost hooks.
133
+
134
+ ## [0.12.12] - 2026-08-05
135
+
136
+ ### Fixed
137
+
138
+ - DeepSeek-family reasoning-content replay 400s are now retryable via a bounded, strip-only circuit breaker. When a proxy strips the encrypted reasoning blob to an empty `encrypted_content`, DeepSeek rejects every follow-up turn with "The `reasoning_content` in the thinking mode must be passed back to the API." Resending the identical history re-triggers this deterministic 400, so the agent loop now strips the unusable `reasoning` items from the Responses history payload in place and resends exactly once (mirroring the `invalid_prompt` poisoned-history breaker). Non-reasoning items are preserved; fail-fast when nothing can be stripped. Budget = one repaired resend.
139
+
140
+ ## [0.12.11] - 2026-08-03
141
+
142
+ ## [0.12.10] - 2026-08-03
143
+
144
+ ### Fixed
145
+
146
+ - Composer repository-file shell policy rejections now receive one bounded, tool-enabled recovery turn without persisting the synthetic instruction. Generic loops retain their repository tools with `toolChoice: auto`; Cursor remote turns continue only when native tools did not already recover, queued user follow-ups take priority, and a second policy block terminates instead of looping. Existing malformed-tool recovery remains tool-free and does not consume dynamic tool-choice state.
147
+
148
+ ## [0.12.8] - 2026-08-02
149
+
150
+ ## [0.12.7] - 2026-07-31
151
+
152
+ ## [0.12.6] - 2026-07-31
153
+
154
+ ## [0.12.5] - 2026-07-30
155
+ ### Fixed
156
+
157
+ - Proxy streams now fail closed when a `toolcall_end` event references missing or non-tool-call content instead of silently dropping the protocol violation and accepting a later terminal event.
158
+
159
+ ## [0.12.4] - 2026-07-30
160
+
161
+ ## [0.12.3] - 2026-07-30
162
+
163
+ ## [0.12.2] - 2026-07-30
164
+
165
+ ## [0.12.1] - 2026-07-29
166
+ - Agent session configuration can carry an explicit first-event stream timeout while preserving provider defaults when the setting is absent.
167
+
168
+ ### Fixed
169
+
170
+ - The `invalid_prompt` circuit breaker no longer replays the rejected turn on its repaired resend. The streaming path commits the failed assistant message to the context before the breaker runs, so the one repaired resend re-sent that errored turn as if the model had spoken it — re-triggering `Request blocked (code=invalid_prompt)` and leaving a second assistant tail that no continuation can resume from. The breaker now repairs and resends only the history that preceded the rejection.
171
+ - Compaction pruning now protects the newest two user/`bashExecution` turns, uses conservative read supersession, preserves bounded error-first diagnostics, and exposes reversible artifact-backed originals with exact savings accounting.
172
+ - Cancelling a prompt no longer fails its terminal closed. `agent_end` is published before the run resource ledger is sealed, so the event's own handlers register post-prompt work against an already-sealed run; that late registration was treated as an escaped resource and quarantined the run, making `waitForSettlement` report `unfenced` forever. Cancel therefore never obtained settlement proof and the SDK refused to publish a terminal, surfacing over ACP as `-32603 "Prompt resources did not settle before the terminalization grace expired."` Sealing now only freezes admission of genuinely new work; post-seal registration joins ordinary settlement accounting so the run stays unsettled until it actually completes.
173
+
174
+ ## [0.11.11] - 2026-07-26
175
+
176
+ ### Fixed
177
+
178
+ - Managed runs now release their logical-run ownership before terminal observers are notified, so terminal overflow recovery cannot leave a stale owner behind.
179
+ - The OpenAI remote-compaction endpoint is now resolved from trusted environment sources only. `OPENAI_BASE_URL` was read through the merged view that includes the caller's `cwd/.env`, so a repository could redirect compaction requests that carry the OpenAI credential; it now uses the non-project resolver, leaving shell and user-level configuration unchanged.
180
+ - Repeated malformed tool calls now get one tool-free recovery response, preventing argument-validation loops from ending without an answer while leaving ordinary execution-error retries unchanged. The recovery turn commits its assistant to the durable context, forces `toolChoice: "none"` alongside an empty tool list without consuming a queued tool choice, and never executes a tool call it did not advertise. Its recovery prompt is request-only, so append-only tool prefixes stay stable and the durable message log is unchanged.
181
+ - Argument-validation loops now reach a deterministic terminal state. If a model keeps emitting only malformed tool calls after the one-shot recovery turn, the run stops with an explanatory error instead of calling the provider indefinitely. The bound counts consecutive all-malformed turns rather than repeated argument signatures, so a model rotating invalid argument shapes is bounded too; any healthy tool turn resets it.
182
+
183
+ ## [0.11.8] - 2026-07-23
184
+
185
+ ### Fixed
186
+
187
+ - Managed model fallback now accepts `reasoning_summary_start`, `reasoning_summary_delta`, and `reasoning_summary_end` assistant events instead of failing them as local snapshot errors.
188
+ ## [0.11.3] - 2026-07-19
189
+
190
+ ### Fixed
191
+ - Pre-compaction pruning now preserves bounded, actionable error evidence instead of discarding it, while enforcing exact positive-savings admission and accounting so a prune is only applied when it demonstrably reduces context cost (#2635).
192
+
193
+ ## [0.11.1] - 2026-07-16
194
+
195
+ ### Fixed
196
+
197
+ - Hardened the managed fallback attempt snapshot: staged agent events and assistant partials were cloned with a bare `structuredClone`, so a single non-cloneable value in a staged payload (e.g. a live `Headers` inside `transportFailure`) threw `DataCloneError` ("The object can not be cloned."), masked the real provider outcome, and deterministically failed every attempt until the fallback chain exhausted. The snapshot now degrades to a cycle-aware sanitizing deep clone that always returns a detached, JSON-serializable value (unsupported leaves become placeholders), so event-time replay semantics are preserved and no local snapshot failure can masquerade as a provider attempt failure. Byte accounting in the provisional buffer measures the raw event before the snapshot duplicates it (over-limit payloads are rejected pre-clone), re-measures degraded snapshots so the retained sanitized form is what gets accounted, and uses the sanitized detached form as the cycle-safe estimator for cyclic payloads.
198
+ - Enforced the managed fallback authority boundary for local staging failures: `ManagedAttemptBufferOverflowError` no longer carries a synthetic provider-like `503` status, so exceeding the provisional event buffer limit (like any other local snapshot failure) is non-retryable, never converts into `transportFailure { kind: "transport", status: 503 }` evidence, and never rotates or consumes the model fallback chain — it surfaces as an explicit local error instead. Only original typed provider transport facts may authorize provider fallback.
199
+ - Added a bounded, neutralize-only `invalid_prompt` circuit breaker to the agent loop (#2282). A poisoned-history rejection (`Request blocked (code=invalid_prompt)`) is a deterministic content fault: re-sending the same history re-triggers it, so uncontrolled session auto-retry would burn its budget re-poisoning the model. On the first `invalid_prompt` of a run, leaked reserved control tokens are neutralized in place across history (no item is ever dropped). If that changes the outgoing bytes, the turn is resent exactly once with the repaired history; if neutralization cannot change anything, the run fails fast immediately with no resend. The repaired history is persisted for a clean resume, the breaker fires at most once per run (budget = one repaired resend), and it is scoped to the non-managed session path since managed fallback owns its own retry policy.
200
+
201
+ ## [0.10.2] - 2026-07-14
202
+
203
+ ### Fixed
204
+
205
+ - Extended the gpt-5.6 `Request blocked (code=invalid_prompt)` fix to the compaction paths that bypass the streaming transport. Remote OpenAI compaction (`/responses/compact`, `compaction.remoteEnabled` default on — the "remote compact task" in openai/codex#32028) built its native `input` from reasoning signatures, verbatim history items, and message/tool text without neutralizing leaked Harmony control-token markers (e.g. `<|channel|>analysis`), so gpt-5.6 rejected the compaction request and, on retry, could escalate to account-level blocking. `requestOpenAiRemoteCompaction` now neutralizes reserved control tokens across the whole outgoing `input`, and the generic `requestRemoteCompaction` prompt/systemPrompt are neutralized too. Local summarization was already covered by the streaming-transport request-boundary fix.
206
+
207
+ ### Changed
208
+
209
+ - `AgentLoopConfig.maintainContext` now receives a required cancellation-aware lifecycle (`signal`, `awaitEventDrain(invocationSignal)`). Agent loops compose the run and maintenance-invocation signals and pass that single signal to EventStream's FIFO consumer-drain barrier, so cancellation removes the pending drain at its owner instead of racing an orphaned wait.
210
+
211
+ ## [0.10.0] - 2026-07-12
212
+
213
+ ### Fixed
214
+
215
+ - The native-free token heuristic is now script-aware: common-BMP CJK characters (Hangul, unified/compat Han, Kana, CJK punctuation, full-width forms) are charged at 1 token each (measured o200k_base upper bound 0.96 tokens/char) and supplementary code points (surrogate pairs: rare Han extensions, emoji) at 1 token per code point, instead of chars/4 for everything. The old estimate undercounted Korean/CJK-heavy unsent context by 2–4x and could delay threshold compaction past the provider window; ASCII estimates are unchanged. `boundConversationTextForSummary` now derives its truncation cut from the text's own estimated token density, validates the complete assembled excerpt (elision marker included) against the estimator, and fails closed — bare marker only when the marker itself fits the budget, otherwise an empty excerpt, including when the computed input budget is non-positive — instead of assuming 4 chars/token and returning over-budget or unbounded text.
216
+
217
+ - A tool call for a name absent from the active tool set now appends a recovery hint pointing at `search_tool_bm25` (gated on a callable `search_tool_bm25`, matched by internal name or `customWireName`), so a model no longer abandons a discoverable tool such as `task` after a bare "Tool <name> not found"; the base error wording stays byte-for-byte stable when discovery is unavailable (#2042).
218
+
219
+ ## [0.9.2] - 2026-07-09
220
+
221
+ ### Fixed
222
+
223
+ - Follow-up queues can now mark individual messages as one-at-a-time, so interactive composer queues can remain sequential without disabling the existing batch mode for other callers.
224
+
225
+ ## [0.8.2] - 2026-07-06
226
+ ### Added
227
+
228
+ - Agent queues now expose ordered move helpers for steering and follow-up messages so callers can reorder pending work without removing and re-adding messages.
229
+
230
+ ### Fixed
231
+
232
+ - Preserved inherited fork-context seed messages when a compacted child rebase receives only child-local normalized messages, avoiding seed loss after task-child compaction (#1567).
233
+
234
+ ## [0.7.7] - 2026-06-28
235
+
236
+ ### Fixed
237
+
238
+ - Mitigate leaked Anthropic-style `<invoke name="…">` tool-call envelopes across providers, not only `openai-codex`, while keeping Codex `to=functions.*` harmony-header mitigation provider-scoped.
239
+
240
+ ## [0.7.4] - 2026-06-27
241
+
242
+ ### Added
243
+
244
+ - Added `pruneAssistantToolArguments`: an isolated pre-compaction pruning pass that redacts stale `edit`/`write`/`apply_patch`/`ast_edit` tool-call argument payloads only when every touched path group has a later successful mutation, preserving tool-call identity (id/name/customWireName/signatures/intent/path hints), protecting latest/failed/ambiguous calls, and reporting separate stats from tool-result pruning. Reduces pre-compaction context pressure and the resident footprint of superseded large edit arguments.
245
+
246
+ ## [0.7.3] - 2026-06-25
247
+ ### Added
248
+
249
+ - Added Composer evidence publication gates in the agent loop, so Composer-harness turns emit structured evidence under defined publication conditions (#1106).
250
+
251
+ ### Fixed
252
+
253
+ - Wired the previously-dead GPT-5 harmony-leak detector into the streamed assistant-message path for openai-codex turns: recoverable tool-argument leaks are now recovered and everything else is routed through the existing abort-retry/audit loop, and the contaminated streamed message is removed (abort-retry) or replaced (truncate-resume) from working context so the model does not replay its own leak as history. Added detection of the leaked Anthropic-style `<invoke name="…">` envelope dialect that gpt-5.5 intermittently emits as visible assistant text instead of a native function call (#1069).
254
+ - Detect proxy-level context overflow from empty responses: some proxies (notably LiteLLM) return an empty `content: []` with `stopReason: "stop"` and fabricated near-zero usage when the upstream context window is exceeded; the agent loop now recognizes this pattern and promotes it to an error so the existing overflow/compaction recovery path fires instead of freezing the session as a clean completion (#1102).
255
+ - Hardened the Composer trace mutation classifier and its recovery-target guard (#1105).
256
+
257
+ ## [0.7.2] - 2026-06-24
258
+
259
+ ### Fixed
260
+
261
+ - Reserved headroom when trimming OpenAI remote compaction input so `/responses/compact` requests stay below the model context window instead of filling the entire window.
262
+
263
+ ## [0.6.2] - 2026-06-19
264
+
265
+ ### Changed
266
+
267
+ - Token accounting no longer depends on a native embedded tokenizer. Token usage now anchors on provider-reported usage (`calculatePromptTokens`) and estimates only the unsent delta with a cheap heuristic (~chars/4 × 1.2); emergency compaction floors are unchanged. Compaction, branch summarization, and fork-seed paths were repointed off the removed native token-estimate alias. Part of dropping the bundled tiktoken/o200k tokenizer (#879).
268
+
269
+ ## [0.5.4] - 2026-06-17
270
+
271
+ ### Fixed
272
+
273
+ - Maintenance one-shot LLM calls now preserve active provider session state and the configured WebSocket transport preference. `SummaryOptions`, `HandoffOptions`, and `GenerateBranchSummaryOptions` accept `sessionId`, `providerSessionState`, and `preferWebsockets`, and `generateSummary`, `generateShortSummary`, `generateTurnPrefixSummary`, `generateHandoff`, `generateBranchSummary`, and `compact()` forward them through to `completeSimple` — previously these fields were dropped, so Codex/OpenAI-compatible compaction summaries, handoff generation, and branch summaries fell back to HTTP/SSE and lost `session_id` affinity even with `providers.openaiWebsockets: "on"`. Split-turn compaction now runs its history and turn-prefix summaries sequentially when they share a single provider WebSocket session, avoiding `websocket request already in progress`; non-WebSocket sessions still run them in parallel. `Agent` exposes a `preferWebsockets` getter so callers can forward the live transport preference (#736).
274
+
275
+ ## [0.5.3] - 2026-06-16
276
+
277
+ ### Fixed
278
+
279
+ - Bounded agent context growth, compaction, and token accounting for long-running sessions: `appendMessage` pushes in place instead of rebuilding the array; the append-only context keeps rolling per-message hashes instead of rescanning the full digest; an emergency-compaction floor that cannot be disabled now surfaces its reason; `getSessionStats` is single-pass; and `nativeCountTokens` skips the synchronous ~39 MB BPE tokenizer above a 2 MiB input cap, falling back to the cheap heuristic (#717).
280
+
281
+ ## [0.5.2] - 2026-06-15
282
+
283
+ ### Fixed
284
+
285
+ - Fixed compaction token estimation in Bun standalone binaries by loading the native tokenizer through the sibling native entrypoint instead of package-name dynamic resolution.
286
+
287
+ ## [0.5.1] - 2026-06-14
288
+
289
+ - Version aligned with the 0.5.1 monorepo release; no functional changes in this package.
290
+
291
+ ## [0.5.0] - 2026-06-13
292
+
293
+ ### Fixed
294
+
295
+ - Fixed compaction cut-point selection when the newest retained context ends in an uncuttable tool result, so automatic compaction can keep the latest assistant/tool-result pair instead of falling back to a no-op cut.
296
+
297
+ ### Changed
298
+
299
+ - Optimization Suite v3 Lane 2 (context cost): compaction token estimates now use a shared per-entry cache (`estimateEntryTokens`) keyed by a boundary-lossless fingerprint of the exact estimator fragments, covering `estimateEntriesTokens`, the `findCutPoint` reverse walk, and pruning candidate scoring — repeated full-session estimate p95 −97%, token totals exactly equal to fresh estimates and never stale after prune mutation. Pruned bash/search/grep tool results now carry a one-line digest notice (exit code, match/file count, first error line; capped at 1.25× the generic notice cost) instead of a bare truncation notice, with savings computed from the exact notice string; reads and other tools keep the generic notice. `trimOpenAiCompactInput` is O(n) via per-item serialized lengths and a running character sum (5k-item trim −99.9%) and is now exported.
300
+ - Optimization Suite v3 Lane 3 (serialization): `cloneJson` in the append-only context now uses a typed JSON-semantic recursive clone instead of a `JSON.parse(JSON.stringify())` round-trip (−36% median on clone-heavy paths), with exact JSON.stringify byte parity including the toJSON holder-key protocol (single get, no re-dispatch on replacement values), function/symbol dropping, sparse arrays, Dates, and prototype-bearing objects; the helper is now exported.
301
+
302
+ ## [0.4.5] - 2026-06-12
303
+
304
+ ### Changed
305
+
306
+ - Made tool-output pruning staleness-aware: results superseded by a later same-target result (re-read file, re-run search) or invalidated by a later successful edit/write are pruned before merely-old ones, including inside the recency protect window. New optional `PruneConfig.staleOverridableTools` (default `["read"]`) waives protected-tool immunity for superseded results while the most recent result per target stays protected. Target identity uses collision-proof canonical JSON tuple keys.
307
+ - `PruneResult` now returns `prunedEntries` so callers whose entry source materializes copies (e.g. blob-externalized session entries) can write mutations back into their canonical store.
308
+
309
+ ### Fixed
310
+
311
+ - Preserved Cursor-native tool call rendering and execution through the agent tool-call path, including runtime tool details.
312
+
313
+ ## [0.4.4] - 2026-06-10
314
+
315
+ - Version aligned with the 0.4.4 monorepo release; no functional changes in this package.
316
+
317
+ ## [0.4.3] - 2026-06-10
318
+
319
+ ### Fixed
320
+
321
+ - Separated a model's total context window from its safe input/prompt-packing budget in the compaction threshold. `effectiveReserveTokens`, `resolveThresholdTokens`, and `shouldCompact` now accept an optional `maxOutputTokens` and reserve at least that completion budget, so a large-output model (e.g. 400K context / 128K max output) caps input near 272K instead of 340K and cannot overflow the total window with reserved output ([#442](https://github.com/Yeachan-Heo/gajae-code/issues/442)).
322
+
323
+ ## [0.4.0] - 2026-06-06
324
+
325
+ ### Changed
326
+
327
+ - Refreshed agent-core package metadata for the GJC 0.4.0 release.
328
+
329
+ ## [0.3.1] - 2026-06-05
330
+
331
+ ### Fixed
332
+
333
+ - Moved the env-driven full message content capture warning into agent-core telemetry resolution so direct `@gajae-code/agent-core` consumers receive `full_content_capture_env_active` when `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=full` is used without an explicit `captureMessageContent` override.
334
+
335
+ ### Changed
336
+
337
+ - Clarified that telemetry `summary` content capture emits bounded real-content snippets in `pi.gen_ai.*` attributes and is not redacted or PII-free.
338
+
339
+ ## [0.2.4] - 2026-06-02
340
+
341
+ ### Added
342
+
343
+ - Added agent options for provider request and stream retry budgets and thread them through streaming calls.
344
+
345
+ ## [0.2.2] - 2026-05-31
346
+
347
+ ### Changed
348
+
349
+ - Refreshed agent-core package metadata for the GJC 0.2.2 release.
350
+
351
+ ## [0.2.1] - 2026-05-30
352
+
353
+ ### Changed
354
+
355
+ - Refreshed agent-core package metadata for the GJC 0.2.1 release.
356
+
357
+ ## [0.2.0] - 2026-05-28
358
+
359
+ ### Changed
360
+
361
+ - Refreshed agent-core package metadata for the GJC 0.2.0 release.
362
+
363
+ ## [0.1.3] - 2026-05-28
364
+
365
+ ### Changed
366
+
367
+ - Released the current dev branch fixes with refreshed 0.1.3 package metadata.
368
+
369
+ ## [0.1.2] - 2026-05-28
370
+
371
+ ### Changed
372
+
373
+ - Updated package metadata for the Gajae Code npm publication.
374
+
375
+ ## [0.1.1] - 2026-05-28
376
+
377
+ ### Added
378
+
379
+ - Added `Agent.forceAbort()` so hosts can recover from provider/tool aborts that ignore cooperative cancellation without clearing conversation history.
380
+
381
+ ## [15.3.0] - 2026-05-25
382
+ ### Fixed
383
+
384
+ - Fixed `transformContext` receiving the loop config object as the `signal` argument instead of the actual `AbortSignal`, so hooks that check `signal.aborted` or call `signal.addEventListener` now work correctly under abort/timeout conditions
385
+ - Fixed `appendOnlyContext` not being re-evaluated after `setModel()` — the mode was decided once at session construction based on the initial model's provider, so switching from/to DeepSeek (or changing `provider.appendOnlyContext`) mid-session produced incorrect mode behavior
386
+
387
+ ## [15.2.3] - 2026-05-22
388
+ ### Added
389
+
390
+ - Added `onBeforeYield` hook support so user code can run right before the agent loop checks for follow-up messages
391
+
392
+ ## [15.1.3] - 2026-05-17
393
+ ### Added
394
+
395
+ - Added optional `telemetry` support to `generateSummary`, `generateHandoff`, `generateBranchSummary`, and `compact` options so compaction, handoff, and branch summary one-shot LLM calls can emit OpenTelemetry chat telemetry when enabled
396
+ - Added shared oneshot telemetry instrumentation for compaction, handoff, and branch summary calls, tagging spans with `pi.gen_ai.oneshot.kind` values such as `compaction_summary`, `compaction_short_summary`, `compaction_turn_prefix`, `handoff`, and `branch_summary`
397
+
398
+ ## [15.1.2] - 2026-05-15
399
+ ### Added
400
+
401
+ - Added `responseHeaders` to `ChatUsageEvent` and `ManualChatTelemetryOptions` so telemetry hooks receive captured lowercase upstream response headers for each chat span
402
+ - Added automatic gateway/proxy detection from response headers (`litellm`, `helicone`, `portkey`, `openrouter`) and stamped `pi.gen_ai.gateway.*` span attributes for detected routing metadata
403
+ - Added exported `detectGatewayFromHeaders` API for header-based gateway detection
404
+
405
+ ## [15.1.0] - 2026-05-15
406
+ ### Breaking Changes
407
+
408
+ - Removed the `@gajae-code/agent-core/compaction/handoff` exports from the package surface, including `extractHandoffDocument`, `createHandoffContext`, and `createHandoffFileName`
409
+ - Removed legacy telemetry constants from the public enum surface (including `AGGREGATE_ATTR`, `GenAIAttr.System`, and old `gen_ai.*` extension keys such as `gen_ai.request.service_tier`/cost/tool status/handoff fields) and replaced them with `OpenAIAttr`, `PiGenAIAttr`, and `PiGenAIAggregateAttr`
410
+
411
+ ### Added
412
+
413
+ - Added `generateHandoff(messages, model, apiKey, options)` to `@gajae-code/agent-core/compaction` to generate a handoff document by calling the model directly, using live system/tool context and optional metadata
414
+ - Added generation filtering so the returned handoff document now includes only text content blocks from the model output
415
+ - Added support for defining `AgentTool` schemas with Zod, with legacy TypeBox schemas still supported when generating tool schemas for model calls
416
+ - Added `OpenAIAttr`, `PiGenAIAttr`, and `PiGenAIAggregateAttr` exports so consumers can reference the new `openai.*` and `pi.gen_ai.*` telemetry attribute keys directly
417
+ - Added `onChatUsage` to `AgentTelemetryConfig`, an always-fired hook receiving a `ChatUsageEvent` for every chat step that produced usage. The event carries the chat `span`, `agent`, `conversationId`, `stepNumber`, `model`, `provider`, `serviceTier`, `usage`, optional `cost`, and resolved dynamic `attributes` — independent of whether a `costEstimator` is configured.
418
+ - Added `agentLoopDetailed(...)` and `agentLoopContinueDetailed(...)` helpers that return the same event stream plus a `detailed()` result with run `telemetry` and `coverage`
419
+ - Added `onRunEnd` to `AgentTelemetryConfig` to receive `AgentRunSummary` and `AgentRunCoverage` at the end of each invocation
420
+ - Added run-level telemetry and coverage types/helpers (for example `AgentRunSummary`, `AgentRunCoverage`, `aggregateAgentRunSummaries`, and `aggregateAgentRunCoverage`) to package exports
421
+ - Added generic telemetry extension hooks for dynamic span attributes, provider/agent-name normalization, per-step cost deltas, warning callbacks, bounded summary content capture, and manual chat telemetry for non-loop model calls.
422
+ - Added opt-in OpenTelemetry instrumentation on the agent loop. Pass `telemetry: {}` (or a richer `AgentTelemetryConfig`) on `AgentLoopConfig` / `AgentOptions` / `createAgentSession({ telemetry })` to emit GenAI-semantic-convention spans plus `pi.gen_ai.*` extension attributes:
423
+ - `invoke_agent {agent.name}` wraps each `agentLoop` invocation with `gen_ai.operation.name=invoke_agent`, agent identity, conversation id, and `pi.gen_ai.agent.step.count`.
424
+ - `chat {model}` per provider call, parented under `invoke_agent`, with OTEL request/response/usage attributes (`gen_ai.request.{model,stream,temperature,top_p,top_k,max_tokens,presence_penalty,stop_sequences}`, `gen_ai.response.{model,id,finish_reasons,time_to_first_chunk}`, `gen_ai.usage.{input_tokens,output_tokens,cache_read.input_tokens,cache_creation.input_tokens,reasoning.output_tokens}`) and project extensions for reasoning effort, tool choice, available tools, usage totals, and cost.
425
+ - `execute_tool {tool.name}` per tool call, parented under `invoke_agent`, with `gen_ai.tool.{name,call.id,description,type}` plus the active context so user/MCP/provider spans created inside `tool.execute()` attach as children.
426
+ - One-shot `handoff` span available via the public `recordHandoff(...)` helper for agent-to-agent transitions.
427
+ - Added `AgentTelemetryConfig` hooks (`onSpanStart`, `onSpanEnd`, `costEstimator`), `agent` identity, `attributes` envelope merged onto every span, `captureMessageContent` toggle (defaults to the `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` env var) emitting OTEL-shaped `gen_ai.input.messages` / `gen_ai.output.messages` / `gen_ai.system_instructions` / `gen_ai.tool.call.arguments` / `gen_ai.tool.call.result`, and tracer/tracerName override surfaces.
428
+ - Added `Agent#setTelemetry(config)` so consumers can swap or disable instrumentation between invocations.
429
+ - Added `@opentelemetry/api` as a runtime dependency; SDK setup (exporters, samplers, processors) remains the host's responsibility per standard OTEL conventions. When no SDK is registered, helpers fall through to no-op spans with zero overhead.
430
+ - Added compaction APIs under `@gajae-code/agent-core/compaction`, including context compaction, branch summarization, handoff prompt/context helpers, pruning, token budgeting, prompt templates, and OpenAI `/responses/compact` helpers.
431
+
432
+ ### Changed
433
+
434
+ - Changed handoff document generation to force `toolChoice: "none"` when calling the model so tool invocation is disabled during generation
435
+ - Changed `chat` spans to emit normalized provider identifiers in `gen_ai.provider.name` via OTEL-style values (for example `google` to `gcp.gemini`) instead of the legacy `gen_ai.system` label
436
+ - Changed service-tier telemetry to emit `openai.request.service_tier`/`openai.response.service_tier` only when supported by provider via `shouldSendServiceTier`, rather than always using `gen_ai.request.service_tier`
437
+ - Changed captured message payloads so full capture now records OTEL-structured message parts with `pi.gen_ai.request.messages`, `pi.gen_ai.system_instructions`, and `gen_ai.output.messages` including assistant `finish_reason`
438
+ - Changed the `agent_end` event payload to include optional `telemetry` and `coverage` fields when telemetry is enabled, while keeping the legacy payload shape when disabled
439
+ - Changed `invoke_agent` spans to include aggregate `pi.gen_ai.agent.*` attributes for chat/tool counts, latency, usage, cost, errors, and tool coverage
440
+
441
+ ### Fixed
442
+
443
+ - Fixed intent-field injection for tool schemas defined with Zod by converting them to wire schema before mutation
444
+ - Fixed token accounting in `ChatUsageEvent` and usage summaries so `inputTokens` and `totalTokens` now include cached read/write input tokens
445
+ - Fixed `execute_tool` span attributes so `pi.gen_ai.tool.status` and `error.type` now reflect run-level tool outcomes (`ok`, `error`, `skipped`, `blocked`, `timeout`, `aborted`) instead of mapping all non-ok cases the same way
446
+ - Fixed `onRunEnd` callbacks to be safe and idempotent by invoking them once per run and swallowing thrown callback errors so they cannot fail or duplicate successful runs
447
+ - Fixed run telemetry to count interrupted, blocked, or otherwise skipped tool calls so run coverage and tool counters now include those paths
448
+ - Fixed chat failure handling so failed chat steps are still represented in run summaries when provider streaming throws before yielding an assistant message
449
+ - Fixed double-counting of interrupted tool calls in run summaries: the `runTool` early-return on a queued steering interrupt now defers to the post-batch tail sweep so each call is recorded exactly once
450
+ - Fixed `coverage.toolsInvoked` and run-summary tool counters under-reporting tool calls embedded in an aborted/errored assistant message — those calls now record a collector orphan with status `aborted` or `error`
451
+ - Fixed `AgentRunSummary.usage.inputTokens` so it now includes `cache_read` and `cache_write` input tokens, matching `ChatUsageEvent.inputTokens`
452
+ - Fixed span lifecycle hooks (`onSpanStart`, `onSpanEnd`) so a thrown user callback is caught and surfaced via `onTelemetryWarning` (`on_span_start_failed` / `on_span_end_failed`) instead of leaking and aborting the surrounding span
453
+ - Fixed unbounded recursion in summary content capture when a captured value contains a cyclic or deeply nested array — array recursion now respects the same depth cap as plain-object recursion and replaces back-references with `"[Circular]"`
454
+
455
+ ## [15.0.1] - 2026-05-14
456
+ ### Breaking Changes
457
+
458
+ - Raised the minimum required Bun version from >=1.3.7 to >=1.3.14
459
+
460
+ ## [14.9.5] - 2026-05-12
461
+
462
+ ### Added
463
+
464
+ - Added an `isError?: boolean` field on `AgentToolResult` so tools can flag a non-throwing failure (e.g. an aggregator that catches per-entry errors). `coerceToolResult` preserves the flag and the agent loop surfaces it as a tool error on the wire.
465
+
466
+ ## [14.9.3] - 2026-05-10
467
+ ### Added
468
+
469
+ - Added `onHarmonyLeak` option on `Agent`/loop config to receive GPT-5 Harmony leak audit callbacks
470
+ - Added harmony-leak detection and audit exports to the package index for programmatic leak detection and recovery hooks
471
+
472
+ ### Changed
473
+
474
+ - Changed OpenAI code provider model runs to detect GPT-5 Harmony protocol leakage during streaming and automatically retry or recover tool calls instead of sending contaminated arguments downstream
475
+
476
+ ### Security
477
+
478
+ - Hardened tool-call handling against leaked `to=functions.*` protocol tails by truncating or retrying before execution
479
+ - Hardened failure handling so repeated GPT-5 Harmony leak mitigation is retried only up to two times before escalating to an explicit error
480
+
481
+ ## [14.9.0] - 2026-05-10
482
+ ### Added
483
+
484
+ - Added `Agent#metadata` field forwarded to every API request; callers can set arbitrary provider metadata (e.g. `metadata.user_id`) once and have it applied to all subsequent stream calls without modifying per-call options
485
+ - Added `Agent#setMetadataResolver(fn)` for installing a function that resolves request metadata at call time. The `metadata` getter dispatches through the resolver on every read (including the snapshot taken per `prompt()`), so callers reflect mutable external state (e.g. live OAuth account UUID after a token refresh) without manual re-syncs. Plain `agent.metadata = …` continues to set a static value and clears any installed resolver.
486
+
487
+ ### Added
488
+
489
+ - Added an `onSseEvent` agent option and loop config forwarding path for raw provider SSE diagnostics.
490
+
491
+ ## [14.7.6] - 2026-05-07
492
+
493
+ ### Added
494
+
495
+ - Added `hideThinkingSummary` option/getter/setter on `Agent` and `AgentLoopConfig`. Forwarded to the underlying stream call so providers can omit reasoning/thinking summaries on demand.
496
+ ## [14.7.2] - 2026-05-06
497
+ ### Added
498
+
499
+ - Added `loadMode` option to `AgentTool` to mark built-in tools as `essential` for initial loading or `discoverable` for search activation
500
+ - Added optional `summary` field to `AgentTool` definitions for one-line text used in tool discovery indexes
501
+
502
+ ## [14.7.0] - 2026-05-04
503
+ ### Breaking Changes
504
+
505
+ - Changed `Agent` API types so `systemPrompt` is now a list of prompt strings, requiring callers to pass and update system prompts via string arrays
506
+
507
+ ### Changed
508
+
509
+ - Removed automatic project-context injection into each model call from loop logic
510
+
511
+ ### Removed
512
+
513
+ - Removed the `projectPrompt` field from agent state/context and the `setProjectPrompt` mutator
514
+
515
+ ## [14.6.2] - 2026-05-03
516
+
517
+ ### Fixed
518
+
519
+ - Fixed unhandled promise rejection when `getApiKey` or any other async error occurs during `streamAssistantResponse`: agent loop IIFEs now catch and route errors through `EventStream.fail()`, which terminates the `for await` loop and lets `Agent#runLoop`'s catch block create a proper error assistant message instead of crashing
520
+
521
+ ## [14.6.0] - 2026-05-02
522
+ ### Fixed
523
+
524
+ - Fixed request cancellation before provider events by emitting an aborted assistant message and ending the stream with `stopReason: "aborted"`
525
+
526
+ ## [14.5.10] - 2026-04-30
527
+
528
+ ### Added
529
+
530
+ - Added an `onResponse` stream option for observing provider response metadata after response headers arrive.
531
+
532
+ ## [14.2.0] - 2026-04-23
533
+
534
+ ### Changed
535
+
536
+ - Changed tool dispatch to match model-returned tool calls by either internal tool name or custom wire name, enabling custom OpenAI tool names such as `apply_patch`.
537
+
538
+ ## [14.0.1] - 2026-04-08
539
+ ### Added
540
+
541
+ - Added `onAssistantMessageEvent` callback option to inspect assistant streaming events before they are emitted, enabling abort decisions before buffered events continue flowing
542
+ - Added `setAssistantMessageEventInterceptor()` method to dynamically set or update the assistant message event interceptor
543
+
544
+ ## [13.13.0] - 2026-03-18
545
+
546
+ ### Added
547
+
548
+ - Added `startup.checkUpdate` setting, set to `true` by default, can be disabled to skip the update check on agent initialization
549
+
550
+ ## [13.12.7] - 2026-03-16
551
+
552
+ ### Added
553
+
554
+ - Added overload for `prompt()` method accepting a string input with optional options parameter
555
+
556
+ ### Fixed
557
+
558
+ - Fixed stale forced toolChoice being passed to provider after tools are refreshed mid-turn
559
+
560
+ ## [13.9.16] - 2026-03-10
561
+ ### Added
562
+
563
+ - Added `onPayload` option to `AgentOptions` to inspect or replace provider payloads before they are sent
564
+
565
+ ## [13.9.3] - 2026-03-07
566
+
567
+ ### Added
568
+
569
+ - Exported `ThinkingLevel` selector constants and types for configuring agent reasoning behavior
570
+ - Added `inherit` thinking level option to defer reasoning configuration to higher-level selectors
571
+ - Added `serviceTier` option to configure service tier for agent requests
572
+
573
+ ### Changed
574
+
575
+ - Changed `thinkingLevel` from required string to optional `Effort` type, allowing undefined state
576
+ - Updated `setThinkingLevel()` method to accept `Effort | undefined` instead of `ThinkingLevel` string
577
+
578
+ ## [13.4.0] - 2026-03-01
579
+ ### Added
580
+
581
+ - Added `getToolChoice` option to dynamically override tool choice per LLM call
582
+
583
+ ## [13.3.8] - 2026-02-28
584
+ ### Changed
585
+
586
+ - Changed intent field name from `agent__intent` to `_i` in tool schemas
587
+
588
+ ### Fixed
589
+
590
+ - Fixed synthetic tool result text formatting so aborted/error tool results no longer emit `Tool execution was aborted.: Request was aborted` style punctuation.
591
+ ## [13.3.7] - 2026-02-27
592
+ ### Added
593
+
594
+ - Added `lenientArgValidation` option to tools to allow graceful handling of argument validation errors by passing raw arguments to execute() instead of returning an error to the LLM
595
+
596
+ ## [13.3.1] - 2026-02-26
597
+ ### Added
598
+
599
+ - Added `topP`, `topK`, `minP`, `presencePenalty`, and `repetitionPenalty` options to `AgentOptions` for fine-grained sampling control
600
+ - Added getter and setter properties for sampling parameters on the `Agent` class to allow runtime configuration
601
+
602
+ ## [13.1.0] - 2026-02-23
603
+
604
+ ### Changed
605
+
606
+ - Removed per-tool `agent__intent` field description from injected schema to reduce token usage; intent format is now documented once in the system prompt instead of repeated in every tool definition
607
+ ## [12.19.0] - 2026-02-22
608
+ ### Changed
609
+
610
+ - Updated tool result messages to include error details when tool execution fails
611
+
612
+ ## [12.14.0] - 2026-02-19
613
+
614
+ ### Added
615
+
616
+ - Added `intentTracing` option to enable intent goal extraction from tool calls, allowing models to specify high-level goals via a required `_intent` field that is automatically injected into tool schemas and stripped from arguments before execution
617
+
618
+ ## [12.11.0] - 2026-02-19
619
+
620
+ ### Added
621
+
622
+ - Exported `AgentBusyError` exception class for handling concurrent agent operations
623
+
624
+ ### Changed
625
+
626
+ - Agent now throws `AgentBusyError` instead of generic `Error` when attempting concurrent operations
627
+
628
+ ## [12.8.0] - 2026-02-16
629
+
630
+ ### Added
631
+
632
+ - Added `transformToolCallArguments` option to `AgentOptions` and `AgentLoopConfig` for transforming tool call arguments before execution (e.g. secret deobfuscation)
633
+
634
+ ## [12.2.0] - 2026-02-13
635
+
636
+ ### Added
637
+
638
+ - Added `providerSessionState` option to share provider state map for session-scoped transport and session caches
639
+ - Added `preferWebsockets` option to hint that websocket transport should be preferred when supported by the provider implementation
640
+
641
+ ## [11.10.0] - 2026-02-10
642
+
643
+ ### Added
644
+
645
+ - Added `temperature` option to `AgentOptions` to control LLM sampling temperature
646
+ - Added `temperature` getter and setter to `Agent` class for runtime configuration
647
+
648
+ ## [11.6.0] - 2026-02-07
649
+
650
+ ### Added
651
+
652
+ - Added `hasQueuedMessages()` method to check for pending steering/follow-up messages
653
+ - Resume queued steering and follow-up messages from `continue()` after auto-compaction
654
+
655
+ ### Changed
656
+
657
+ - Extracted `dequeueSteeringMessages()` and `dequeueFollowUpMessages()` from inline config callbacks
658
+ - Added `skipInitialSteeringPoll` option to `_runLoop()` for correct queue resume ordering
659
+
660
+ ## [11.3.0] - 2026-02-06
661
+
662
+ ### Added
663
+
664
+ - Added `maxRetryDelayMs` option to AgentOptions to cap server-requested retry delays, allowing higher-level retry logic to handle long waits with user visibility
665
+
666
+ ### Changed
667
+
668
+ - Updated ThinkingLevel documentation to include support for gpt-5.3 and gpt-5.3-openai-code models with 'xhigh' thinking level
669
+
670
+ ## [11.2.0] - 2026-02-05
671
+
672
+ ### Fixed
673
+
674
+ - Fixed handling of aborted requests to properly throw abort errors when stream terminates without a terminal event
675
+
676
+ ## [10.5.0] - 2026-02-04
677
+
678
+ ### Added
679
+
680
+ - Added `concurrency` option to `AgentTool` to control tool scheduling: "shared" (default, runs in parallel) or "exclusive" (runs alone)
681
+ - Implemented parallel execution of shared tools within a single agent turn for improved performance
682
+
683
+ ### Changed
684
+
685
+ - Refactored tool execution to support concurrent scheduling with proper interrupt handling and steering message checks
686
+
687
+ ## [9.2.2] - 2026-01-31
688
+
689
+ ### Added
690
+
691
+ - Added toolChoice option to AgentPromptOptions for controlling tool selection
692
+
693
+ ## [8.2.0] - 2026-01-24
694
+
695
+ ### Changed
696
+
697
+ - Updated TypeScript configuration for better publish-time configuration handling with tsconfig.publish.json
698
+
699
+ ## [8.0.0] - 2026-01-23
700
+
701
+ ### Added
702
+
703
+ - Added `nonAbortable` option to tools to ignore abort signals during execution
704
+
705
+ ## [6.8.0] - 2026-01-20
706
+
707
+ ### Changed
708
+
709
+ - Updated proxy stream processing to use utility function for reading lines
710
+
711
+ ## [6.2.0] - 2026-01-19
712
+
713
+ ### Added
714
+
715
+ - Enhanced getToolContext to receive tool call batch information including batchId, index, total count, and tool call details
716
+
717
+ ## [5.6.7] - 2026-01-18
718
+
719
+ ### Fixed
720
+
721
+ - Added proper tool result messages for tool calls that are aborted or error out
722
+ - Ensured tool_use/tool_result pairing is maintained when tool execution fails
723
+
724
+ ## [4.6.0] - 2026-01-12
725
+
726
+ ### Changed
727
+
728
+ - Modified assistant message handling to split messages around tool results for improved readability when using Cursor tools
729
+
730
+ ### Fixed
731
+
732
+ - Fixed tool result ordering in Cursor mode by buffering results and emitting them at the correct position within assistant messages
733
+
734
+ ## [4.3.0] - 2026-01-11
735
+
736
+ ### Added
737
+
738
+ - Added `cursorExecHandlers` and `cursorOnToolResult` options for local tool execution with cursor-based streaming
739
+ - Added `emitExternalEvent` method to allow external event injection into the agent state
740
+
741
+ ## [4.0.0] - 2026-01-10
742
+
743
+ ### Added
744
+
745
+ - Added `popLastSteer()` and `popLastFollowUp()` methods to remove and return the last queued message (LIFO) for dequeue operations
746
+ - `thinkingBudgets` option on `Agent` and `AgentOptions` to customize token budgets per thinking level
747
+ - `sessionId` option on `Agent` to forward session identifiers to LLM providers for session-based caching
748
+
749
+ ### Fixed
750
+
751
+ - `minimal` thinking level now maps to `minimal` reasoning effort instead of being treated as `low`
752
+
753
+ ## [3.33.0] - 2026-01-08
754
+
755
+ ### Fixed
756
+
757
+ - Ensured aborted assistant responses always include an error message for callers.
758
+ - Filtered thinking blocks from Cerebras request context to keep multi-turn prompts compatible.
759
+
760
+ ## [3.21.0] - 2026-01-06
761
+
762
+ ### Changed
763
+
764
+ - Switched from local `@gajae-code/ai` to upstream `@gajae-code/ai` package
765
+
766
+ ### Added
767
+
768
+ - Added `sessionId` option for provider caching (e.g., OpenAI code provider session-based prompt caching)
769
+ - Added `sessionId` getter/setter on Agent class for runtime session switching
770
+
771
+ ## [3.20.0] - 2026-01-06
772
+
773
+ ### Breaking Changes
774
+
775
+ - Replaced `queueMessage`/`queueMode` with steering + follow-up queues: use `steer`, `setSteeringMode`, and `getSteeringMode` for mid-run interruptions, and `followUp`, `setFollowUpMode`, and `getFollowUpMode` for post-turn messages
776
+ - Agent loop callbacks now use `getSteeringMessages` and `getFollowUpMessages` instead of `getQueuedMessages`
777
+
778
+ ### Added
779
+
780
+ - Added follow-up message queue support so new user messages can continue a run after the agent would otherwise stop
781
+ - Added `RenderResultOptions.spinnerFrame` for animated tool-result rendering
782
+
783
+ ### Changed
784
+
785
+ - `prompt()` and `continue()` now throw when the agent is already streaming; use steering or follow-up queues instead
786
+
787
+ ## [3.4.1337] - 2026-01-03
788
+
789
+ ### Added
790
+
791
+ - Added `popMessage()` method to Agent class for removing and retrieving the last message
792
+ - Added abort signal checks during response streaming for faster interruption handling
793
+
794
+ ### Fixed
795
+
796
+ - Fixed abort handling to properly return aborted message state when stream is interrupted mid-response
797
+
798
+ ## [1.341.0] - 2026-01-03
799
+
800
+ ### Added
801
+
802
+ - Added `interruptMode` option to control when queued messages interrupt tool execution.
803
+ - Implemented "immediate" mode (default) to check queue after each tool and interrupt remaining tools.
804
+ - Implemented "wait" mode to defer queue processing until the entire turn completes.
805
+ - Added getter and setter methods for `interruptMode` on Agent class.
806
+
807
+ ## [1.337.1] - 2026-01-02
808
+
809
+ ### Changed
810
+
811
+ - Forked to @gajae-code scope with unified versioning across all packages
812
+
813
+ ## [1.337.0] - 2026-01-02
814
+
815
+ Initial release under @gajae-code scope. See previous releases at [badlogic/pi-mono](https://github.com/badlogic/pi-mono).
816
+
817
+ ## [0.31.0] - 2026-01-02
818
+
819
+ ### Breaking Changes
820
+
821
+ - **Transport abstraction removed**: `ProviderTransport`, `AppTransport`, and `AgentTransport` interface have been removed. Use the `streamFn` option directly for custom streaming implementations.
822
+
823
+ - **Agent options renamed**:
824
+ - `transport` → removed (use `streamFn` instead)
825
+ - `messageTransformer` → `convertToLlm`
826
+ - `preprocessor` → `transformContext`
827
+
828
+ - **`AppMessage` renamed to `AgentMessage`**: All references to `AppMessage` have been renamed to `AgentMessage` for consistency.
829
+
830
+ - **`CustomMessages` renamed to `CustomAgentMessages`**: The declaration merging interface has been renamed.
831
+
832
+ - **`UserMessageWithAttachments` and `Attachment` types removed**: Attachment handling is now the responsibility of the `convertToLlm` function.
833
+
834
+ - **Agent loop moved from `@gajae-code/ai`**: The `agentLoop`, `agentLoopContinue`, and related types have moved to this package. Import from `@gajae-code/pi-agent` instead.
835
+
836
+ ### Added
837
+
838
+ - `streamFn` option on `Agent` for custom stream implementations. Default uses `streamSimple` from pi-ai.
839
+
840
+ - `streamProxy()` utility function for browser apps that need to proxy LLM calls through a backend server. Replaces the removed `AppTransport`.
841
+
842
+ - `getApiKey` option for dynamic API key resolution (useful for expiring OAuth tokens like GitHub Copilot).
843
+
844
+ - `agentLoop()` and `agentLoopContinue()` low-level functions for running the agent loop without the `Agent` class wrapper.
845
+
846
+ - New exported types: `AgentLoopConfig`, `AgentContext`, `AgentTool`, `AgentToolResult`, `AgentToolUpdateCallback`, `StreamFn`.
847
+
848
+ ### Changed
849
+
850
+ - `Agent` constructor now has all options optional (empty options use defaults).
851
+
852
+ - `queueMessage()` is now synchronous (no longer returns a Promise).