@deepstrike/sdk 0.2.52 → 0.2.61

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 (151) hide show
  1. package/README.md +28 -28
  2. package/dist/agent-ir.d.ts +103 -0
  3. package/dist/agent-ir.js +134 -0
  4. package/dist/agent.d.ts +67 -0
  5. package/dist/agent.js +36 -0
  6. package/dist/collaboration/harness.js +1 -1
  7. package/dist/collaboration/modes/creator-verifier.d.ts +2 -7
  8. package/dist/collaboration/modes/creator-verifier.js +4 -6
  9. package/dist/collaboration/pool.d.ts +8 -20
  10. package/dist/collaboration/pool.js +27 -97
  11. package/dist/compat/anthropic/mcp.d.ts +15 -0
  12. package/dist/compat/anthropic/mcp.js +10 -0
  13. package/dist/compat/openai/agent.d.ts +34 -0
  14. package/dist/compat/openai/agent.js +24 -0
  15. package/dist/governance.d.ts +1 -17
  16. package/dist/governance.js +1 -34
  17. package/dist/guardrail.d.ts +6 -0
  18. package/dist/guardrail.js +1 -0
  19. package/dist/handoff-target.d.ts +12 -0
  20. package/dist/handoff-target.js +1 -0
  21. package/dist/harness/manifest.js +0 -4
  22. package/dist/index.d.ts +19 -7
  23. package/dist/index.js +8 -5
  24. package/dist/kernel.d.ts +2 -20
  25. package/dist/knowledge/public.d.ts +29 -0
  26. package/dist/knowledge/public.js +1 -0
  27. package/dist/mcp-server.d.ts +28 -0
  28. package/dist/mcp-server.js +1 -0
  29. package/dist/memory/agent.d.ts +2 -2
  30. package/dist/memory/agent.js +2 -2
  31. package/dist/memory/durable.d.ts +16 -0
  32. package/dist/memory/durable.js +46 -0
  33. package/dist/memory/in-memory-store.d.ts +9 -7
  34. package/dist/memory/in-memory-store.js +8 -2
  35. package/dist/memory/protocols.d.ts +22 -4
  36. package/dist/memory/public.d.ts +4 -3
  37. package/dist/memory/public.js +3 -2
  38. package/dist/os/public.d.ts +1 -1
  39. package/dist/os/public.js +1 -1
  40. package/dist/providers/anthropic-adapter.d.ts +59 -0
  41. package/dist/providers/anthropic-adapter.js +530 -0
  42. package/dist/providers/anthropic-compatible.d.ts +2 -3
  43. package/dist/providers/anthropic-compatible.js +8 -5
  44. package/dist/providers/anthropic.d.ts +20 -23
  45. package/dist/providers/anthropic.js +176 -395
  46. package/dist/providers/base.d.ts +2 -2
  47. package/dist/providers/base.js +50 -8
  48. package/dist/providers/capability-router.d.ts +29 -0
  49. package/dist/providers/capability-router.js +43 -0
  50. package/dist/providers/catalog.d.ts +16 -4
  51. package/dist/providers/catalog.js +112 -36
  52. package/dist/providers/content-normalization.d.ts +57 -0
  53. package/dist/providers/content-normalization.js +238 -0
  54. package/dist/providers/content-policy.d.ts +16 -0
  55. package/dist/providers/content-policy.js +39 -0
  56. package/dist/providers/credentials.d.ts +83 -0
  57. package/dist/providers/credentials.js +190 -0
  58. package/dist/providers/endpoints.d.ts +137 -0
  59. package/dist/providers/endpoints.js +128 -0
  60. package/dist/providers/factories.js +25 -9
  61. package/dist/providers/gemini-adapter.d.ts +33 -0
  62. package/dist/providers/gemini-adapter.js +264 -0
  63. package/dist/providers/gemini.d.ts +16 -3
  64. package/dist/providers/gemini.js +97 -195
  65. package/dist/providers/model-catalog.d.ts +37 -0
  66. package/dist/providers/model-catalog.js +62 -0
  67. package/dist/providers/model-registry.d.ts +119 -0
  68. package/dist/providers/model-registry.js +379 -0
  69. package/dist/providers/ollama-adapter.d.ts +65 -0
  70. package/dist/providers/ollama-adapter.js +188 -0
  71. package/dist/providers/ollama.d.ts +9 -4
  72. package/dist/providers/ollama.js +96 -109
  73. package/dist/providers/openai-chat-dialects.d.ts +154 -0
  74. package/dist/providers/openai-chat-dialects.js +179 -0
  75. package/dist/providers/openai-chat.d.ts +46 -18
  76. package/dist/providers/openai-chat.js +416 -51
  77. package/dist/providers/openai-responses-adapter.d.ts +42 -0
  78. package/dist/providers/openai-responses-adapter.js +343 -0
  79. package/dist/providers/openai-responses.d.ts +19 -33
  80. package/dist/providers/openai-responses.js +164 -264
  81. package/dist/providers/openai.d.ts +29 -76
  82. package/dist/providers/openai.js +195 -292
  83. package/dist/providers/protocol-adapter.d.ts +39 -0
  84. package/dist/providers/protocol-adapter.js +13 -0
  85. package/dist/providers/protocol-capabilities.d.ts +34 -0
  86. package/dist/providers/protocol-capabilities.js +44 -0
  87. package/dist/providers/provider-error.d.ts +31 -0
  88. package/dist/providers/provider-error.js +153 -0
  89. package/dist/providers/public.d.ts +26 -3
  90. package/dist/providers/public.js +13 -1
  91. package/dist/providers/registry.d.ts +7 -6
  92. package/dist/providers/registry.js +47 -20
  93. package/dist/providers/request-plan.d.ts +89 -0
  94. package/dist/providers/request-plan.js +199 -0
  95. package/dist/providers/usage-normalizer.d.ts +48 -0
  96. package/dist/providers/usage-normalizer.js +139 -0
  97. package/dist/providers/vendor-profiles.d.ts +2 -15
  98. package/dist/providers/vendor-profiles.js +14 -60
  99. package/dist/runtime/canonical-kernel-step.d.ts +1 -2
  100. package/dist/runtime/canonical-kernel-step.js +47 -12
  101. package/dist/runtime/context-policy.d.ts +10 -12
  102. package/dist/runtime/context-policy.js +6 -8
  103. package/dist/runtime/durable-content.d.ts +50 -0
  104. package/dist/runtime/durable-content.js +159 -0
  105. package/dist/runtime/execution-plane.d.ts +2 -2
  106. package/dist/runtime/execution-plane.js +2 -2
  107. package/dist/runtime/kernel-event-log.js +0 -1
  108. package/dist/runtime/kernel-step.d.ts +0 -1
  109. package/dist/runtime/kernel-step.js +4 -2
  110. package/dist/runtime/mcp-proxy-plane.d.ts +25 -1
  111. package/dist/runtime/mcp-proxy-plane.js +44 -6
  112. package/dist/runtime/output-schema.d.ts +1 -2
  113. package/dist/runtime/provider-replay.d.ts +5 -1
  114. package/dist/runtime/provider-replay.js +26 -27
  115. package/dist/runtime/reactive-session.d.ts +1 -1
  116. package/dist/runtime/reactive-session.js +2 -3
  117. package/dist/runtime/run-group.d.ts +1 -1
  118. package/dist/runtime/runner.d.ts +31 -45
  119. package/dist/runtime/runner.js +178 -63
  120. package/dist/runtime/session-log.d.ts +8 -1
  121. package/dist/runtime/session-log.js +42 -2
  122. package/dist/runtime/session-repair.d.ts +1 -1
  123. package/dist/runtime/session-repair.js +1 -1
  124. package/dist/runtime/sub-agent-orchestrator.d.ts +1 -1
  125. package/dist/runtime/sub-agent-orchestrator.js +8 -11
  126. package/dist/runtime/workflow-control-flow.d.ts +0 -4
  127. package/dist/runtime/workflow-control-flow.js +0 -16
  128. package/dist/session.d.ts +11 -0
  129. package/dist/session.js +1 -0
  130. package/dist/skill.d.ts +17 -0
  131. package/dist/skill.js +16 -0
  132. package/dist/skills/loader.d.ts +3 -0
  133. package/dist/tools/errors.d.ts +1 -3
  134. package/dist/tools/errors.js +1 -3
  135. package/dist/tools/index.d.ts +3 -0
  136. package/dist/types/agent.d.ts +21 -9
  137. package/dist/types/agent.js +30 -4
  138. package/dist/types.d.ts +135 -17
  139. package/package.json +4 -4
  140. package/dist/providers/deepseek.d.ts +0 -46
  141. package/dist/providers/deepseek.js +0 -97
  142. package/dist/providers/glm.d.ts +0 -25
  143. package/dist/providers/glm.js +0 -48
  144. package/dist/providers/kimi.d.ts +0 -23
  145. package/dist/providers/kimi.js +0 -30
  146. package/dist/providers/minimax.d.ts +0 -49
  147. package/dist/providers/minimax.js +0 -98
  148. package/dist/providers/profiles.d.ts +0 -1992
  149. package/dist/providers/profiles.js +0 -796
  150. package/dist/providers/qwen.d.ts +0 -38
  151. package/dist/providers/qwen.js +0 -97
