agent-accelerator 0.5.0 → 0.5.2

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/src/agent/loop.ts CHANGED
@@ -20,7 +20,6 @@ import {
20
20
  traceToolEvent,
21
21
  } from "../tools/executor.ts";
22
22
  import { getModelFromCatalog, ensureModelCatalogFresh, validateModelThinking } from "../models/catalog.ts";
23
- import { preprocessFilePartsForBypass } from "../utils/documents.ts";
24
23
  import { enforceFileAccess } from "../utils/safe-io.ts";
25
24
  import { isSubagentResult, normalizeSubagentMetadata } from "../tools/subagent-result.ts";
26
25
  import { BudgetExceededError } from "../types/errors.ts";
@@ -49,8 +48,6 @@ export interface AgentLoopConfig {
49
48
  options?: ProviderRequestOptions;
50
49
  runOptions?: AgentRunOptions;
51
50
  maxTurns?: number;
52
- /** Convert `file` parts client-side for pdf-incapable models (see Agent flag). */
53
- bypassInputFileModality?: boolean;
54
51
  /** Local-file policy: media paths must resolve inside `roots` (see `AgentConfig.fileAccess`). */
55
52
  fileAccess?: { roots?: string[] };
56
53
  /**
@@ -343,8 +340,7 @@ function loopSessionId(config: AgentLoopConfig): string | undefined {
343
340
  try {
344
341
  return (
345
342
  (config.runOptions as { sessionId?: string } | undefined)?.sessionId ||
346
- (config.options as { sessionId?: string } | undefined)?.sessionId ||
347
- (config.options as { cache?: { sessionId?: string } } | undefined)?.cache?.sessionId
343
+ (config.options as { sessionId?: string } | undefined)?.sessionId
348
344
  );
349
345
  } catch { return undefined; }
350
346
  }
@@ -622,15 +618,6 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
622
618
  const repeatCounts = new Map<string, number>();
623
619
 
624
620
  try {
625
- if (config.bypassInputFileModality) {
626
- await preprocessFilePartsForBypass(config.context.messages, {
627
- providerId: provider.id,
628
- modelId,
629
- signal: runOptions?.signal,
630
- roots: config.fileAccess?.roots,
631
- });
632
- }
633
-
634
621
  const standardTools = toStandardToolDeclarations(tools);
635
622
 
636
623
  while (turns < maxTurns) {
@@ -647,8 +634,7 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
647
634
 
648
635
  const providerOptions: ProviderRequestOptions = {
649
636
  ...options,
650
- // Merge sessionId from cache or top-level (C4 fix: read both)
651
- sessionId: runOptions?.sessionId || options?.sessionId || options?.cache?.sessionId,
637
+ sessionId: runOptions?.sessionId || options?.sessionId,
652
638
  cache: options?.cache,
653
639
  tools: standardTools.length > 0 ? standardTools : undefined,
654
640
  signal: runOptions?.signal,
@@ -680,31 +666,30 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
680
666
  if (gTier === "paid" || gTier === "free") providerOptions.googleTier = gTier;
681
667
  } catch {}
682
668
 
669
+ // A long-running call (e.g. Google long decode) times each HTTP request itself: no whole-call race.
670
+ const longRunning = provider.isLongRunning?.(modelId, providerOptions) === true;
683
671
  const genResult = await generateWithTimeout(
684
672
  () => provider.generate(
685
673
  modelId,
686
674
  {
687
675
  systemPrompt: context.systemPrompt,
688
676
  messages: context.messages,
689
- cachedContentId: context.cachedContentId,
690
677
  },
691
678
  providerOptions
692
679
  ),
693
- limits.requestTimeoutMs
680
+ longRunning ? Infinity : limits.requestTimeoutMs
694
681
  );
695
682
 
696
683
  finalResult = genResult;
697
684
 
698
685
  // Canonical session routing: lets adapters detect provider switches.
699
686
  noteProviderTurn(
700
- runOptions?.sessionId || options?.sessionId || options?.cache?.sessionId,
687
+ runOptions?.sessionId || options?.sessionId,
701
688
  provider.id
702
689
  );
703
690
 
704
- // Thinking is exposed via events/traces and onTurn (see shouldExposeThinking,
705
- // default true). Promoting thinking to answer text is gated (Q-15, default
706
- // OFF): without the explicit opt-in the run returns the provider's empty
707
- // text with its finishReason instead of fabricating an answer from reasoning.
691
+ // Thinking is exposed via events/traces and onTurn. Promoting it to answer text is gated (Q-15,
692
+ // default OFF): without the opt-in the run returns the provider's empty text and finishReason.
708
693
  if ((!genResult.text || genResult.text.trim() === "") && (!genResult.toolCalls || genResult.toolCalls.length === 0) && genResult.thinking) {
709
694
  if (shouldPromoteThinkingToAnswer(config, runOptions)) {
710
695
  if (genResult.thinking.includes("</think>")) {
@@ -727,7 +712,8 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
727
712
  genResult.text,
728
713
  genResult.toolCalls,
729
714
  genResult.thinking,
730
- genResult.thoughtSignature
715
+ genResult.thoughtSignature,
716
+ genResult.providerSteps
731
717
  );
732
718
 
733
719
  // Thinking-trace telemetry (observability-only, full text, no limit):
@@ -742,7 +728,7 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
742
728
  turns,
743
729
  model: modelId,
744
730
  provider: provider.id,
745
- sessionId: runOptions?.sessionId || options?.sessionId || options?.cache?.sessionId,
731
+ sessionId: runOptions?.sessionId || options?.sessionId,
746
732
  thinking: genResult.thinking,
747
733
  ...(genResult.thoughtSignature ? { thoughtSignature: genResult.thoughtSignature } : {}),
748
734
  },
@@ -763,14 +749,6 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
763
749
  emitTurn(runOptions, { turns, text: genResult.text, thinking: genResult.thinking });
764
750
  if (noToolSteered.length > 0) {
765
751
  try { config.onSteerInjected?.(noToolSteered); } catch {}
766
- if (config.bypassInputFileModality) {
767
- await preprocessFilePartsForBypass(config.context.messages, {
768
- providerId: provider.id,
769
- modelId,
770
- signal: runOptions?.signal,
771
- roots: config.fileAccess?.roots,
772
- });
773
- }
774
752
  }
775
753
  emitProgress(config);
776
754
  if (noToolSteered.length > 0) continue;
@@ -795,7 +773,7 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
795
773
  repeatCounts,
796
774
  agentName,
797
775
  signal: runOptions?.signal,
798
- sessionId: runOptions?.sessionId || options?.sessionId || options?.cache?.sessionId,
776
+ sessionId: runOptions?.sessionId || options?.sessionId,
799
777
  });
800
778
  const results = guarded.results;
801
779
  previousToolCallFingerprints = guarded.fingerprints;
@@ -839,14 +817,6 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
839
817
  const toolSteered = drainSteerInbox(context, config.steerInbox);
840
818
  if (toolSteered.length > 0) {
841
819
  try { config.onSteerInjected?.(toolSteered); } catch {}
842
- if (config.bypassInputFileModality) {
843
- await preprocessFilePartsForBypass(config.context.messages, {
844
- providerId: provider.id,
845
- modelId,
846
- signal: runOptions?.signal,
847
- roots: config.fileAccess?.roots,
848
- });
849
- }
850
820
  }
851
821
  emitProgress(config);
852
822
 
@@ -1005,14 +975,6 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
1005
975
  }
1006
976
  }
1007
977
  }
1008
- if (config.bypassInputFileModality) {
1009
- await preprocessFilePartsForBypass(config.context.messages, {
1010
- providerId: config.provider.id,
1011
- modelId: config.modelId,
1012
- signal: config.runOptions?.signal,
1013
- roots: config.fileAccess?.roots,
1014
- });
1015
- }
1016
978
  const {
1017
979
  agentName,
1018
980
  provider,
@@ -1067,7 +1029,7 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
1067
1029
 
1068
1030
  const providerOptions: ProviderRequestOptions = {
1069
1031
  ...options,
1070
- sessionId: runOptions?.sessionId || options?.sessionId || options?.cache?.sessionId,
1032
+ sessionId: runOptions?.sessionId || options?.sessionId,
1071
1033
  cache: options?.cache,
1072
1034
  tools: standardTools.length > 0 ? standardTools : undefined,
1073
1035
  signal: linked.signal,
@@ -1094,12 +1056,12 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
1094
1056
  if (gTier === "paid" || gTier === "free") providerOptions.googleTier = gTier;
1095
1057
  } catch {}
1096
1058
 
1059
+ const longRunning = provider.isLongRunning?.(modelId, providerOptions) === true;
1097
1060
  const innerStream = provider.stream(
1098
1061
  modelId,
1099
1062
  {
1100
1063
  systemPrompt: context.systemPrompt,
1101
1064
  messages: context.messages,
1102
- cachedContentId: context.cachedContentId,
1103
1065
  },
1104
1066
  providerOptions
1105
1067
  );
@@ -1113,7 +1075,8 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
1113
1075
  let first = true;
1114
1076
  let doneIter = false;
1115
1077
  while (!doneIter) {
1116
- const waitMs = first ? streamLimits.firstByteTimeoutMs : streamLimits.streamIdleTimeoutMs;
1078
+ // Long-running streams pause for minutes between chunks; the adapter guards stalls and reconnects.
1079
+ const waitMs = longRunning ? Infinity : first ? streamLimits.firstByteTimeoutMs : streamLimits.streamIdleTimeoutMs;
1117
1080
  let timer: ReturnType<typeof setTimeout> | undefined;
1118
1081
  const timeoutP =
1119
1082
  Number.isFinite(waitMs) && waitMs !== Infinity && waitMs > 0
@@ -1161,7 +1124,7 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
1161
1124
  lastResponse = turnResponse;
1162
1125
  // Canonical session routing: lets adapters detect provider switches.
1163
1126
  noteProviderTurn(
1164
- runOptions?.sessionId || options?.sessionId || options?.cache?.sessionId,
1127
+ runOptions?.sessionId || options?.sessionId,
1165
1128
  provider.id
1166
1129
  );
1167
1130
 
@@ -1189,7 +1152,8 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
1189
1152
  turnResponse.text,
1190
1153
  turnResponse.toolCalls,
1191
1154
  turnResponse.thinking,
1192
- turnResponse.thoughtSignature
1155
+ turnResponse.thoughtSignature,
1156
+ turnResponse.providerSteps
1193
1157
  );
1194
1158
 
1195
1159
  // Thinking-trace telemetry (observability-only, full text, no limit):
@@ -1203,7 +1167,7 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
1203
1167
  turns,
1204
1168
  model: modelId,
1205
1169
  provider: provider.id,
1206
- sessionId: runOptions?.sessionId || options?.sessionId || options?.cache?.sessionId,
1170
+ sessionId: runOptions?.sessionId || options?.sessionId,
1207
1171
  thinking: turnResponse.thinking,
1208
1172
  ...(turnResponse.thoughtSignature ? { thoughtSignature: turnResponse.thoughtSignature } : {}),
1209
1173
  },
@@ -1254,7 +1218,7 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
1254
1218
  repeatCounts,
1255
1219
  agentName,
1256
1220
  signal: linked.signal,
1257
- sessionId: runOptions?.sessionId || options?.sessionId || options?.cache?.sessionId,
1221
+ sessionId: runOptions?.sessionId || options?.sessionId,
1258
1222
  onSubagentEvent: (ev) => {
1259
1223
  try {
1260
1224
  outerStream.push({
@@ -1452,36 +1416,10 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
1452
1416
  }
1453
1417
 
1454
1418
  // ---------------------------------------------------------------------------
1455
- // Q-15: single thinking-exposure policy + Q-04 canonical finish helper.
1419
+ // Q-15: thinking-promotion policy + Q-04 canonical finish helper.
1456
1420
  // (Appended here to avoid conflicts with other loop sections.)
1457
1421
  // ---------------------------------------------------------------------------
1458
1422
 
1459
- /**
1460
- * Single expose-thinking policy (Q-15).
1461
- * - Events/traces/onTurn always carry thinking separately (default true).
1462
- * - Promoting thinking to answer *text* is a separate opt-in
1463
- * (`thinkingAsAnswerFallback`, default false) — see
1464
- * `shouldPromoteThinkingToAnswer`.
1465
- *
1466
- * Reads `exposeThinking` from the loop config, run options, or provider
1467
- * options; any explicit `false` hides thinking from events/traces.
1468
- */
1469
- export function shouldExposeThinking(config?: unknown): boolean {
1470
- try {
1471
- const c = config as {
1472
- exposeThinking?: unknown;
1473
- runOptions?: { exposeThinking?: unknown };
1474
- options?: { exposeThinking?: unknown };
1475
- } | null | undefined;
1476
- const v = c?.exposeThinking ?? c?.runOptions?.exposeThinking ?? c?.options?.exposeThinking;
1477
- if (v === undefined) return true;
1478
- return Boolean(v);
1479
- } catch {
1480
- // why: policy lookup is best-effort — default to exposing thinking.
1481
- return true;
1482
- }
1483
- }
1484
-
1485
1423
  /**
1486
1424
  * Whether an empty-text turn may promote `thinking` to answer `text` (Q-15).
1487
1425
  * Default false: the run returns the provider's empty text with its
@@ -59,7 +59,7 @@ export function agentFromEnv(
59
59
  export class SubAgent extends Agent {
60
60
  /**
61
61
  * Creates a delegated worker, defaulting to `SUB_AGENT_MODEL` or `MODEL`
62
- * when `model` is omitted, and retaining short-lived cache state by default.
62
+ * when `model` is omitted.
63
63
  *
64
64
  * @param config Worker configuration. It accepts the same options as `Agent`
65
65
  * and can be registered with a parent via `subagents`.
@@ -83,7 +83,6 @@ export class SubAgent extends Agent {
83
83
  super({
84
84
  ...config,
85
85
  model: resolvedModel,
86
- cache: config.cache ?? { retention: "short" },
87
86
  });
88
87
  }
89
88
 
@@ -99,8 +99,7 @@ export function resolveMainModel(configModel: AgentConfig["model"]): {
99
99
  * Unwraps `ModelProviderInstance` / `ModelSpec` the same way.
100
100
  */
101
101
  export function resolveDynamicWorkerModel(
102
- dynModelRawInput: unknown,
103
- subagentModelInput: unknown
102
+ dynModelRawInput: unknown
104
103
  ): string | Record<string, unknown> | undefined {
105
104
  const dynModelRaw = dynModelRawInput as
106
105
  | { model?: unknown; id?: unknown; provider?: unknown }
@@ -119,7 +118,6 @@ export function resolveDynamicWorkerModel(
119
118
  } else {
120
119
  dynModel = (dynModelRaw as string | undefined) || getSubModel() as string | undefined;
121
120
  }
122
- void subagentModelInput;
123
121
  return dynModel;
124
122
  }
125
123
 
@@ -133,7 +131,7 @@ export function resolveDynamicModelInput(
133
131
  subagentModel: unknown
134
132
  ): string | Record<string, unknown> | undefined {
135
133
  const dynModelRaw = (dynamicSubagents as { model?: unknown } | undefined)?.model ?? subagentModel;
136
- return resolveDynamicWorkerModel(dynModelRaw, subagentModel);
134
+ return resolveDynamicWorkerModel(dynModelRaw);
137
135
  }
138
136
 
139
137
  /**
@@ -337,7 +335,6 @@ export function createLiveWorker(
337
335
  hooks: LiveWorkerHooks = {}
338
336
  ): {
339
337
  onWorkerTurn: (turn: LiveWorkerTurn) => void;
340
- onWorkerDelta: (delta?: string, thinkingDelta?: string) => void;
341
338
  attachToStream: (workerStream: {
342
339
  on: (event: string, listener: (e: { delta?: string; thinkingDelta?: string }) => void) => void;
343
340
  off: (event: string, listener: (e: { delta?: string; thinkingDelta?: string }) => void) => void;
@@ -431,5 +428,5 @@ export function createLiveWorker(
431
428
  };
432
429
  };
433
430
 
434
- return { onWorkerTurn, onWorkerDelta, attachToStream };
431
+ return { onWorkerTurn, attachToStream };
435
432
  }
package/src/index.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { z } from "zod";
2
1
  import type { AssistantMessageEventStream as AssistantMessageEventStreamT } from "./streaming/event-stream.ts";
3
2
  import type { AgentResponse as AgentResponseT } from "./types/response.ts";
4
3
 
@@ -56,23 +55,6 @@ export { zodToJsonSchema, cleanJsonSchema } from "./tools/schema.ts";
56
55
  */
57
56
  export { executeToolCalls } from "./tools/executor.ts";
58
57
 
59
- // Client-side document conversion (optional anydoc peer — see utils/documents.ts)
60
- export {
61
- convertDocumentToMarkdown,
62
- convertDocumentInput,
63
- convert_document_to_markdown,
64
- createConvertDocumentTool,
65
- isAnydocAvailable,
66
- resolveDocumentFormat,
67
- truncateMarkdown,
68
- buildDocumentXml,
69
- modelSupportsFileInput,
70
- preprocessFilePartsForBypass,
71
- DocumentConversionError,
72
- DEFAULT_DOCUMENT_MAX_CHARS,
73
- MAX_DOCUMENT_FETCH_BYTES,
74
- } from "./utils/documents.ts";
75
- export type { ConvertDocumentOptions, ConvertedDocument, ConvertDocumentToolOptions } from "./utils/documents.ts";
76
58
  export { assertPathAllowed, enforceFileAccess, fetchRemoteBytes, isPrivateAddress, RemoteFetchError, MAX_REMOTE_FETCH_BYTES } from "./utils/safe-io.ts";
77
59
 
78
60
  // Multi-Agent Delegation & Tools
@@ -223,17 +205,14 @@ export {
223
205
  clearSessionRouting,
224
206
  mapThinkingLevelToGoogle,
225
207
  mapServiceTierToGoogle,
226
- applyCacheForGoogle,
227
208
  mapThinkingLevelToOpenRouter,
228
209
  mapServiceTierToOpenRouter,
229
- applyCacheForOpenRouter,
230
210
  mapToolChoiceToOpenRouter,
231
211
  mapThinkingLevelToOpenRouterChat,
232
212
  mapToolChoiceToOpenRouterChat,
233
213
  mapThinkingLevelToOpenAI,
234
214
  mapServiceTierToOpenAI,
235
- applyCacheForOpenAI,
236
- applyCacheForCustom,
215
+ resolveCache,
237
216
  mapToolChoiceToOpenAI,
238
217
  normalizeToolChoice,
239
218
  parseStreamedToolArguments,
@@ -278,16 +257,7 @@ export {
278
257
 
279
258
  export { stripSchemaForGoogle } from "./tools/schema.ts";
280
259
 
281
- export {
282
- createExplicitCache,
283
- retentionToTtlSeconds,
284
- getPromptCacheRetention,
285
- clampCacheKey,
286
- } from "./utils/cache.ts";
287
- export type {
288
- CreateExplicitCacheOptions,
289
- CachedContentMetadata,
290
- } from "./utils/cache.ts";
260
+ export { clampCacheKey } from "./utils/cache.ts";
291
261
 
292
262
  // Streaming & Events
293
263
  export { AssistantMessageEventStream } from "./streaming/event-stream.ts";
@@ -368,20 +338,13 @@ export { normalizeMediaInput, inferMimeType, sniffMimeType } from "./utils/media
368
338
  export { base64ToBytes, bytesToBase64 } from "./utils/base64.ts";
369
339
  export { toJsonSafe, safeStringify, escapeXml } from "./utils/serialization.ts";
370
340
 
371
- // Re-export Zod (compat only)
372
- /**
373
- * @deprecated Compat re-export: prefer adding `zod` as a direct (peer)
374
- * dependency and importing from `"zod"` (Q-50). Kept so existing
375
- * `import { z } from "agent-accelerator"` code keeps working.
376
- */
377
- export { z };
341
+ export { CACHE_OPTIONS } from "./types/core.ts";
378
342
 
379
343
  // TypeScript Type Exports
380
344
  export type {
381
345
  ThinkingLevel,
382
346
  ThinkingConfig,
383
- CacheRetention,
384
- CacheConfig,
347
+ CacheOption,
385
348
  ServiceTier,
386
349
  TokenUsage,
387
350
  } from "./types/core.ts";
@@ -399,6 +362,8 @@ export type {
399
362
  ToolResultPart,
400
363
  ThinkingPart,
401
364
  ProviderContext,
365
+ ProviderSteps,
366
+ MediaResolution,
402
367
  } from "./types/message.ts";
403
368
 
404
369
  export type {