agent-accelerator 0.2.0 → 0.4.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.
package/README.md CHANGED
@@ -126,16 +126,17 @@ An `Agent` holds :
126
126
  | `subagents` | `SubAgent[] \| Agent[]` | Pre-defined workers. Each worker becomes a callable tool. Useful for fixed roles such as researcher or critic. |
127
127
  | `subagentModel` | `string \| ModelSpec \| ModelProviderInstance` | Developer-only model for dynamically spawned workers. Never choosable by the Main Agent. Overridden by `dynamicSubagents.model`. Falls back to `SUB_AGENT_MODEL`. |
128
128
  | `dynamicSubagents` | `DynamicSubagentsConfig` | Enables and constrains LLM-spawned stateless workers: `{ enabled, model?, maxSpawn?, thinkingLevel?, tools?, timeout? }`. See [Dynamic delegation](#dynamic-delegation). |
129
- | `thinkingLevel` | `ThinkingLevel` | `none \| dynamic \| minimal \| low \| medium \| high \| xhigh`. Validated against the model catalog before a request. |
129
+ | `thinkingLevel` | `ThinkingLevel` | `none \| dynamic \| minimal \| low \| medium \| high \| xhigh \| max`. Validated against the model catalog before a request. |
130
130
  | `cache` | `CacheConfig` | `{ retention, sessionId, cachedContentId, ttlSeconds }`. Controls cache reuse. |
131
131
  | `serviceTier` | `"flex" \| "priority"` | Cost / priority routing where supported. Omit for standard routing. |
132
132
  | `bypassInputFileModality` | `boolean` | When `true`, `file` parts are converted client-side to Markdown for models lacking native support. Capable models still receive files natively. Defaults to `false`. |
133
- | `maxTurns` | `number` | Maximum model → tool → model loops per `run`. Defaults to `10`. |
133
+ | `maxTurns` | `number` | Maximum model → tool → model loops per `run`. Infinite by default (`0` or omitted = no limit). Hitting a finite limit with pending tool calls warns and sets `finishReason: "max_turns"`. |
134
134
  | `sessionId` | `string` | Stable identifier used for cache affinity. Auto-generated when omitted. |
135
135
  | `headers` | `Record<string,string>` | Additional headers merged into every request. |
136
136
  | `apiKey` | `string` | Overrides environment-based API-key lookup for this agent. |
137
137
  | `baseUrl` | `string` | Overrides the default endpoint for this agent. |
138
138
  | `stateless` | `boolean` | When `true`, history is cleared before and after each `run`. Useful for one-shot evaluators. Defaults to `false`. |
139
+ | `persist` | `{ dir?: string; file?: string }` | Durable sessions: rewrites the session file after every step (user/assistant/tool/sub-agent). `{ dir }` uses `sessions/<sessionId>/session.json`, `{ file }` a single `.session.json`. Writes are atomic and never fail a turn. |
139
140
 
140
141
  When `dynamicSubagents.enabled` is set without a resolvable worker model, construction throws `SubAgentModelError`.
141
142
 
@@ -146,6 +147,12 @@ await agent.run(prompt, opts?) // non-streaming, or streaming when opts.stream i
146
147
  agent.ask(prompt, optsOrBool?) // string deltas when streaming, otherwise same as run
147
148
  agent.stream(prompt, opts?) // AssistantMessageEventStream
148
149
  agent.reset() // clears messages + signatures, keeps config
150
+ agent.exportSession(telemetry?) // storable snapshot for saveSessionFile
151
+ agent.importSession(saved) // restores messages + config from loadSessionFile
152
+ agent.track(trackingId) // live snapshot of one sub-agent worker (`NAME-{TrackingID}`)
153
+ agent.listTrackedSubAgents() // TrackingIDs of known workers
154
+ agent.subscribeToSubAgent(id, fn) // live worker updates, returns unsubscribe fn
155
+ agent.persistNow() // rewrites the persist target now (no-op unless persist is set)
149
156
  ```
150
157
 
151
158
  `prompt` accepts `string | ContentPart[]`.
@@ -159,8 +166,9 @@ Use `ContentPart[]` when sending images, audio, or video alongside text.
159
166
  | `stream` | When `true`, returns a stream instead of a regular response promise. |
160
167
  | `onDelta(delta, event)` | Called for each text chunk. Use to render answers live. |
161
168
  | `onThinkingDelta(delta, event)` | Called for each reasoning chunk. Use to render reasoning separately. |
162
- | `onEvent(event)` | Called for every event: `text_delta`, `thinking_delta`, `tool_call_complete`, `tool_result`, `subagent_complete`, `usage`, `done`, and `error`. |
169
+ | `onEvent(event)` | Called for every event: `text_delta`, `thinking_delta`, `tool_call_complete`, `tool_result`, `subagent_complete`, `subagent_delta`, `usage`, `done`, and `error`. |
163
170
  | `wrapThinking` | Wraps reasoning as `<think>\n...\n</think>\n\n`, allowing UIs to render it without maintaining separate state. |
171
+ | `onTurn(turn)` | Called after every model/tool turn with `{ turns, text?, thinking?, toolCalls?, toolResults? }`. Drives sub-agent step logs and persistence. |
164
172
  | `additionalContext` | Added only to the current user turn. Keeps the system prompt stable for better caching. |
165
173
  | `sessionId` | Per-run session override. |
166
174
  | `headers` | Per-run header merge. |
@@ -290,6 +298,8 @@ A `spawn_subagents` tool is injected with the following task shape:
290
298
  - `tools` — developer-owned pool. Workers get zero tools unless the Main Agent grants a per-task `tools` subset by name (unknown names are ignored), keeping worker context small.
291
299
  - `timeout` (ms) — `0` = no limit, `-1` = the Main Agent sets a per-task `timeoutMs`, `>0` = fixed limit for every worker. Timed-out workers report an error entry; the rest of the batch still completes.
292
300
  - Workers are stateless: one task in, one result out, then shut down. No history, no recursion. The Main Agent cannot choose worker models or reasoning levels.
301
+ - Worker names use UPPER-KEBAB (`HBM-PRICING-ANALYST`). Each worker gets a system-generated 32-char TrackingID, displayed as `NAME-{TrackingID}` (e.g. `HBM-PRICING-ANALYST-9f2c…`).
302
+ - Workers stream internally: thinking/text deltas update the worker trace live (`agent.track(id)`, `subscribeToSubAgent`) and surface on the parent stream as `subagent_delta` events.
293
303
 
294
304
  ```ts
295
305
  const res = await agent.run("Audit auth pipeline and write a threat model");
@@ -488,7 +498,7 @@ Turns chain statefully through `previous_interaction_id` per session, falling ba
488
498
  Thinking levels map to `thinking_level`, with `thinking_summaries` enabled whenever thinking is active:
489
499
 
490
500
  ```text
491
- minimal | low | medium | high (xhigh clamps to high; none is unsupported and omitted; dynamic omits)
501
+ minimal | low | medium | high (xhigh/max clamp to high; none is unsupported and omitted; dynamic omits)
492
502
  ```
493
503
 
494
504
  Google-specific handling includes:
@@ -515,7 +525,7 @@ Every turn is stateless: the full history is sent explicitly with `store: false`
515
525
  Thinking levels map to `reasoning.effort` verbatim:
516
526
 
517
527
  ```text
518
- none | minimal | low | medium | high | xhigh (dynamic omits — server default)
528
+ none | minimal | low | medium | high | xhigh | max (dynamic omits — server default)
519
529
  ```
520
530
 
521
531
  It also:
@@ -536,7 +546,7 @@ Session affinity is a top-level body `session_id` plus the `x-session-id` header
536
546
  Thinking levels map to `reasoning.effort` verbatim:
537
547
 
538
548
  ```text
539
- none | minimal | low | medium | high | xhigh (dynamic omits — server default)
549
+ none | minimal | low | medium | high | xhigh | max (dynamic omits — server default)
540
550
  ```
541
551
 
542
552
  It also:
@@ -591,14 +601,15 @@ ThinkingLevel =
591
601
  | "low"
592
602
  | "medium"
593
603
  | "high"
594
- | "xhigh";
604
+ | "xhigh"
605
+ | "max";
595
606
  ```
596
607
 
597
608
  ### Thinking Levels
598
609
 
599
610
  * `none` — disables thinking where supported.
600
611
  * `dynamic` — allows the model to decide.
601
- * `minimal`, `low`, `medium`, `high`, `xhigh` — request increasing levels of reasoning where supported.
612
+ * `minimal`, `low`, `medium`, `high`, `xhigh`, `max` — request increasing levels of reasoning where supported.
602
613
 
603
614
  Thinking can be configured on the `Agent` or through `ModelProvider.*(..., { thinkingLevel })`.
604
615
 
@@ -729,6 +740,7 @@ StreamEvent {
729
740
  toolCall?,
730
741
  toolResult?,
731
742
  subagent?,
743
+ subagentTrackingId?,
732
744
  usage?,
733
745
  responseId?,
734
746
  finishReason?,
@@ -754,12 +766,13 @@ tool_call_delta
754
766
  tool_call_complete
755
767
  tool_result
756
768
  subagent_complete
769
+ subagent_delta
757
770
  usage
758
771
  done
759
772
  error
760
773
  ```
761
774
 
762
- Emitted in practice: `start`, `text_delta`, `thinking_delta`, `tool_call_complete`, `tool_result`, `subagent_complete`, `usage`, `done`, `error`. The rest exist in the type for forward compatibility.
775
+ Emitted in practice: `start`, `text_delta`, `thinking_delta`, `tool_call_complete`, `tool_result`, `subagent_complete`, `subagent_delta`, `usage`, `done`, `error`. The rest exist in the type for forward compatibility.
763
776
 
764
777
  Use:
765
778
 
@@ -767,6 +780,7 @@ Use:
767
780
  * `thinking_delta` for reasoning output.
768
781
  * `tool_call_complete` / `tool_result` for tool progress.
769
782
  * `subagent_complete` for each completed worker during streaming multi-agent runs.
783
+ * `subagent_delta` for live worker thinking/text (`subagentTrackingId` + `delta`/`thinkingDelta` + partials). Render per-worker; never merge into the parent answer.
770
784
  * `usage` for interim usage counts.
771
785
  * `done` for final usage and completion information.
772
786
 
@@ -836,10 +850,33 @@ SubAgentExecutionMetadata {
836
850
  toolCalls?,
837
851
  raw?,
838
852
  isError?,
839
- error?
853
+ error?,
854
+ trackingId?,
855
+ sessionId?,
856
+ parentSessionId?,
857
+ steps?
840
858
  }
841
859
  ```
842
860
 
861
+ `finishReason` is `"max_turns"` when a finite `maxTurns` limit stopped the run with tool calls still pending (plus a console warning naming the dropped tools).
862
+
863
+ ### SubAgentStep
864
+
865
+ ```ts
866
+ SubAgentStep {
867
+ turn,
868
+ type, // "assistant" | "tool_call" | "tool_result"
869
+ name?,
870
+ text?,
871
+ thinking?,
872
+ isError?,
873
+ timestamp,
874
+ partial? // true while the worker is still streaming this step
875
+ }
876
+ ```
877
+
878
+ `agent.track(id)` returns these live; `partial` entries finalize when the worker's turn completes.
879
+
843
880
  ### TokenUsage
844
881
 
845
882
  ```ts
@@ -1089,6 +1126,8 @@ never in the gitignored snapshot.
1089
1126
  ## Utils
1090
1127
 
1091
1128
  * `createSessionId(prefix="accel")` — creates a UUID-based session ID clamped to 64 characters for affinity.
1129
+ * `createTrackingId()` — system-generated 32-char TrackingID for one sub-agent worker (`NAME-{TrackingID}`).
1130
+ * `createChildSessionId(parentId, tag)` / `createFixedChildSessionId(parentId, name)` / `isSessionDescendant(child, parent)` — provider-safe (≤64 chars) child session IDs with parent-hash lineage.
1092
1131
  * `getEnv(key, fallback?)` — resolves an environment variable.
1093
1132
  * `getApiKey(provider, explicit?, env?)` — resolves API keys using the configured environment lookup order.
1094
1133
  * `buildSessionHeaders(provider, cache?, custom?, sessionId?)` — builds provider-specific affinity headers. Normally handled automatically.
@@ -1130,6 +1169,9 @@ bun run examples/08-multimodal_video.ts
1130
1169
 
1131
1170
  bun run examples/10-document_markdown.ts
1132
1171
  # document → Markdown preprocessing (any model, optional @firecrawl/anydoc peer)
1172
+
1173
+ bun run examples/11-session-identity.ts
1174
+ # sub-agent TrackingIDs, live worker boxes, lineage, track(), durable sessions
1133
1175
  ```
1134
1176
 
1135
1177
  Every example ends its `run()` with `.catch(fail)` (`examples/_shared.ts`),
@@ -1138,17 +1180,54 @@ so failures print one line and exit `1` — no stack dumps.
1138
1180
  The chat example persists conversations to:
1139
1181
 
1140
1182
  ```text
1141
- .session.jsonl
1183
+ sessions/<sessionId>/session.json (+ media/ for images, audio, video, files)
1142
1184
  ```
1143
1185
 
1144
- It resumes from that file on next launch.
1186
+ It resumes the most recent session on next launch (legacy `.session.json`/`.session.jsonl` files still load) and prints a resume banner:
1145
1187
 
1146
- It also displays per-turn:
1188
+ ```text
1189
+ ↺ Previous session loaded • accel-1a2b… (.session.json) • 12 messages • google/gemini-3.5-flash-lite • total-CH82.4% • $0.013 total
1190
+ ```
1191
+
1192
+ It also displays per-turn and session totals on one line:
1147
1193
 
1148
1194
  ```text
1149
- input / output / cached / cost / context %
1195
+ ↑turn ↓turn CRturn turn-CH% | ↑total ↓total CRtotal total-CH% $total(+turn) ctx%/window
1196
+ ```
1197
+
1198
+ ### Session persistence
1199
+
1200
+ ```ts
1201
+ import {
1202
+ Agent,
1203
+ loadSessionFile,
1204
+ saveSessionFile,
1205
+ SessionTelemetry,
1206
+ formatSessionBanner,
1207
+ } from "agent-accelerator";
1208
+
1209
+ const saved = loadSessionFile(".session.json");
1210
+ const telemetry = SessionTelemetry.fromSaved(saved);
1211
+
1212
+ const agent = new Agent({
1213
+ model: saved?.model ?? process.env.MODEL,
1214
+ sessionId: saved?.sessionId,
1215
+ });
1216
+
1217
+ if (saved) agent.importSession(saved);
1218
+
1219
+ const res = await agent.run("Hello");
1220
+ telemetry.add(res.usage, agent.modelStringOrSpec as string);
1221
+ saveSessionFile(".session.json", agent, telemetry);
1150
1222
  ```
1151
1223
 
1224
+ * `agent.exportSession(telemetry)` / `agent.importSession(saved)` round-trip messages, system prompt, model, thinking level, instructions, cache, worker model, and sub-agent traces without touching `AgentContext` internals.
1225
+ * `SessionTelemetry` accumulates `input / output / cacheRead / cacheWrite / reasoning / cost`, with clamped `turnHitRate()` / `totalHitRate()`, a dual `formatBar(res)`, and `formatSessionBanner(saved, telemetry, path)` for startup.
1226
+ * Files are pretty-printed JSON (2-space indent), written atomically (temp + rename). Cost prefers provider-reported totals and falls back to catalog pricing.
1227
+ * Binary media (bytes, data URLs, base64) is extracted to `media/` on save via `saveSessionDir("sessions", agent, telemetry)` → `sessions/<sessionId>/{session.json, media/*}`; remote URLs and local paths stay references. `loadSessionDir(dir)` resolves `media/…` refs back to absolute paths, and `findLatestSessionDir("sessions")` resumes the most recent session.
1228
+ * Sub-agent traces persist in a dedicated `subagents` section keyed by TrackingID (`{ trackingId, name, sessionId, parentSessionId, status, task, turns, usage, steps, text }`). Files stay lean: redundant `rawArguments` and repeated step text are dropped on save (rebuilt/kept live in memory).
1229
+ * With `persist: { dir }` or `{ file }`, the session file is rewritten after every step, so a crash loses at most the in-flight step.
1230
+
1152
1231
  ---
1153
1232
  ## Scripts and Structure
1154
1233
 
@@ -1164,6 +1243,7 @@ bun run update-models # refresh model catalog cache (supports --force, --ttl=24h
1164
1243
  ```text
1165
1244
  src/
1166
1245
  ├── agent/ # Agent, context, loop, delegation, subagent
1246
+ ├── session/ # Session persistence + telemetry (snapshots, hit rates, .session.json store)
1167
1247
  ├── providers/ # native REST adapters (google/openai/openrouter/openai-compat) + registry + canonical contract
1168
1248
  ├── models/ # Dynamic catalog cache, parser, verified overrides
1169
1249
  ├── data/ # Dynamic model catalog cache (gitignored, excluded from bundle)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-accelerator",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "High-performance SDK for AI agents with a unified API across AI providers. Optimized for high cache hit rates, observability, and seamless agent orchestration. Built to power production-grade agentic systems and harnesses for teams at any scale.",
5
5
  "license": "MIT",
6
6
  "author": "Sashvat Bharat",