@@ -0,0 +1,199 @@
1
+ import { createHash } from "node:crypto";
2
+ const TRANSPORT_ONLY_KEYS = new Set([
3
+ "apiKey", "api_key", "bearerToken", "bearer_token", "authorization", "credential",
4
+ "credentials", "retry", "maxRetries", "baseDelay", "timeout", "signal", "access_token", "refresh_token", "token", "secret", "x-api-key",
5
+ ]);
6
+ export function createProviderRequestPlan(input) {
7
+ const options = materialOptions(input.options ?? {});
8
+ const plan = {
9
+ providerId: input.providerId,
10
+ modelId: input.modelId,
11
+ endpoint: sanitizeEndpoint(input.endpoint),
12
+ context: clone(input.context),
13
+ tools: clone(input.tools),
14
+ options,
15
+ };
16
+ const stablePrefix = {
17
+ providerId: plan.providerId,
18
+ modelId: plan.modelId,
19
+ endpoint: plan.endpoint,
20
+ context: stablePrefixContext(plan.context),
21
+ tools: plan.tools,
22
+ options: plan.options,
23
+ };
24
+ return {
25
+ ...plan,
26
+ fingerprint: sha256(stableJson(plan)),
27
+ stablePrefixFingerprint: sha256(stableJson(stablePrefix)),
28
+ };
29
+ }
30
+ /** Build the plan from a resolved provider when the runner only has the public provider object. */
31
+ export function createProviderRequestPlanForProvider(provider, context, tools, options) {
32
+ const descriptor = provider.descriptor?.() ?? { provider: "unknown", protocol: "unknown", model: "unknown" };
33
+ const identity = provider.requestPlanIdentity?.();
34
+ return createProviderRequestPlan({
35
+ providerId: identity?.providerId ?? descriptor.provider,
36
+ modelId: identity?.modelId ?? descriptor.model,
37
+ endpoint: {
38
+ id: identity?.endpoint?.id ?? `${descriptor.provider}.${descriptor.protocol}`,
39
+ protocol: identity?.endpoint?.protocol ?? descriptor.protocol,
40
+ baseURL: identity?.endpoint?.baseURL ?? "",
41
+ },
42
+ context,
43
+ tools,
44
+ options,
45
+ });
46
+ }
47
+ export function estimateProviderPromptTokens(context, tools) {
48
+ const bytes = new TextEncoder().encode(stableJson({ context, tools })).byteLength;
49
+ return Math.max(1, Math.ceil(bytes / 4));
50
+ }
51
+ /** Bind a preflight count to its exact provider-visible request. Replay only reuses matching facts. */
52
+ export function recordPromptMeasurement(plan, measurement) {
53
+ return {
54
+ requestFingerprint: plan.fingerprint,
55
+ inputTokens: requireNonNegativeInteger(measurement.inputTokens, "inputTokens"),
56
+ source: clone(measurement.source),
57
+ confidence: measurement.confidence,
58
+ };
59
+ }
60
+ export function measurementForPlan(plan, recorded) {
61
+ if (!recorded || recorded.requestFingerprint !== plan.fingerprint)
62
+ return undefined;
63
+ if (!Number.isSafeInteger(recorded.inputTokens) || recorded.inputTokens < 0)
64
+ return undefined;
65
+ if (recorded.confidence !== "exact" && recorded.confidence !== "high_confidence" && recorded.confidence !== "low_confidence")
66
+ return undefined;
67
+ const source = recorded.source;
68
+ if (!source || typeof source !== "object")
69
+ return undefined;
70
+ if (source.kind === "native" && typeof source["provider"] === "string" && source["provider"].length > 0)
71
+ return clone(recorded);
72
+ if (source.kind === "local_exact" && typeof source.tokenizer === "string" && source.tokenizer.length > 0)
73
+ return clone(recorded);
74
+ if (source.kind === "postflight")
75
+ return clone(recorded);
76
+ if (source.kind === "heuristic")
77
+ return clone(recorded);
78
+ return undefined;
79
+ }
80
+ /** Normalize postflight provider facts without turning estimates into actual usage. */
81
+ export function normalizeProviderUsage(usage) {
82
+ const inputTokens = requireNonNegativeInteger(usage.inputTokens, "inputTokens");
83
+ const outputTokens = requireNonNegativeInteger(usage.outputTokens, "outputTokens");
84
+ const cacheReadInputTokens = optionalNonNegativeInteger(usage.cacheReadInputTokens, "cacheReadInputTokens");
85
+ const cacheCreationInputTokens = optionalNonNegativeInteger(usage.cacheCreationInputTokens, "cacheCreationInputTokens");
86
+ const reasoningTokens = optionalNonNegativeInteger(usage.reasoningTokens, "reasoningTokens");
87
+ const cached = (cacheReadInputTokens ?? 0) + (cacheCreationInputTokens ?? 0);
88
+ if (cached > inputTokens)
89
+ throw new RangeError("cache token subsets cannot exceed inputTokens");
90
+ if (reasoningTokens !== undefined && reasoningTokens > outputTokens) {
91
+ throw new RangeError("reasoningTokens must be a subset of outputTokens");
92
+ }
93
+ return {
94
+ inputTokens,
95
+ uncachedInputTokens: inputTokens - cached,
96
+ outputTokens,
97
+ ...(cacheReadInputTokens !== undefined ? { cacheReadInputTokens } : {}),
98
+ ...(cacheCreationInputTokens !== undefined ? { cacheCreationInputTokens } : {}),
99
+ ...(reasoningTokens !== undefined ? { reasoningTokens } : {}),
100
+ };
101
+ }
102
+ /** Cost is derived only from an explicit, time-valid host snapshot; otherwise it stays unknown. */
103
+ export function priceProviderUsage(usage, snapshot, observedAt = new Date()) {
104
+ const at = typeof observedAt === "string" ? new Date(observedAt) : observedAt;
105
+ const from = new Date(snapshot.effectiveFrom);
106
+ const expires = snapshot.expiresAt ? new Date(snapshot.expiresAt) : undefined;
107
+ const rates = snapshot.ratesPerMillion;
108
+ const requiredRates = [rates.input, rates.output];
109
+ if (!snapshot.version || !snapshot.currency || Number.isNaN(at.valueOf()) || Number.isNaN(from.valueOf())
110
+ || requiredRates.some(rate => typeof rate !== "number" || !Number.isFinite(rate) || rate < 0)
111
+ || Object.values(rates).some(rate => typeof rate !== "number" || !Number.isFinite(rate) || rate < 0)) {
112
+ return { source: "unpriced", reason: "invalid_pricing_snapshot" };
113
+ }
114
+ if (at < from)
115
+ return { source: "unpriced", reason: "pricing_snapshot_not_effective" };
116
+ if (expires && (Number.isNaN(expires.valueOf()) || at >= expires)) {
117
+ return { source: "unpriced", reason: "pricing_snapshot_expired" };
118
+ }
119
+ const amount = (usage.uncachedInputTokens * rates.input
120
+ + usage.outputTokens * rates.output
121
+ + (usage.cacheReadInputTokens ?? 0) * (rates.cacheRead ?? rates.input)
122
+ + (usage.cacheCreationInputTokens ?? 0) * (rates.cacheCreation ?? rates.input)
123
+ + (usage.reasoningTokens ?? 0) * (rates.reasoning ?? 0)) / 1_000_000;
124
+ return { source: "snapshot", currency: snapshot.currency, amount, pricingVersion: snapshot.version };
125
+ }
126
+ function materialOptions(options) {
127
+ return sanitizeMaterialValue(options);
128
+ }
129
+ function sanitizeEndpoint(endpoint) {
130
+ try {
131
+ const url = new URL(endpoint.baseURL);
132
+ url.username = "";
133
+ url.password = "";
134
+ url.search = "";
135
+ url.hash = "";
136
+ return { ...clone(endpoint), baseURL: url.toString().replace(/\/$/, "") };
137
+ }
138
+ catch {
139
+ return { ...clone(endpoint), baseURL: "" };
140
+ }
141
+ }
142
+ function sanitizeMaterialValue(value) {
143
+ if (value === undefined || typeof value === "function")
144
+ return undefined;
145
+ if (Array.isArray(value))
146
+ return value.map(sanitizeMaterialValue).filter(item => item !== undefined);
147
+ if (value !== null && typeof value === "object") {
148
+ return Object.fromEntries(Object.keys(value).sort().flatMap(key => {
149
+ if (TRANSPORT_ONLY_KEYS.has(key) || isTransportOnlyKey(key))
150
+ return [];
151
+ const sanitized = sanitizeMaterialValue(value[key]);
152
+ return sanitized === undefined ? [] : [[key, sanitized]];
153
+ }));
154
+ }
155
+ return value;
156
+ }
157
+ function isTransportOnlyKey(key) {
158
+ const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
159
+ return normalized.includes("authorization") || normalized.includes("credential")
160
+ || normalized.includes("accesstoken") || normalized.includes("refreshtoken")
161
+ || normalized.includes("apikey") || normalized === "bearer" || normalized === "token"
162
+ || normalized === "secret" || normalized === "xapikey";
163
+ }
164
+ function stableJson(value) {
165
+ if (value === null || typeof value !== "object")
166
+ return JSON.stringify(value);
167
+ if (Array.isArray(value))
168
+ return `[${value.map(stableJson).join(",")}]`;
169
+ const object = value;
170
+ return `{${Object.keys(object).sort().map(key => `${JSON.stringify(key)}:${stableJson(object[key])}`).join(",")}}`;
171
+ }
172
+ function stablePrefixContext(context) {
173
+ const frozenPrefixLen = context.frozenPrefixLen ?? 0;
174
+ return {
175
+ systemText: context.systemText,
176
+ ...(context.systemStable !== undefined ? { systemStable: context.systemStable } : {}),
177
+ ...(context.systemKnowledge !== undefined ? { systemKnowledge: context.systemKnowledge } : {}),
178
+ frozenPrefixLen,
179
+ turns: clone(context.turns.slice(0, frozenPrefixLen)),
180
+ };
181
+ }
182
+ function sha256(value) {
183
+ return `sha256:${createHash("sha256").update(value).digest("hex")}`;
184
+ }
185
+ function clone(value) {
186
+ if (value === undefined || value === null || typeof value !== "object")
187
+ return value;
188
+ if (Array.isArray(value))
189
+ return value.map(clone);
190
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, clone(item)]));
191
+ }
192
+ function requireNonNegativeInteger(value, name) {
193
+ if (!Number.isSafeInteger(value) || value < 0)
194
+ throw new RangeError(`${name} must be a non-negative safe integer`);
195
+ return value;
196
+ }
197
+ function optionalNonNegativeInteger(value, name) {
198
+ return value === undefined ? undefined : requireNonNegativeInteger(value, name);
199
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * spc_011-C-07: normalizes each vendor's raw postflight usage object into the shared
3
+ * `ProviderUsage` shape (`../types.js`). One function per wire family, not one
4
+ * per provider — DeepSeek/Kimi/GLM/Qwen/MiniMax's OpenAI-wire variants all route through
5
+ * `normalizeOpenAIUsage` via `OpenAIChatProvider` inheritance, and their Anthropic-wire variants
6
+ * route through `normalizeAnthropicUsage` via `AnthropicCompatibleProvider` inheritance — the
7
+ * "8 providers" the spec counts are 8 *providers*, not 8 independent parsing implementations.
8
+ *
9
+ * Reuses `openAICachedPromptTokens` (`./base.js`) for the OpenAI-family cache figure rather than
10
+ * re-deriving it — that function already covers the OpenAI/Qwen/MiniMax/GLM/Kimi standard shape
11
+ * plus DeepSeek's `prompt_cache_hit_tokens` variant.
12
+ *
13
+ * `TokenUsage`/`UsageEvent` are otherwise untouched by this module. Missing or malformed usage
14
+ * returns `undefined`; absence is not a zero-token measurement.
15
+ */
16
+ import type { ProviderUsage } from "../types.js";
17
+ /**
18
+ * Covers both OpenAI wire shapes actually in use: Chat Completions (`prompt_tokens`/
19
+ * `completion_tokens`/`completion_tokens_details.reasoning_tokens`, used by `openai.ts` and every
20
+ * `OpenAIChatProvider` subclass) and the Responses API (`input_tokens`/`output_tokens`/
21
+ * `output_tokens_details.reasoning_tokens`, used by `openai-responses.ts`) — the two field-name
22
+ * conventions are read via fallback, and only one will ever be present on a given raw object.
23
+ */
24
+ export declare function normalizeOpenAIUsage(usage: unknown): ProviderUsage | undefined;
25
+ /**
26
+ * Anthropic's raw `input_tokens` is UNCACHED input only (unlike OpenAI's `prompt_tokens`, which
27
+ * is already cache-inclusive) — `anthropic.ts`'s own `stream()` sums `input_tokens +
28
+ * cache_read_input_tokens + cache_creation_input_tokens` into the full prompt size for the same
29
+ * reason context-pressure accounting needs it (see that file's comment on why excluding cached
30
+ * tokens would suppress compaction until a 413). This function replicates that same sum so
31
+ * `ProviderUsage.inputTokens` means the same "full prompt size" thing across vendors — reading
32
+ * raw `input_tokens` alone here would silently undercount every cache-heavy Anthropic turn.
33
+ * No `reasoning_tokens`-equivalent field exists in this SDK's `Usage` type, so that field stays
34
+ * unset rather than guessed.
35
+ */
36
+ export declare function normalizeAnthropicUsage(usage: unknown): ProviderUsage | undefined;
37
+ /**
38
+ * `@google/generative-ai`'s `UsageMetadata` has no reasoning/thoughts token field and no separate
39
+ * cache-write count (only `cachedContentTokenCount`, a read figure) — `reasoningTokens` and
40
+ * `cacheCreationInputTokens` stay unset rather than invented.
41
+ */
42
+ export declare function normalizeGeminiUsage(usage: unknown): ProviderUsage | undefined;
43
+ /**
44
+ * Ollama's final stream chunk (`done: true`) carries `prompt_eval_count`/`eval_count` — no cache
45
+ * or reasoning concept exists in its API at all, so both stay unset. Before this card `ollama.ts`
46
+ * read neither field; this is the first usage extraction it has ever had.
47
+ */
48
+ export declare function normalizeOllamaUsage(chunk: unknown): ProviderUsage | undefined;
@@ -0,0 +1,139 @@
1
+ import { openAICachedPromptTokens } from "./base.js";
2
+ import { ProtocolResponseError } from "./protocol-adapter.js";
3
+ function readNumber(obj, key, protocol) {
4
+ const value = obj?.[key];
5
+ if (value === undefined || value === null)
6
+ return undefined;
7
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
8
+ throw new ProtocolResponseError(protocol, `usage.${key} must be a non-negative safe integer`);
9
+ }
10
+ return value;
11
+ }
12
+ function hasOwn(obj, key) {
13
+ return obj !== undefined && Object.prototype.hasOwnProperty.call(obj, key);
14
+ }
15
+ function openAICacheTelemetry(usage) {
16
+ const promptDetails = usage?.prompt_tokens_details;
17
+ const inputDetails = usage?.input_tokens_details;
18
+ if (hasOwn(usage, "prompt_cache_hit_tokens") || hasOwn(usage, "prompt_cache_miss_tokens")) {
19
+ return { cacheTelemetryStatus: "measured", cacheTelemetrySource: "deepseek_prompt_cache" };
20
+ }
21
+ if (hasOwn(promptDetails, "cached_tokens") || hasOwn(inputDetails, "cached_tokens")) {
22
+ return { cacheTelemetryStatus: "measured", cacheTelemetrySource: "openai_prompt_details" };
23
+ }
24
+ return { cacheTelemetryStatus: "unavailable" };
25
+ }
26
+ /**
27
+ * Covers both OpenAI wire shapes actually in use: Chat Completions (`prompt_tokens`/
28
+ * `completion_tokens`/`completion_tokens_details.reasoning_tokens`, used by `openai.ts` and every
29
+ * `OpenAIChatProvider` subclass) and the Responses API (`input_tokens`/`output_tokens`/
30
+ * `output_tokens_details.reasoning_tokens`, used by `openai-responses.ts`) — the two field-name
31
+ * conventions are read via fallback, and only one will ever be present on a given raw object.
32
+ */
33
+ export function normalizeOpenAIUsage(usage) {
34
+ const u = usage && typeof usage === "object" ? usage : undefined;
35
+ const protocol = hasOwn(u, "input_tokens") ? "openai-responses" : "openai-chat";
36
+ const rawInput = readNumber(u, "prompt_tokens", protocol) ?? readNumber(u, "input_tokens", protocol);
37
+ const rawOutput = readNumber(u, "completion_tokens", protocol) ?? readNumber(u, "output_tokens", protocol);
38
+ if (rawInput === undefined && rawOutput === undefined)
39
+ return undefined;
40
+ const inputTokens = rawInput ?? 0;
41
+ const outputTokens = rawOutput ?? 0;
42
+ const promptDetails = u?.prompt_tokens_details;
43
+ const inputDetails = u?.input_tokens_details;
44
+ readNumber(promptDetails, "cached_tokens", protocol);
45
+ readNumber(inputDetails, "cached_tokens", protocol);
46
+ const cacheHit = readNumber(u, "prompt_cache_hit_tokens", protocol);
47
+ const cacheMiss = readNumber(u, "prompt_cache_miss_tokens", protocol);
48
+ const cacheReadInputTokens = openAICachedPromptTokens(usage);
49
+ const details = (u?.completion_tokens_details ?? u?.output_tokens_details);
50
+ const reasoningTokens = readNumber(details, "reasoning_tokens", protocol);
51
+ if (cacheReadInputTokens > inputTokens) {
52
+ throw new ProtocolResponseError(protocol, "cache token subsets cannot exceed input tokens");
53
+ }
54
+ if (cacheHit !== undefined && cacheMiss !== undefined && cacheHit + cacheMiss !== inputTokens) {
55
+ throw new ProtocolResponseError(protocol, "DeepSeek cache hit and miss tokens must sum to prompt tokens");
56
+ }
57
+ const providerUsage = {
58
+ inputTokens,
59
+ outputTokens,
60
+ ...(cacheReadInputTokens > 0 ? { cacheReadInputTokens } : {}),
61
+ ...(reasoningTokens !== undefined ? { reasoningTokens } : {}),
62
+ ...openAICacheTelemetry(u),
63
+ };
64
+ return providerUsage;
65
+ }
66
+ /**
67
+ * Anthropic's raw `input_tokens` is UNCACHED input only (unlike OpenAI's `prompt_tokens`, which
68
+ * is already cache-inclusive) — `anthropic.ts`'s own `stream()` sums `input_tokens +
69
+ * cache_read_input_tokens + cache_creation_input_tokens` into the full prompt size for the same
70
+ * reason context-pressure accounting needs it (see that file's comment on why excluding cached
71
+ * tokens would suppress compaction until a 413). This function replicates that same sum so
72
+ * `ProviderUsage.inputTokens` means the same "full prompt size" thing across vendors — reading
73
+ * raw `input_tokens` alone here would silently undercount every cache-heavy Anthropic turn.
74
+ * No `reasoning_tokens`-equivalent field exists in this SDK's `Usage` type, so that field stays
75
+ * unset rather than guessed.
76
+ */
77
+ export function normalizeAnthropicUsage(usage) {
78
+ const u = usage && typeof usage === "object" ? usage : undefined;
79
+ const rawUncachedInput = readNumber(u, "input_tokens", "anthropic-messages");
80
+ const rawCacheRead = readNumber(u, "cache_read_input_tokens", "anthropic-messages");
81
+ const rawCacheCreation = readNumber(u, "cache_creation_input_tokens", "anthropic-messages");
82
+ const rawOutput = readNumber(u, "output_tokens", "anthropic-messages");
83
+ if (rawUncachedInput === undefined && rawCacheRead === undefined && rawCacheCreation === undefined && rawOutput === undefined)
84
+ return undefined;
85
+ const uncachedInput = rawUncachedInput ?? 0;
86
+ const cacheReadInputTokens = rawCacheRead ?? 0;
87
+ const cacheCreationInputTokens = rawCacheCreation ?? 0;
88
+ const outputTokens = rawOutput ?? 0;
89
+ const providerUsage = {
90
+ inputTokens: uncachedInput + cacheReadInputTokens + cacheCreationInputTokens,
91
+ outputTokens,
92
+ ...(cacheReadInputTokens > 0 ? { cacheReadInputTokens } : {}),
93
+ ...(cacheCreationInputTokens > 0 ? { cacheCreationInputTokens } : {}),
94
+ ...(hasOwn(u, "cache_read_input_tokens") || hasOwn(u, "cache_creation_input_tokens")
95
+ ? { cacheTelemetryStatus: "measured", cacheTelemetrySource: "anthropic_usage" }
96
+ : { cacheTelemetryStatus: "unavailable" }),
97
+ };
98
+ return providerUsage;
99
+ }
100
+ /**
101
+ * `@google/generative-ai`'s `UsageMetadata` has no reasoning/thoughts token field and no separate
102
+ * cache-write count (only `cachedContentTokenCount`, a read figure) — `reasoningTokens` and
103
+ * `cacheCreationInputTokens` stay unset rather than invented.
104
+ */
105
+ export function normalizeGeminiUsage(usage) {
106
+ const u = usage && typeof usage === "object" ? usage : undefined;
107
+ const rawInput = readNumber(u, "promptTokenCount", "gemini");
108
+ const rawOutput = readNumber(u, "candidatesTokenCount", "gemini");
109
+ if (rawInput === undefined && rawOutput === undefined)
110
+ return undefined;
111
+ const inputTokens = rawInput ?? 0;
112
+ const outputTokens = rawOutput ?? 0;
113
+ const cacheReadInputTokens = readNumber(u, "cachedContentTokenCount", "gemini");
114
+ if ((cacheReadInputTokens ?? 0) > inputTokens) {
115
+ throw new ProtocolResponseError("gemini", "cache token subsets cannot exceed input tokens");
116
+ }
117
+ const providerUsage = {
118
+ inputTokens,
119
+ outputTokens,
120
+ ...(cacheReadInputTokens ? { cacheReadInputTokens } : {}),
121
+ ...(hasOwn(u, "cachedContentTokenCount")
122
+ ? { cacheTelemetryStatus: "measured", cacheTelemetrySource: "gemini_usage" }
123
+ : { cacheTelemetryStatus: "unavailable" }),
124
+ };
125
+ return providerUsage;
126
+ }
127
+ /**
128
+ * Ollama's final stream chunk (`done: true`) carries `prompt_eval_count`/`eval_count` — no cache
129
+ * or reasoning concept exists in its API at all, so both stay unset. Before this card `ollama.ts`
130
+ * read neither field; this is the first usage extraction it has ever had.
131
+ */
132
+ export function normalizeOllamaUsage(chunk) {
133
+ const u = chunk && typeof chunk === "object" ? chunk : undefined;
134
+ const rawInput = readNumber(u, "prompt_eval_count", "ollama-chat");
135
+ const rawOutput = readNumber(u, "eval_count", "ollama-chat");
136
+ if (rawInput === undefined && rawOutput === undefined)
137
+ return undefined;
138
+ return { inputTokens: rawInput ?? 0, outputTokens: rawOutput ?? 0, cacheTelemetryStatus: "unavailable" };
139
+ }
@@ -1,6 +1,5 @@
1
- import type { RuntimePolicy } from "../types.js";
2
- import { endpointProfiles } from "./profiles.js";
3
- import type { ProviderId } from "./profiles.js";
1
+ import { endpointProfiles } from "./endpoints.js";
2
+ import type { ProviderId } from "./endpoints.js";
4
3
  export type EndpointProfileKey = keyof typeof endpointProfiles;
