@elevasis/sdk 1.42.0 → 1.43.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.
@@ -252,16 +252,12 @@ type OpenAIModel = 'gpt-5' | 'gpt-5.4-mini' | 'gpt-5.4-nano';
252
252
  * Supported OpenRouter models (explicit union for type safety)
253
253
  */
254
254
  type OpenRouterModel = 'openrouter/z-ai/glm-5';
255
- /**
256
- * Supported Google models (direct SDK access)
257
- */
258
- type GoogleModel = 'gemini-3-flash-preview' | 'gemini-3.1-flash-lite-preview';
259
255
  /**
260
256
  * Supported Anthropic models (direct SDK access via @anthropic-ai/sdk)
261
257
  */
262
258
  type AnthropicModel = 'claude-opus-5' | 'claude-sonnet-5' | 'claude-haiku-4-5-20251001' | 'claude-haiku-4-5';
263
259
  /** Supported LLM models */
264
- type LLMModel = OpenAIModel | OpenRouterModel | GoogleModel | AnthropicModel | 'mock';
260
+ type LLMModel = OpenAIModel | OpenRouterModel | AnthropicModel | 'mock';
265
261
  /**
266
262
  * GPT-5 model options schema
267
263
  */
@@ -288,18 +284,6 @@ declare const OpenRouterOptionsSchema: z.ZodObject<{
288
284
  fallback: "fallback";
289
285
  }>>;
290
286
  }, z.core.$strip>;
291
- /**
292
- * Google model options schema
293
- * Gemini 3 specific options for thinking depth control
294
- */
295
- declare const GoogleOptionsSchema: z.ZodObject<{
296
- thinkingLevel: z.ZodOptional<z.ZodEnum<{
297
- minimal: "minimal";
298
- low: "low";
299
- medium: "medium";
300
- high: "high";
301
- }>>;
302
- }, z.core.$strip>;
303
287
  /**
304
288
  * Anthropic model options schema
305
289
  * Currently empty - future options must be added per supported model family
@@ -311,16 +295,15 @@ declare const AnthropicOptionsSchema: z.ZodObject<{}, z.core.$strict>;
311
295
  type GPT5Options = z.infer<typeof GPT5OptionsSchema>;
312
296
  type MockOptions = Record<string, never>;
313
297
  type OpenRouterOptions = z.infer<typeof OpenRouterOptionsSchema>;
314
- type GoogleOptions = z.infer<typeof GoogleOptionsSchema>;
315
298
  type AnthropicOptions = z.infer<typeof AnthropicOptionsSchema>;
316
- type ModelSpecificOptions = GPT5Options | MockOptions | OpenRouterOptions | GoogleOptions | AnthropicOptions;
299
+ type ModelSpecificOptions = GPT5Options | MockOptions | OpenRouterOptions | AnthropicOptions;
317
300
  /**
318
301
  * Model configuration for LLM execution
319
302
  * Belongs in resource definition (AgentDefinition, WorkflowDefinition, etc.)
320
303
  */
321
304
  interface ModelConfig {
322
305
  model: LLMModel;
323
- provider: 'openai' | 'anthropic' | 'openrouter' | 'google' | 'mock';
306
+ provider: 'openai' | 'anthropic' | 'openrouter' | 'mock';
324
307
  apiKey: string;
325
308
  temperature?: number;
326
309
  /** Maximum output tokens per LLM call. NOT the model's context window — see ModelInfo.maxTokens for that. */
@@ -335,14 +318,70 @@ interface ModelConfig {
335
318
  modelOptions?: ModelSpecificOptions;
336
319
  }
337
320
 
321
+ /**
322
+ * Types for the schema compiler. `compile.ts` walks a `JsonSchema` once, driven entirely by a
323
+ * `ProviderDialect`, and every server adapter compiles through it.
324
+ */
338
325
  /**
339
326
  * What happened to `strict` on a request, recorded per call rather than inferred.
340
327
  *
341
- * `applied` and `notAttempted` are the two states that a refusal-only field cannot tell apart
328
+ * `applied` and `notAttempted` are the two states that a refusal-only field cannot tell apart --
342
329
  * both leave `strictRefusalReasons` empty. Recording the verdict positively is what makes "was
343
330
  * this agent's output actually enforced?" answerable from an `ai_calls` row.
344
331
  */
345
332
  type StrictStatus = 'applied' | 'refused' | 'compileRejected' | 'notAttempted';
333
+ /**
334
+ * A JSON Schema node, typed enough to be useful without pretending to validate the spec.
335
+ *
336
+ * The compiler has to accept schemas that arrive OUTSIDE the strict subset (that is the whole
337
+ * point of a dialect that can refuse or rewrite them) as well as the `$ref`/`$defs`/`const`/
338
+ * `$schema` shapes the strict subset has no vocabulary for at all. The index signature exists
339
+ * because tenant schemas carry keywords (`minLength`, `pattern`, `minimum`, ...) this compiler
340
+ * drops or refuses on, and they still need somewhere to type-check while they pass through
341
+ * `Object.entries`.
342
+ */
343
+ interface JsonSchema {
344
+ type?: string | string[];
345
+ /**
346
+ * The value is `JsonSchema | undefined`, not `JsonSchema`, because a property really can be
347
+ * declared with nothing describing it. `buildIterationResponseSchema` emits one per tool as
348
+ * `input: tool.inputSchema`, and `ToolDefinition.inputSchema` is typed `unknown` -- a tool
349
+ * deployed without one puts `undefined` under a key that exists.
350
+ *
351
+ * Both readers already handle it: `compileSchema` passes each value through `convertNode`, which
352
+ * takes `unknown`, and `collectErrors` opens with `if (!schema || typeof schema !== 'object')`
353
+ * above a comment naming this exact case. Declaring the value non-optional only hid that they
354
+ * were right to.
355
+ */
356
+ properties?: Record<string, JsonSchema | undefined>;
357
+ items?: JsonSchema;
358
+ anyOf?: JsonSchema[];
359
+ oneOf?: JsonSchema[];
360
+ allOf?: JsonSchema[];
361
+ required?: string[];
362
+ additionalProperties?: boolean | JsonSchema;
363
+ minItems?: number;
364
+ maxItems?: number;
365
+ format?: string;
366
+ enum?: unknown[];
367
+ const?: unknown;
368
+ description?: string;
369
+ default?: unknown;
370
+ $ref?: string;
371
+ $defs?: Record<string, JsonSchema>;
372
+ definitions?: Record<string, JsonSchema>;
373
+ $schema?: string;
374
+ $id?: string;
375
+ $anchor?: string;
376
+ /**
377
+ * OpenAPI's nullability spelling, which is not JSON Schema's. It is declared because
378
+ * `response-schema-validator.ts` READS it (`schemaPermitsNull`) -- Google's schema dialect is
379
+ * OpenAPI-derived, so a schema that reaches the validator can carry it. No dialect in `compile.ts`
380
+ * writes or rewrites it; the canonical spelling this compiler emits is `type: ['x', 'null']`.
381
+ */
382
+ nullable?: boolean;
383
+ [key: string]: unknown;
384
+ }
346
385
 
347
386
  declare const ResourceGovernanceStatusSchema: z.ZodEnum<{
348
387
  active: "active";
@@ -886,16 +925,86 @@ interface LLMMessage {
886
925
  */
887
926
  interface LLMGenerateRequest {
888
927
  messages: LLMMessage[];
889
- responseSchema: unknown;
928
+ /**
929
+ * JSON Schema for structured output. Omit it for an unstructured call.
930
+ *
931
+ * Absence is what turns validation off: `runGeneratePipeline` skips `validateResponseSchema`
932
+ * entirely when this is missing, whatever `validationSchema` holds.
933
+ *
934
+ * This was declared `responseSchema: unknown` -- required, and typed as nothing. `unknown` admits
935
+ * `undefined`, so "required" only ever forced the KEY to be written, and `createLLMCallTool`
936
+ * writes it as `undefined` on every call where the model supplies no usable schema. There was no
937
+ * type error available for that, and three separate layers re-derived the same nullability at
938
+ * runtime under three different rules -- truthiness in the pipeline, an object check in the
939
+ * validator, and a `'type'`-key check in the tool. Because the pipeline's was truthiness, `null`,
940
+ * `0` and `''` all quietly meant "no structured output" while the type insisted a schema was
941
+ * mandatory. Optional-and-typed is what those three were compensating for.
942
+ */
943
+ responseSchema?: JsonSchema;
890
944
  /** Maximum output tokens per LLM call. NOT the model's context window — see ModelInfo.maxTokens for that. */
891
945
  maxOutputTokens?: number;
892
946
  temperature?: number;
893
947
  topP?: number;
894
948
  signal?: AbortSignal;
949
+ /**
950
+ * Caller-supplied acceptance step (Wave D2b / decision A15). A pipeline-aware adapter
951
+ * (`UniversalLLMAdapter`, via `runGeneratePipeline`) runs this once per retry attempt, right
952
+ * after the response has passed `responseSchema` validation. Throw to reject the attempt --
953
+ * rejection is classified exactly like a thrown `LLMResponseParseError` from
954
+ * `validateResponseSchema`: retryable, no circuit-breaker verdict, and the attempt is recorded as
955
+ * a failure (`ai_calls` validation-failure row) rather than a clean success. Returning normally
956
+ * (including `undefined`) accepts the response.
957
+ *
958
+ * Optional, and a HINT rather than a dependency -- an adapter that does not read this field
959
+ * simply ignores it, so a caller must not assume it ran:
960
+ * - A bare test-stub `LLMAdapter` (many exist in this codebase) does not invoke it.
961
+ * - `PostMessageLLMAdapter` (`packages/sdk/src/worker/llm-adapter.ts`) cannot forward it at all --
962
+ * functions cannot be structured-cloned across the worker `postMessage` boundary, so its
963
+ * `params` object is built from an explicit allowlist that omits `accept`. The field is dropped
964
+ * before `postMessage` is ever called (no `DataCloneError`), and the parent-side handler that
965
+ * fulfils the call (`tool-dispatcher.ts`'s `case 'llm'`) rebuilds its own `LLMGenerateRequest`
966
+ * from that allowlisted payload, so there is nothing to forward even in principle. This is the
967
+ * path every deployed org-bundle agent and the `command-center-assistant` static module run
968
+ * through today -- `accept` does not reach their retry loop.
969
+ *
970
+ * This is not a validation mechanism on its own: it does not decide whether output is acceptable,
971
+ * the caller's function does, by throwing or not. `callLLMForAgentIteration`
972
+ * (`execution/engine/agent/reasoning/adapters/agent-adapter-helpers.ts`) passes its Zod parse of
973
+ * the iteration response as this field, so a malformed-but-schema-valid iteration is re-sampled
974
+ * inside the retry loop instead of losing the turn -- for the in-process callers that can see it.
975
+ */
976
+ accept?: (output: unknown) => void;
977
+ /**
978
+ * The schema the RESPONSE is validated against, when that must differ from the schema the
979
+ * provider was asked to sample against. Defaults to `responseSchema` when omitted.
980
+ *
981
+ * **This does not affect what is sent to the provider.** `responseSchema` remains the only schema
982
+ * an adapter puts on the wire; this one is read solely by `runGeneratePipeline`'s validation step.
983
+ * Whether validation happens at all is still decided by `responseSchema` -- a request with no
984
+ * `responseSchema` is unstructured and stays unvalidated, whatever this field holds.
985
+ *
986
+ * A caller may legitimately ACCEPT A SUPERSET of what it ASKS FOR -- a document that validates a
987
+ * response more leniently than the one the provider was asked to sample against. No caller in this
988
+ * codebase supplies one today (agent iterations validate with a single Zod parse instead, see
989
+ * `agent-adapter-helpers.ts`), but the mechanism stays: `validateResponseSchema` does not descend
990
+ * into `anyOf`/`oneOf` regardless of which document is supplied here, so this field only ever
991
+ * changes which top-level/required/type keywords are checked, never which acceptance contract a
992
+ * union is read as.
993
+ *
994
+ * Unlike `accept` above, this is DATA. It is structured-cloneable, so it survives the worker
995
+ * `postMessage` boundary that drops `accept`: `PostMessageLLMAdapter` forwards it in its params
996
+ * allowlist and `tool-dispatcher.ts`'s `case 'llm'` puts it back on the `LLMGenerateRequest` it
997
+ * rebuilds parent-side. That is why a divergence expressible as a schema belongs here rather than
998
+ * in a callback -- deployed org-bundle agents run on the far side of that boundary.
999
+ */
1000
+ validationSchema?: JsonSchema;
895
1001
  }
896
1002
  /**
897
1003
  * Generic LLM generation response
898
- * Usage field is internal-only (stripped by UniversalLLMAdapter wrapper)
1004
+ * `usage`, `cost`, `strictStatus` and `strictRefusalReasons` are observability fields. They are
1005
+ * **read** by `UniversalLLMAdapter` and lifted onto the `ai_calls` row; they are **not removed**.
1006
+ * The wrapper returns the base adapter's response object as-is, so a caller can observe all four.
1007
+ * Earlier revisions of this file claimed they were stripped — they never were.
899
1008
  */
900
1009
  interface LLMGenerateResponse<T = unknown> {
901
1010
  output: T;
@@ -903,35 +1012,53 @@ interface LLMGenerateResponse<T = unknown> {
903
1012
  inputTokens: number;
904
1013
  outputTokens: number;
905
1014
  totalTokens: number;
1015
+ /**
1016
+ * Anthropic-only: input tokens served from the prompt cache (`cache_read_input_tokens`), billed
1017
+ * at 0.1x the base input rate. Optional so OpenAI/OpenRouter usage objects, which never report
1018
+ * this, stay valid -- absent means "this provider doesn't report it," not "zero were read."
1019
+ */
1020
+ cacheReadInputTokens?: number;
1021
+ /**
1022
+ * Anthropic-only: input tokens written to the prompt cache this call
1023
+ * (`cache_creation_input_tokens`), billed at 1.25x the base input rate. Same optionality
1024
+ * rationale as `cacheReadInputTokens`.
1025
+ */
1026
+ cacheCreationInputTokens?: number;
906
1027
  };
907
1028
  cost?: number;
908
1029
  /**
909
- * What actually happened to `strict` on the request that produced this response. Every server
910
- * adapter sets it on every call, so the value is a statement rather than an inference:
1030
+ * What actually happened to `strict` on the request that produced this response.
911
1031
  *
912
1032
  * - `applied` — the request carried `strict: true` and the grammar was in effect
913
- * - `refused` — `toStrictSchema` could not express the schema, so the request went out unstrict
914
- * - `compileRejected` — the schema passed `toStrictSchema` but the provider's grammar compiler
1033
+ * - `refused` — `compileSchema` could not express the schema, so the request went out unstrict
1034
+ * - `compileRejected` — the schema passed `compileSchema` but the provider's grammar compiler
915
1035
  * rejected it at request time, and the call was retried unstrict
916
- * - `notAttempted` — this adapter does not send strict at all (OpenAI, Google, OpenRouter)
1036
+ * - `notAttempted` — the adapter did not send `strict` on this call
917
1037
  *
918
1038
  * This exists because `strictRefusalReasons` alone cannot answer the question. Its absence means
919
1039
  * "strict held" OR "nothing ever tried", and a prod run that recorded zero refusals while
920
1040
  * returning an array-typed field as a string is exactly the case where the difference matters.
921
1041
  *
922
- * Internal-only, like `usage` `UniversalLLMAdapter` lifts it onto the `ai_calls` row and
923
- * strips it before the response reaches callers.
1042
+ * **Do not read this as "provider X never sends strict."** It describes one call, not an adapter.
1043
+ * A previous revision of this comment enumerated OpenAI, Google and OpenRouter as adapters that
1044
+ * never send `strict`, which was false for OpenRouter — it sends `strict: true` whenever the
1045
+ * schema compiles, and separately reports `notAttempted`. That producer bug is still live; the
1046
+ * fix is to make the value a return of schema compilation rather than a per-adapter literal.
1047
+ * `MockAdapter` sets no value at all, so absence does not imply `notAttempted` either.
1048
+ *
1049
+ * Observability only — `UniversalLLMAdapter` lifts it onto the `ai_calls` row. It is not removed
1050
+ * from the response.
924
1051
  */
925
1052
  strictStatus?: StrictStatus;
926
1053
  /**
927
1054
  * Why this call went out WITHOUT `strict`, on an adapter that tried to send it with one.
928
1055
  *
929
1056
  * The detail behind a `refused` / `compileRejected` `strictStatus` — the short, stable reason
930
- * strings `toStrictSchema` computes. Read `strictStatus` to answer "was it enforced"; read this
1057
+ * strings `compileSchema` computes. Read `strictStatus` to answer "was it enforced"; read this
931
1058
  * to answer "why not".
932
1059
  *
933
- * Internal-only, like `usage` — `UniversalLLMAdapter` lifts it onto the `ai_calls` row and
934
- * strips it before the response reaches callers.
1060
+ * Observability only — `UniversalLLMAdapter` lifts it onto the `ai_calls` row. It is not removed
1061
+ * from the response.
935
1062
  */
936
1063
  strictRefusalReasons?: string[];
937
1064
  }
@@ -964,7 +1091,7 @@ interface LLMAdapter {
964
1091
  * Use-case agnostic types that describe the purpose of each entry
965
1092
  * Memory types mirror action types for clarity and filtering
966
1093
  */
967
- type MemoryEntryType = 'context' | 'input' | 'reasoning' | 'tool-result' | 'delegation-result' | 'error';
1094
+ type MemoryEntryType = 'context' | 'input' | 'reasoning' | 'tool-result' | 'error';
968
1095
  /**
969
1096
  * Who authored an entry's content.
970
1097
  *
@@ -993,6 +1120,14 @@ interface MemoryEntry {
993
1120
  * starting the agent with empty memory rather than throwing.
994
1121
  */
995
1122
  source?: MemoryEntrySource;
1123
+ /**
1124
+ * Which tool produced this entry. Set on `tool-result` entries so the model can tell N parallel
1125
+ * results apart -- the framework instructs batching independent tool calls in one iteration, and
1126
+ * an anonymous result is unattributable the moment two land in the same iteration. `addToolError`
1127
+ * already carries this (folded into its `content` JSON); this is the same fact for the success
1128
+ * path, carried as a real field instead of prose the caller has to parse back out.
1129
+ */
1130
+ toolName?: string;
996
1131
  }
997
1132
  /**
998
1133
  * Agent memory - Self-orchestrated memory with session + working storage
@@ -1019,7 +1154,6 @@ interface AgentMemory {
1019
1154
  interface MemoryStatus {
1020
1155
  sessionMemoryKeys: number;
1021
1156
  sessionMemoryLimit: number;
1022
- currentKeys: string[];
1023
1157
  sessionMemoryTokens: number;
1024
1158
  sessionMemoryTokenLimit: number;
1025
1159
  /**
@@ -1028,10 +1162,26 @@ interface MemoryStatus {
1028
1162
  * read as history pressure and triggered history compaction that could not relieve it.
1029
1163
  */
1030
1164
  historyPercent: number;
1165
+ /**
1166
+ * Tokens the history entries **in scope for the requested turn** occupy — the same set
1167
+ * `toContextParts` puts in the envelope. Equal to `storedHistoryTokens` when `getStatus` is
1168
+ * called without a turn.
1169
+ *
1170
+ * This is the number the model is shown, and it is scoped because the model is handed a scoped
1171
+ * set. Counting the whole cross-turn array here meant the framing quoted the size of a store
1172
+ * while the envelope beside it carried one turn's worth of it.
1173
+ */
1031
1174
  historyTokens: number;
1175
+ /**
1176
+ * Tokens the **entire** history array occupies, across every turn the session snapshot restored.
1177
+ *
1178
+ * This is what compaction measures, because compaction trims that array. Scoping it to a turn
1179
+ * would let the store grow without bound whenever the current turn happened to be small.
1180
+ */
1181
+ storedHistoryTokens: number;
1182
+ /** `storedHistoryTokens` as a percentage of `historyBudget`. The auto-compaction trigger. */
1183
+ storedHistoryPercent: number;
1032
1184
  historyBudget: number;
1033
- totalTokens: number;
1034
- tokenBudget: number;
1035
1185
  }
1036
1186
  /**
1037
1187
  * Memory constraints (optional limits)
@@ -1113,6 +1263,14 @@ declare class MemoryManager {
1113
1263
  * are not. Eviction is oldest-first by timestamp, matching the key-count path, and always
1114
1264
  * leaves at least one entry so a single oversized key degrades to "one key" rather than to
1115
1265
  * "memory silently emptied".
1266
+ *
1267
+ * The running total is **recomputed** from the survivors rather than decremented per entry.
1268
+ * `getStatus` estimates the pool as a ceiling of the joined sum, and a per-entry decrement is a
1269
+ * sum of ceilings — the larger of the two by up to one token per key. The running total therefore
1270
+ * fell faster than the pool did, and the loop could exit reporting a fit while the very next
1271
+ * `getStatus` still read over the limit. Recomputing makes the loop's exit condition and the
1272
+ * number it is judged by the same expression. The pool is capped at `MAX_SESSION_MEMORY_KEYS`
1273
+ * entries, so the extra passes are bounded and cheap.
1116
1274
  */
1117
1275
  private enforceSessionMemoryTokenLimit;
1118
1276
  /**
@@ -1122,9 +1280,13 @@ declare class MemoryManager {
1122
1280
  getHistoryLength(): number;
1123
1281
  /**
1124
1282
  * Get memory status for agent awareness
1283
+ *
1284
+ * @param currentTurn - Turn to scope `historyTokens` / `historyPercent` to. Omit to measure the
1285
+ * whole store, which is what the compaction paths want. Callers building something the model
1286
+ * reads should pass it, so the count describes the set the model is actually handed.
1125
1287
  * @returns Memory status with token usage and key counts
1126
1288
  */
1127
- getStatus(): MemoryStatus;
1289
+ getStatus(currentTurn?: number): MemoryStatus;
1128
1290
  /**
1129
1291
  * Create memory snapshot for persistence
1130
1292
  * Caches snapshot internally for later retrieval
@@ -1163,87 +1325,6 @@ declare class MemoryManager {
1163
1325
  toContextParts(currentIteration: number, currentTurn?: number): MemoryContextParts;
1164
1326
  }
1165
1327
 
1166
- /**
1167
- * Knowledge Map Types
1168
- *
1169
- * Enables agents to navigate organizational knowledge through a lightweight
1170
- * graph that lazy-loads capabilities on-demand.
1171
- *
1172
- * @module agent/knowledge-map
1173
- */
1174
-
1175
- /**
1176
- * Lightweight knowledge map (passed as agent property)
1177
- *
1178
- * Contains metadata about available knowledge nodes without loading
1179
- * the full content upfront. Total size: ~300-500 tokens.
1180
- *
1181
- * Multi-tenancy is enforced via:
1182
- * - File-scoped maps (organizations/{org-name}/knowledge/)
1183
- * - ExecutionContext.organizationId passed to node.load()
1184
- */
1185
- interface KnowledgeMap {
1186
- /** Available knowledge nodes indexed by ID */
1187
- nodes: Record<string, KnowledgeNode>;
1188
- }
1189
- /**
1190
- * Single knowledge source
1191
- *
1192
- * Represents a domain knowledge area (CRM, brand guidelines, Excel tools)
1193
- * that can be lazy-loaded to provide instructions and tools to agents.
1194
- */
1195
- interface KnowledgeNode {
1196
- /** Unique identifier for this node (e.g., "crm", "brand-guidelines") */
1197
- id: string;
1198
- /**
1199
- * Description of when to use this knowledge
1200
- * Used for semantic matching against user intent
1201
- */
1202
- description: string;
1203
- /**
1204
- * Load knowledge content on-demand
1205
- *
1206
- * @param context - Execution context with organizationId for multi-tenancy
1207
- * @returns Promise resolving to knowledge content (prompt + optional tools)
1208
- */
1209
- load(context: ExecutionContext): Promise<KnowledgeContent>;
1210
- /**
1211
- * Loaded state flag
1212
- * Set to true after load() is called
1213
- */
1214
- loaded?: boolean;
1215
- /**
1216
- * Cached prompt (for system prompt serialization)
1217
- * Only the prompt is cached - tools go to toolRegistry, children flattened to nodes
1218
- */
1219
- prompt?: string;
1220
- }
1221
- /**
1222
- * Content returned by knowledge node
1223
- *
1224
- * Separates instructions (prompt) from capabilities (tools).
1225
- * Tools are optional - some nodes only provide context.
1226
- *
1227
- * Supports recursive navigation - nodes can contain child nodes
1228
- * that are discovered when the parent node is loaded.
1229
- */
1230
- interface KnowledgeContent {
1231
- /** Instructions and context (markdown format) */
1232
- prompt: string;
1233
- /** Tool implementations (optional) */
1234
- tools?: Tool[];
1235
- /**
1236
- * Child knowledge nodes (optional, recursive)
1237
- *
1238
- * Enables hierarchical navigation: base → specialized → deep expertise.
1239
- * Child nodes are flattened into the main knowledge map when parent loads,
1240
- * making them available for subsequent navigate-knowledge actions.
1241
- *
1242
- * Example: CRM base node returns crm-customers and crm-deals as children
1243
- */
1244
- nodes?: Record<string, KnowledgeNode>;
1245
- }
1246
-
1247
1328
  /**
1248
1329
  * Agent-specific type definitions
1249
1330
  * Types for autonomous agents with tools, memory, and constraints
@@ -1320,11 +1401,6 @@ interface AgentDefinition {
1320
1401
  * Specifies provider, API key, and model-specific options
1321
1402
  */
1322
1403
  modelConfig: ModelConfig;
1323
- /**
1324
- * Optional knowledge map for lazy-loading capabilities
1325
- * Enables agents to navigate organizational knowledge on-demand
1326
- */
1327
- knowledgeMap?: KnowledgeMap;
1328
1404
  /**
1329
1405
  * Preload memory before execution starts
1330
1406
  * Handles BOTH context loading AND session restoration
@@ -1358,7 +1434,6 @@ interface IterationContext {
1358
1434
  logger: AgentScopedLogger;
1359
1435
  modelConfig: ModelConfig;
1360
1436
  adapterFactory: LLMAdapterFactory;
1361
- knowledgeMap?: KnowledgeMap;
1362
1437
  /**
1363
1438
  * The validated input for this execution, serialized. It travels here because the model gets
1364
1439
  * it as its own `role:'user'` message; nothing else in this context carried it, so the input
@@ -10304,6 +10379,17 @@ interface BaseAICall {
10304
10379
  costUsd: number;
10305
10380
  latencyMs: number;
10306
10381
  context?: AICallContext;
10382
+ /**
10383
+ * Anthropic-only: input tokens served from the prompt cache this call (`cache_read_input_tokens`),
10384
+ * billed at 0.1x the base input rate. Already folded into `inputTokens`/`totalInputTokens` so
10385
+ * aggregate totals reflect real usage -- present here as the raw breakdown, not additive on top.
10386
+ */
10387
+ cacheReadInputTokens?: number;
10388
+ /**
10389
+ * Anthropic-only: input tokens written to the prompt cache this call (`cache_creation_input_tokens`),
10390
+ * billed at 1.25x the base input rate. Same folding rationale as `cacheReadInputTokens`.
10391
+ */
10392
+ cacheCreationInputTokens?: number;
10307
10393
  /**
10308
10394
  * Distinct prompt-injection pattern types detected in the request's user-role messages.
10309
10395
  * Present only when the input sanitizer matched something. Non-blocking matches ride along on
@@ -10369,6 +10455,41 @@ interface BaseAICall {
10369
10455
  * Existing readers that only look at the fields above are unaffected.
10370
10456
  */
10371
10457
  strictRefusalReasons?: string[];
10458
+ /**
10459
+ * Time spent in the base adapter's `generate()` call alone, excluding `responseSchema`
10460
+ * validation. On a success or validation-failure row, `providerMs + validateMs === latencyMs`
10461
+ * (modulo rounding) -- `latencyMs` keeps its existing meaning unchanged; this and `validateMs`
10462
+ * are the same window split into its two components.
10463
+ *
10464
+ * Present on success and validation-failure rows. Absent on a blocked row (no provider call was
10465
+ * made) and on rows written before this field existed.
10466
+ */
10467
+ providerMs?: number;
10468
+ /**
10469
+ * Time spent in `validateResponseSchema` alone. Omitted when the call carried no `responseSchema`
10470
+ * (nothing to validate); `0` is a legitimate value meaning a schema was supplied and validation
10471
+ * was effectively instant. See `providerMs` for how the two relate to `latencyMs`.
10472
+ *
10473
+ * Present on success and validation-failure rows that supplied a `responseSchema`. Absent on a
10474
+ * blocked row and on rows written before this field existed.
10475
+ */
10476
+ validateMs?: number;
10477
+ /**
10478
+ * Total elapsed time for the WHOLE `generate()` call -- every retry attempt plus every backoff
10479
+ * sleep between them. Unlike `latencyMs` (which is per-attempt and never includes backoff, by
10480
+ * design -- see `runWithRetry`), this is the one number that answers "how long did the caller
10481
+ * actually wait". On a call that never retried, `wallClockMs === latencyMs`. On a retried call,
10482
+ * `wallClockMs` is strictly greater than any individual row's `latencyMs` from that same call, by
10483
+ * at least the backoff time actually slept.
10484
+ *
10485
+ * The same value is attached to every row produced by one `generate()` call (a validation-failure
10486
+ * row from an earlier attempt included), because it describes the call, not the attempt.
10487
+ *
10488
+ * Present on success and validation-failure rows. Absent on a blocked row -- a blocked call never
10489
+ * reaches the retry loop, so `wallClockMs` would just restate `latencyMs` (0). Absent on rows
10490
+ * written before this field existed.
10491
+ */
10492
+ wallClockMs?: number;
10372
10493
  }
10373
10494
  type AICallContext = AgentReasoningContext | AgentCompletionContext | WorkflowStepContext | ToolCallContext | OtherCallContext;
10374
10495
  interface AgentReasoningContext {
@@ -10414,6 +10535,16 @@ interface LLMUsageData {
10414
10535
  latencyMs: number;
10415
10536
  /** Actual cost from provider in USD (when available, e.g., OpenRouter) */
10416
10537
  cost?: number;
10538
+ /**
10539
+ * Anthropic-only: input tokens served from the prompt cache (`cache_read_input_tokens`), billed at
10540
+ * 0.1x the base input rate. Absent for providers that never report it (OpenAI, OpenRouter).
10541
+ */
10542
+ cacheReadInputTokens?: number;
10543
+ /**
10544
+ * Anthropic-only: input tokens written to the prompt cache this call
10545
+ * (`cache_creation_input_tokens`), billed at 1.25x the base input rate. Same absence rationale.
10546
+ */
10547
+ cacheCreationInputTokens?: number;
10417
10548
  /** Distinct prompt-injection pattern types detected in the request's user-role messages */
10418
10549
  inputWarnings?: string[];
10419
10550
  /** Additive per-source breakdown of `inputWarnings` — see `SourcedInputWarnings` */
@@ -10428,6 +10559,12 @@ interface LLMUsageData {
10428
10559
  strictStatus?: StrictStatus;
10429
10560
  /** Why the call went out unstrict, when a strict-capable adapter refused the schema */
10430
10561
  strictRefusalReasons?: string[];
10562
+ /** Time in the base adapter's `generate()` alone, excluding `responseSchema` validation. See `BaseAICall.providerMs`. */
10563
+ providerMs?: number;
10564
+ /** Time in `validateResponseSchema` alone. Omitted when no `responseSchema` was supplied. See `BaseAICall.validateMs`. */
10565
+ validateMs?: number;
10566
+ /** Total elapsed for the whole `generate()` call, including every retry and every backoff sleep. See `BaseAICall.wallClockMs`. */
10567
+ wallClockMs?: number;
10431
10568
  }
10432
10569
  interface AIUsageSummary {
10433
10570
  model: LLMModel;
@@ -10988,19 +11125,17 @@ interface DeploymentSpec {
10988
11125
  * Types are shared with the server-side LLM engine and inlined for SDK consumers.
10989
11126
  */
10990
11127
 
10991
- type LLMProvider = 'openai' | 'anthropic' | 'openrouter' | 'google';
11128
+ type LLMProvider = 'openai' | 'anthropic' | 'openrouter';
10992
11129
  /**
10993
11130
  * SDK LLM generate params.
10994
11131
  * Extends LLMGenerateRequest with required provider/model for worker→platform dispatch.
10995
11132
  * Provider and model must always be specified explicitly — no implicit fallback.
10996
11133
  */
10997
- interface SDKLLMGenerateParams extends Omit<LLMGenerateRequest, 'signal' | 'responseSchema'> {
11134
+ interface SDKLLMGenerateParams extends Omit<LLMGenerateRequest, 'signal'> {
10998
11135
  /** LLM provider */
10999
11136
  provider: LLMProvider;
11000
11137
  /** Model identifier — must be a supported LLMModel */
11001
11138
  model: LLMModel;
11002
- /** JSON Schema for structured output (optional — omit for unstructured text) */
11003
- responseSchema?: unknown;
11004
11139
  }
11005
11140
 
11006
11141
  /**