5
4
  export interface AnthropicVendorProfile {
6
5
  /** Identity advertised in `descriptor().provider`. */
@@ -9,44 +8,32 @@ export interface AnthropicVendorProfile {
9
8
  defaultModel: string;
10
9
  /** Endpoint profile whose `baseURL` is the Anthropic-compatible wire for this vendor. */
11
10
  baseURLProfileKey: EndpointProfileKey;
12
- /** Recommended `maxTurns` per model id; missing model → empty policy. */
13
- policies: Record<string, RuntimePolicy>;
14
11
  }
15
- export declare const DEEPSEEK_POLICIES: Record<string, RuntimePolicy>;
16
- export declare const KIMI_POLICIES: Record<string, RuntimePolicy>;
17
- export declare const QWEN_POLICIES: Record<string, RuntimePolicy>;
18
- export declare const GLM_POLICIES: Record<string, RuntimePolicy>;
19
- export declare const MINIMAX_POLICIES: Record<string, RuntimePolicy>;
20
12
  export declare const anthropicVendorProfiles: {
21
13
  deepseek: {
22
14
  providerId: "deepseek";
23
15
  defaultModel: string;
24
16
  baseURLProfileKey: "deepseek.anthropic";
25
- policies: Record<string, RuntimePolicy>;
26
17
  };
27
18
  kimi: {
28
19
  providerId: "kimi";
29
20
  defaultModel: string;
30
21
  baseURLProfileKey: "kimi.anthropic";
31
- policies: Record<string, RuntimePolicy>;
32
22
  };
33
23
  qwen: {
34
24
  providerId: "qwen";
35
25
  defaultModel: string;
36
26
  baseURLProfileKey: "qwen.anthropic";
37
- policies: Record<string, RuntimePolicy>;
38
27
  };
39
28
  glm: {
40
29
  providerId: "glm";
41
30
  defaultModel: string;
42
31
  baseURLProfileKey: "glm.anthropic";
43
- policies: Record<string, RuntimePolicy>;
44
32
  };
45
33
  minimax: {
46
34
  providerId: "minimax";
47
35
  defaultModel: string;
48
36
  baseURLProfileKey: "minimax.anthropic";
49
- policies: Record<string, RuntimePolicy>;
50
37
  };
51
38
  };
52
39
  export type AnthropicVendorId = keyof typeof anthropicVendorProfiles;
@@ -1,64 +1,18 @@
1
- import { endpointProfiles } from "./profiles.js";
2
- export const DEEPSEEK_POLICIES = {
3
- "deepseek-chat": { maxTurns: 25 },
4
- "deepseek-reasoner": { maxTurns: 50 },
5
- "deepseek-v4-flash": { maxTurns: 20 },
6
- "deepseek-v4-pro": { maxTurns: 35 },
7
- };
8
- export const KIMI_POLICIES = {
9
- "moonshot-v1-8k": { maxTurns: 15 },
10
- "moonshot-v1-32k": { maxTurns: 20 },
11
- "moonshot-v1-128k": { maxTurns: 30 },
12
- "kimi-k2.5": { maxTurns: 30 },
13
- "kimi-k2.6": { maxTurns: 35 },
14
- "kimi-k2-thinking": { maxTurns: 50 },
15
- "kimi-k2-thinking-turbo": { maxTurns: 40 },
16
- };
17
- export const QWEN_POLICIES = {
18
- "qwen3.7-max-preview": { maxTurns: 45 },
19
- "qwen3.7-plus-preview": { maxTurns: 40 },
20
- "qwen3.6-max-preview": { maxTurns: 40 },
21
- "qwen3.6-plus": { maxTurns: 35 },
22
- "qwen3.6-flash": { maxTurns: 20 },
23
- "qwen3.6-35b-a3b": { maxTurns: 25 },
24
- "qwen3.6-27b": { maxTurns: 25 },
25
- "qwen3.5-plus": { maxTurns: 35 },
26
- "qwen3.5-flash": { maxTurns: 20 },
27
- "qwen3.5-397b-a17b": { maxTurns: 35 },
28
- "qwen3.5-122b-a10b": { maxTurns: 25 },
29
- "qwen3.5-35b-a3b": { maxTurns: 20 },
30
- "qwen3.5-27b": { maxTurns: 20 },
31
- };
32
- export const GLM_POLICIES = {
33
- "glm-5.2": { maxTurns: 50 },
34
- "glm/glm-5.2": { maxTurns: 50 },
35
- "glm-5.1": { maxTurns: 50 },
36
- "glm/glm-5.1": { maxTurns: 50 },
37
- "glm-4-plus": { maxTurns: 35 },
38
- "glm/glm-4-plus": { maxTurns: 35 },
39
- "glm-4-flash": { maxTurns: 15 },
40
- "glm/glm-4-flash": { maxTurns: 15 },
41
- "glm-4-air": { maxTurns: 20 },
42
- "glm/glm-4-air": { maxTurns: 20 },
43
- };
44
- export const MINIMAX_POLICIES = {
45
- "MiniMax-M3": { maxTurns: 35 },
46
- "MiniMax-M3-highspeed": { maxTurns: 35 },
47
- "MiniMax-M2.7": { maxTurns: 35 },
48
- "MiniMax-M2.7-highspeed": { maxTurns: 35 },
49
- "MiniMax-M2.5": { maxTurns: 25 },
50
- "MiniMax-M2.5-highspeed": { maxTurns: 25 },
51
- "MiniMax-M2.1": { maxTurns: 25 },
52
- "MiniMax-M2.1-highspeed": { maxTurns: 25 },
53
- "MiniMax-M2": { maxTurns: 20 },
54
- "MiniMax-Text-01": { maxTurns: 20 },
55
- };
1
+ // Single source of truth for the Anthropic-compatible vendor backends (DeepSeek,
2
+ // Kimi, Qwen, GLM, MiniMax). Each backend differs only by data — provider id,
3
+ // default model, endpoint, and per-model runtime policy so the generic
4
+ // `AnthropicCompatibleProvider` reads a profile from here instead of every
5
+ // backend subclassing `AnthropicProvider` purely to carry configuration.
6
+ //
7
+ // Runtime policy and default model resolution live in ModelRegistry; this module
8
+ // only carries Anthropic-compatible transport configuration.
9
+ import { endpointProfiles } from "./endpoints.js";
56
10
  export const anthropicVendorProfiles = {
57
- deepseek: { providerId: "deepseek", defaultModel: "deepseek-v4-flash", baseURLProfileKey: "deepseek.anthropic", policies: DEEPSEEK_POLICIES },
58
- kimi: { providerId: "kimi", defaultModel: "kimi-k2.6", baseURLProfileKey: "kimi.anthropic", policies: KIMI_POLICIES },
59
- qwen: { providerId: "qwen", defaultModel: "qwen3.6-plus", baseURLProfileKey: "qwen.anthropic", policies: QWEN_POLICIES },
60
- glm: { providerId: "glm", defaultModel: "glm-5.2", baseURLProfileKey: "glm.anthropic", policies: GLM_POLICIES },
61
- minimax: { providerId: "minimax", defaultModel: "MiniMax-M3", baseURLProfileKey: "minimax.anthropic", policies: MINIMAX_POLICIES },
11
+ deepseek: { providerId: "deepseek", defaultModel: "deepseek-v4-flash", baseURLProfileKey: "deepseek.anthropic" },
12
+ kimi: { providerId: "kimi", defaultModel: "kimi-k2.6", baseURLProfileKey: "kimi.anthropic" },
13
+ qwen: { providerId: "qwen", defaultModel: "qwen3.6-plus", baseURLProfileKey: "qwen.anthropic" },
14
+ glm: { providerId: "glm", defaultModel: "glm-5.2", baseURLProfileKey: "glm.anthropic" },
15
+ minimax: { providerId: "minimax", defaultModel: "MiniMax-M3", baseURLProfileKey: "minimax.anthropic" },
62
16
  };
63
17
  /** Resolve the Anthropic-compatible base URL for a vendor profile. */
64
18
  export function anthropicVendorBaseURL(profile) {
@@ -95,8 +95,7 @@ export interface CanonicalRunnerRuntimeOptions {
95
95
  }
96
96
  /**
97
97
  * Canonical operation runtime used by the Node host.
98
- * Every durable transition below is one of the canonical ABI's five input classes; no legacy
99
- * envelope or synthesized host transaction reaches core or storage.
98
+ * Every durable transition below is one of the canonical contract's five input classes.
100
99
  */
101
100
  export declare class CanonicalRunnerRuntime {
102
101
  private readonly options;