@deepstrike/sdk 0.2.62 → 0.2.63

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/LICENSE ADDED
@@ -0,0 +1,106 @@
1
+ DeepStrike License (Dual License)
2
+ Version 1.0 — 2026-09-01
3
+
4
+ Copyright (c) 2025-2026 DeepStrike Contributors
5
+ Project: https://github.com/kongusen/deepstrike
6
+
7
+ ======================================================================
8
+ 中文摘要(便于理解,不具有法律效力;以下英文条款为准)
9
+ ======================================================================
10
+
11
+ 本软件采用双授权模式:
12
+
13
+ 1. 个人,以及上一财年总营收低于 1,000,000 美元的组织(含其关联方),
14
+ 可按 MIT 条款免费使用本软件(见第 2 节),包括使用、复制、修改、
15
+ 合并、发布、分发、再授权及销售的权利。
16
+ 2. 上一财年总营收达到或超过 1,000,000 美元的组织(含其关联方),
17
+ 在使用本软件之前(包括内部使用、基于本软件开发的项目、以及对外
18
+ 分发此类产品或服务)须向作者获取商业授权(见第 3 节)。
19
+ 获取方式:发送邮件至 wanghaishan0210@gmail.com,或通过
20
+ https://github.com/kongusen/deepstrike 提交 Issue / Discussion
21
+ 联系作者。出于评估目的的试用不超过 30 天除外。
22
+ 3. 当组织的年营收增长至达到或超过该阈值时,自该时点起第 2 节的免费
23
+ 授权终止,须获取商业授权后方可继续使用。
24
+ 4. v0.2.62 及之前已经以 MIT 协议发布的版本继续适用 MIT 协议,不受
25
+ 本协议影响。本协议仅适用于随其一同分发的版本。
26
+
27
+ ======================================================================
28
+ TERMS AND CONDITIONS
29
+ ======================================================================
30
+
31
+ 1. DEFINITIONS
32
+
33
+ "Software" means the DeepStrike software and associated documentation
34
+ files distributed by the Licensor, including all copies and substantial
35
+ portions thereof.
36
+
37
+ "Licensor" means the copyright holders of the Software (the DeepStrike
38
+ Contributors), represented by the project maintainer at
39
+ https://github.com/kongusen/deepstrike.
40
+
41
+ "You" (or "Licensee") means the individual or legal entity exercising
42
+ permissions granted by this License, including, where that entity is an
43
+ organization, all entities that control, are controlled by, or are under
44
+ common control with that entity ("Affiliates"). "Control" means ownership
45
+ of more than fifty percent (50%) of the equity or voting interests, or
46
+ the power to direct management and policies.
47
+
48
+ "Annual Revenue" means the total gross revenue of You and Your Affiliates
49
+ for the most recently completed fiscal year, expressed in US dollars or
50
+ converted into US dollars at prevailing exchange rates.
51
+
52
+ 2. FREE LICENSE FOR INDIVIDUALS AND SMALL ORGANIZATIONS
53
+
54
+ If You are an individual, or a legal entity whose Annual Revenue is less
55
+ than one million US dollars (USD 1,000,000), the Licensor hereby grants
56
+ You, free of charge, permission to deal in the Software without
57
+ restriction, including without limitation the rights to use, copy, modify,
58
+ merge, publish, distribute, sublicense, and/or sell copies of the
59
+ Software, and to permit persons to whom the Software is furnished to do
60
+ so, subject to the following conditions:
61
+
62
+ (a) The above copyright notice and this License shall be included in all
63
+ copies or substantial portions of the Software.
64
+
65
+ (b) If Your Annual Revenue reaches or exceeds USD 1,000,000, the grant in
66
+ this Section 2 terminates for You, and Section 3 applies from that
67
+ point on.
68
+
69
+ 3. COMMERCIAL LICENSE REQUIRED (ANNUAL REVENUE >= USD 1,000,000)
70
+
71
+ If Your Annual Revenue equals or exceeds one million US dollars
72
+ (USD 1,000,000), You must obtain a commercial license from the Licensor
73
+ before using the Software. This applies to every form of use, including
74
+ internal use, use within products or services developed based on the
75
+ Software, and distribution or provision of such products or services to
76
+ third parties.
77
+
78
+ Exception: You may use the Software without a commercial license solely
79
+ for evaluation purposes, for a period of up to thirty (30) days.
80
+
81
+ To obtain a commercial license, contact the Licensor at
82
+ wanghaishan0210@gmail.com, or via the project repository at
83
+ https://github.com/kongusen/deepstrike (open an issue or discussion).
84
+ Commercial terms, including fees, are set by individual agreement with
85
+ the Licensor.
86
+
87
+ Any use of the Software requiring a commercial license under this
88
+ Section 3 without one is unlicensed use and constitutes copyright
89
+ infringement.
90
+
91
+ 4. PRIOR VERSIONS
92
+
93
+ Versions of the Software released before this License took effect (up to
94
+ and including version 0.2.62) were released under the MIT License and
95
+ remain available under the terms of the MIT License. This License applies
96
+ only to versions of the Software distributed together with it.
97
+
98
+ 5. NO WARRANTY
99
+
100
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
101
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
102
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
103
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
104
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
105
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
106
+ DEALINGS IN THE SOFTWARE.
package/dist/index.d.ts CHANGED
@@ -13,7 +13,9 @@ export type { ContextPolicyOverrides, ContextPolicy, ContextPolicyWire, ContextP
13
13
  export { LocalExecutionPlane } from "./runtime/execution-plane.js";
14
14
  export type { ExecutionPlane, RunContext } from "./runtime/execution-plane.js";
15
15
  export { InMemorySessionLog, FileSessionLog } from "./runtime/session-log.js";
16
- export type { SessionLog, SessionEvent } from "./runtime/session-log.js";
16
+ export type { SessionLog, SessionEvent, SessionEventKind } from "./runtime/session-log.js";
17
+ export { SESSION_EVENT_KINDS } from "./runtime/session-log.js";
18
+ export { CANONICAL_CONTENT_PARTS_PREFIX, encodeCanonicalContentParts, decodeCanonicalContentParts, } from "./runtime/kernel-step.js";
17
19
  export { FileKernelJournal, InMemoryKernelJournal, JournalCasConflictError, JournalIntegrityError, JournalIoError, } from "./runtime/kernel-journal.js";
18
20
  export type { CheckpointCandidate, InstalledCheckpoint, JournalAppendReceipt, JournalEntry, JournalHead, JournalPruneReceipt, JournalRecordInput, KernelJournal, } from "./runtime/kernel-journal.js";
19
21
  export { diagnoseKernelJournal } from "./runtime/kernel-doctor.js";
@@ -43,8 +45,10 @@ export { OpenAIResponsesProvider } from "./providers/openai-responses.js";
43
45
  export { createProvider, createProviderAsync, resolveProviderRuntime, resolveProviderRuntimeAsync } from "./providers/catalog.js";
44
46
  export { UnsupportedModalityError } from "./providers/base.js";
45
47
  export type { CreateProviderOptions, EndpointProfileId } from "./providers/catalog.js";
46
- export { createProviderRequestPlan, createProviderRequestPlanForProvider, estimateProviderPromptTokens, measurementForPlan, normalizeProviderUsage, priceProviderUsage, recordPromptMeasurement } from "./providers/request-plan.js";
47
- export type { CostObservation, NormalizedProviderUsage, PricingSnapshot, ProviderRequestEndpoint, ProviderRequestPlan, RecordedPromptMeasurement } from "./providers/request-plan.js";
48
+ export { createProviderRequestPlan, createProviderRequestPlanForProvider, estimateProviderPromptTokens, measurementForPlan, normalizeProviderUsage, priceProviderUsage, recordPromptMeasurement, resolveProviderRoute } from "./providers/request-plan.js";
49
+ export type { CostObservation, NormalizedProviderUsage, PricingSnapshot, ProviderRequestEndpoint, ProviderRequestPlan, RecordedPromptMeasurement, ResolvedProviderRoute } from "./providers/request-plan.js";
50
+ export { FULL_FOOTPRINT_USAGE_ACCOUNTING_POLICY } from "./runtime/execution-evidence.js";
51
+ export type { InvocationOutcome, ModelInvocation, ProviderAttempt, ProviderAttemptRecord, ProviderAttemptStatus, UsageAccountingPolicy, UsageSettlement } from "./runtime/execution-evidence.js";
48
52
  export type { GovernancePolicy, GovernanceConstraint } from "./governance.js";
49
53
  export { AgentPool } from "./collaboration/pool.js";
50
54
  export { Agent } from "./agent.js";
@@ -57,7 +61,7 @@ export type { Knowledge, KnowledgeSourceRef } from "./knowledge/public.js";
57
61
  export type { AgentRef, Handoff } from "./handoff-target.js";
58
62
  export type { Session } from "./session.js";
59
63
  export type { RuntimeSignal, SignalClaim, SignalDeliveryReceipt, SignalSource, } from "./signals/types.js";
60
- export type { Message, ToolCall, ToolResult, ToolSchema, ContentPart, TextPart, ImagePart, AudioPart, MediaSource, ContentBlockText, ContentBlockImage, ContentBlockAudio, ContentBlockVideo, ContentBlockFile, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolChunk, ToolDeltaEvent, ToolSuspendEvent, ToolResultEvent, ToolAuditFailedEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, PermissionResolvedEvent, PermissionResponse, EntropySample, EntropySampleEvent, EntropyAlertEvent, EntropyWatchOptions, LLMProvider, RetryConfig, TokenUsage, } from "./types.js";
64
+ export type { Message, ToolCall, ToolResult, ToolSchema, ContentPart, TextPart, ImagePart, AudioPart, MediaSource, ContentBlockText, ContentBlockImage, ContentBlockAudio, ContentBlockVideo, ContentBlockFile, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolChunk, ToolDeltaEvent, ToolSuspendEvent, ToolResultEvent, ToolAuditFailedEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, PermissionResolvedEvent, PermissionResponse, EntropySample, EntropySampleEvent, EntropyAlertEvent, EntropyWatchOptions, LLMProvider, RetryConfig, TokenUsage, ProviderWireEvidence, ProviderTransportTelemetry, } from "./types.js";
61
65
  export { DurableContentError, decodeDurableContent, decodeDurableToolResult, encodeDurableContent, encodeDurableToolResult, toolOutputBlocksToDurable, durableBlocksToToolOutput, } from "./runtime/durable-content.js";
62
66
  export type { DurableContent, DurableContentBlock, DurableSource, DurableToolResult } from "./runtime/durable-content.js";
63
67
  export type { WorkflowSpec, WorkflowNodeSpec, SchedulingFactors, WorkflowDependencyPolicy, WorkflowNodeStatus, WorkflowNodeOutcome, WorkflowOutcome, } from "./types/agent.js";
package/dist/index.js CHANGED
@@ -20,6 +20,10 @@ export { DEFAULT_CONTEXT_POLICY, PPM_SCALE, contextPolicy, normalizeContextPolic
20
20
  // ── Execution plane + session log (the defaults) ────────────────────────────
21
21
  export { LocalExecutionPlane } from "./runtime/execution-plane.js";
22
22
  export { InMemorySessionLog, FileSessionLog } from "./runtime/session-log.js";
23
+ // Registered session-event vocabulary (F9/S3; manifest-pinned by sdk-conformance, P7-S4)
24
+ export { SESSION_EVENT_KINDS } from "./runtime/session-log.js";
25
+ // ── content-parts-v1 registered encoding (F14/B5; byte-pinned by sdk-conformance) ──
26
+ export { CANONICAL_CONTENT_PARTS_PREFIX, encodeCanonicalContentParts, decodeCanonicalContentParts, } from "./runtime/kernel-step.js";
23
27
  // ── Durable transaction capability (Canonical Kernel ABI §9.1) ──────────────
24
28
  export { FileKernelJournal, InMemoryKernelJournal, JournalCasConflictError, JournalIntegrityError, JournalIoError, } from "./runtime/kernel-journal.js";
25
29
  export { diagnoseKernelJournal } from "./runtime/kernel-doctor.js";
@@ -40,7 +44,8 @@ export { OpenAIProvider } from "./providers/openai.js";
40
44
  export { OpenAIResponsesProvider } from "./providers/openai-responses.js";
41
45
  export { createProvider, createProviderAsync, resolveProviderRuntime, resolveProviderRuntimeAsync } from "./providers/catalog.js";
42
46
  export { UnsupportedModalityError } from "./providers/base.js";
43
- export { createProviderRequestPlan, createProviderRequestPlanForProvider, estimateProviderPromptTokens, measurementForPlan, normalizeProviderUsage, priceProviderUsage, recordPromptMeasurement } from "./providers/request-plan.js";
47
+ export { createProviderRequestPlan, createProviderRequestPlanForProvider, estimateProviderPromptTokens, measurementForPlan, normalizeProviderUsage, priceProviderUsage, recordPromptMeasurement, resolveProviderRoute } from "./providers/request-plan.js";
48
+ export { FULL_FOOTPRINT_USAGE_ACCOUNTING_POLICY } from "./runtime/execution-evidence.js";
44
49
  // ── Multi-agent primitive ───────────────────────────────────────────────────
45
50
  // Parallel fan-out / sub-agent delegation. The full orchestration layer is in `@deepstrike/sdk/workflow`.
46
51
  export { AgentPool } from "./collaboration/pool.js";
@@ -1,4 +1,4 @@
1
- import type { LLMProvider, Message, PromptMeasurement, ProviderDescriptor, ProviderReplay, ProviderRunState, RenderedContext, RuntimePolicy, StreamEvent, ToolSchema } from "../types.js";
1
+ import type { LLMProvider, Message, PromptMeasurement, ProviderDescriptor, ProviderReplay, ProviderRunState, ProviderTransportTelemetry, RenderedContext, RuntimePolicy, StreamEvent, ToolSchema } from "../types.js";
2
2
  import { type CanonicalAdapterInput } from "./content-normalization.js";
3
3
  export interface AnthropicProviderConfig {
4
4
  apiKey: string;
@@ -29,6 +29,10 @@ export declare class AnthropicProvider implements LLMProvider {
29
29
  /** Identity advertised in the descriptor; overridden by Anthropic-compatible vendors. */
30
30
  protected providerName(): string;
31
31
  descriptor(): ProviderDescriptor;
32
+ /** P4-S1: transport facts of the most recent execution (rung count + wire response id).
33
+ * Host evidence only — never kernel input (B7). */
34
+ private lastTelemetry;
35
+ peekTransportTelemetry(): ProviderTransportTelemetry | undefined;
32
36
  bindResolvedRuntime(resolved: ResolvedAnthropicRuntime): void;
33
37
  peekProviderReplay(message: Pick<Message, "content" | "toolCalls">): ProviderReplay | undefined;
34
38
  seedProviderReplay(message: Pick<Message, "content" | "toolCalls">, replay: ProviderReplay): void;
@@ -70,6 +70,12 @@ export class AnthropicProvider {
70
70
  },
71
71
  };
72
72
  }
73
+ /** P4-S1: transport facts of the most recent execution (rung count + wire response id).
74
+ * Host evidence only — never kernel input (B7). */
75
+ lastTelemetry;
76
+ peekTransportTelemetry() {
77
+ return this.lastTelemetry;
78
+ }
73
79
  bindResolvedRuntime(resolved) {
74
80
  if (resolved.identity.protocol !== "anthropic-messages"
75
81
  || resolved.identity.providerId !== this.providerName()
@@ -138,8 +144,11 @@ export class AnthropicProvider {
138
144
  let lastErr;
139
145
  for (let attempt = 0; attempt < this.maxRetries; attempt++) {
140
146
  try {
147
+ this.lastTelemetry = { rungs: attempt + 1 };
141
148
  const raw = await this.createMessage(plan.params, plan.transport);
142
149
  this.circuit.recordSuccess();
150
+ if (typeof raw.id === "string")
151
+ this.lastTelemetry = { rungs: attempt + 1, responseId: raw.id };
143
152
  const decoded = this.adapter.decodeComplete(raw, { input });
144
153
  if (decoded.replay?.native_blocks) {
145
154
  this.rememberNativeBlocks(decoded.message, decoded.replay.native_blocks);
@@ -183,7 +192,13 @@ export class AnthropicProvider {
183
192
  try {
184
193
  const { input, plan } = this.buildPlan(context, tools, extensions);
185
194
  const state = this.adapter.createStreamState({ input });
195
+ this.lastTelemetry = { rungs: 1 };
186
196
  for await (const chunk of this.streamMessage(plan.params, plan.transport, signal)) {
197
+ if (this.lastTelemetry.responseId === undefined && chunk.type === "message_start") {
198
+ const id = chunk.message?.id;
199
+ if (typeof id === "string")
200
+ this.lastTelemetry = { rungs: 1, responseId: id };
201
+ }
187
202
  for (const event of this.adapter.pushStreamChunk(chunk, state).events)
188
203
  yield event;
189
204
  }
@@ -1,5 +1,5 @@
1
1
  import { type Content } from "@google/generative-ai";
2
- import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider, RuntimePolicy, PromptMeasurement } from "../types.js";
2
+ import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider, RuntimePolicy, PromptMeasurement, ProviderTransportTelemetry } from "../types.js";
3
3
  import { type CanonicalAdapterInput } from "./content-normalization.js";
4
4
  type ResolvedGeminiRuntime = CanonicalAdapterInput["resolved"];
5
5
  export declare function buildContents(turns: Message[]): Content[];
@@ -13,6 +13,9 @@ export declare class GeminiProvider implements LLMProvider {
13
13
  private requestOptions;
14
14
  private readonly resolvedRuntimePolicy;
15
15
  private readonly adapter;
16
+ /** P4-S1: transport facts of the most recent execution. Host evidence only (B7). */
17
+ private lastTelemetry;
18
+ peekTransportTelemetry(): ProviderTransportTelemetry | undefined;
16
19
  constructor(apiKey: string, model?: string, retry?: {
17
20
  maxRetries: number;
18
21
  baseDelay: number;
@@ -19,6 +19,11 @@ export class GeminiProvider {
19
19
  requestOptions;
20
20
  resolvedRuntimePolicy;
21
21
  adapter = new GeminiAdapter();
22
+ /** P4-S1: transport facts of the most recent execution. Host evidence only (B7). */
23
+ lastTelemetry;
24
+ peekTransportTelemetry() {
25
+ return this.lastTelemetry;
26
+ }
22
27
  constructor(apiKey, model = "gemini-2.0-flash", retry = { maxRetries: 3, baseDelay: 1000 }, baseURL = GEMINI_BASE, runtimePolicy = {}, resolvedRuntime) {
23
28
  this.model = model;
24
29
  this.resolvedRuntime = resolvedRuntime;
@@ -89,9 +94,13 @@ export class GeminiProvider {
89
94
  let lastErr;
90
95
  for (let i = 0; i < this.maxRetries; i++) {
91
96
  try {
97
+ this.lastTelemetry = { rungs: i + 1 };
92
98
  const m = this.genAI.getGenerativeModel(plan.modelParams, this.requestOptions);
93
99
  const resp = await m.generateContent(plan.request);
94
100
  this.circuit.recordSuccess();
101
+ const responseId = resp.response.responseId;
102
+ if (typeof responseId === "string")
103
+ this.lastTelemetry = { rungs: i + 1, responseId };
95
104
  return this.adapter.decodeComplete(resp.response, { input }).message;
96
105
  }
97
106
  catch (err) {
@@ -110,11 +119,16 @@ export class GeminiProvider {
110
119
  const m = this.genAI.getGenerativeModel(plan.modelParams, this.requestOptions);
111
120
  const result = await m.generateContentStream(plan.request);
112
121
  const state = this.adapter.createStreamState({ input });
122
+ this.lastTelemetry = { rungs: 1 };
113
123
  for await (const chunk of result.stream) {
114
124
  for (const event of this.adapter.pushStreamChunk(chunk, state).events)
115
125
  yield event;
116
126
  }
117
- for (const event of this.adapter.finishStream(state, await result.response).events)
127
+ const finalResponse = await result.response;
128
+ const responseId = finalResponse.responseId;
129
+ if (typeof responseId === "string")
130
+ this.lastTelemetry = { rungs: 1, responseId };
131
+ for (const event of this.adapter.finishStream(state, finalResponse).events)
118
132
  yield event;
119
133
  }
120
134
  catch (error) {
@@ -1,4 +1,4 @@
1
- import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider, RuntimePolicy } from "../types.js";
1
+ import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider, RuntimePolicy, ProviderTransportTelemetry } from "../types.js";
2
2
  import { type CanonicalAdapterInput } from "./content-normalization.js";
3
3
  type ResolvedOllamaRuntime = CanonicalAdapterInput["resolved"];
4
4
  export declare class OllamaProvider implements LLMProvider {
@@ -8,6 +8,9 @@ export declare class OllamaProvider implements LLMProvider {
8
8
  private resolvedRuntime?;
9
9
  private readonly adapter;
10
10
  constructor(model?: string, baseUrl?: string, resolvedRuntimePolicy?: RuntimePolicy, resolvedRuntime?: ResolvedOllamaRuntime | undefined);
11
+ /** P4-S1: transport facts of the most recent execution (Ollama's wire has no response id). */
12
+ private lastTelemetry;
13
+ peekTransportTelemetry(): ProviderTransportTelemetry | undefined;
11
14
  runtimePolicy(): RuntimePolicy;
12
15
  bindResolvedRuntime(resolved: ResolvedOllamaRuntime): void;
13
16
  private adapterInput;
@@ -14,6 +14,11 @@ export class OllamaProvider {
14
14
  this.resolvedRuntimePolicy = resolvedRuntimePolicy;
15
15
  this.resolvedRuntime = resolvedRuntime;
16
16
  }
17
+ /** P4-S1: transport facts of the most recent execution (Ollama's wire has no response id). */
18
+ lastTelemetry;
19
+ peekTransportTelemetry() {
20
+ return this.lastTelemetry;
21
+ }
17
22
  runtimePolicy() {
18
23
  return this.resolvedRuntimePolicy;
19
24
  }
@@ -53,6 +58,7 @@ export class OllamaProvider {
53
58
  try {
54
59
  const input = this.adapterInput(context, tools, extensions);
55
60
  const body = { ...this.adapter.buildRequest(input), stream: false };
61
+ this.lastTelemetry = { rungs: 1 };
56
62
  const resp = await fetch(`${this.baseUrl}/api/chat`, {
57
63
  method: "POST",
58
64
  headers: { "Content-Type": "application/json" },
@@ -71,6 +77,7 @@ export class OllamaProvider {
71
77
  try {
72
78
  const input = this.adapterInput(context, tools, extensions);
73
79
  const body = { ...this.adapter.buildRequest(input), stream: true };
80
+ this.lastTelemetry = { rungs: 1 };
74
81
  const resp = await fetch(`${this.baseUrl}/api/chat`, {
75
82
  method: "POST",
76
83
  headers: { "Content-Type": "application/json" },
@@ -1,5 +1,5 @@
1
1
  import OpenAI from "openai";
2
- import type { LLMProvider, Message, PromptMeasurement, ProviderRunState, RenderedContext, RuntimePolicy, StreamEvent, ToolSchema } from "../types.js";
2
+ import type { LLMProvider, Message, PromptMeasurement, ProviderRunState, ProviderTransportTelemetry, RenderedContext, RuntimePolicy, StreamEvent, ToolSchema } from "../types.js";
3
3
  import { CircuitBreaker } from "./base.js";
4
4
  import { type CanonicalAdapterInput } from "./content-normalization.js";
5
5
  import { OpenAIResponsesAdapter, type OpenAIResponsesRunState } from "./openai-responses-adapter.js";
@@ -32,5 +32,8 @@ export declare class OpenAIResponsesProvider implements LLMProvider {
32
32
  stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState, signal?: AbortSignal): AsyncIterable<StreamEvent>;
33
33
  private builtinTools;
34
34
  private requestExtensions;
35
+ /** P4-S1: transport facts of the most recent execution. Host evidence only (B7). */
36
+ private lastTelemetry;
37
+ peekTransportTelemetry(): ProviderTransportTelemetry | undefined;
35
38
  private asRunState;
36
39
  }
@@ -86,8 +86,12 @@ export class OpenAIResponsesProvider {
86
86
  let lastError;
87
87
  for (let attempt = 0; attempt < this.maxRetries; attempt++) {
88
88
  try {
89
+ this.lastTelemetry = { rungs: attempt + 1 };
89
90
  const response = await this.client.responses.create(plan.params);
90
91
  this.circuit.recordSuccess();
92
+ const responseId = response.id;
93
+ if (typeof responseId === "string")
94
+ this.lastTelemetry = { rungs: attempt + 1, responseId };
91
95
  return this.responses.decodeComplete(response, { input }).message;
92
96
  }
93
97
  catch (error) {
@@ -130,7 +134,14 @@ export class OpenAIResponsesProvider {
130
134
  const plan = this.responses.buildRequest(input, runState);
131
135
  const streamState = this.responses.createStreamState({ input }, runState);
132
136
  const stream = await this.client.responses.create({ ...plan.params, stream: true }, signal ? { signal } : undefined);
137
+ this.lastTelemetry = { rungs: 1 };
133
138
  for await (const chunk of stream) {
139
+ if (this.lastTelemetry.responseId === undefined
140
+ && (chunk.type === "response.completed" || chunk.type === "response.incomplete" || chunk.type === "response.created")) {
141
+ const id = chunk.response?.id;
142
+ if (typeof id === "string")
143
+ this.lastTelemetry = { rungs: 1, responseId: id };
144
+ }
134
145
  const output = this.responses.pushStreamChunk(chunk, streamState);
135
146
  for (const event of output.events)
136
147
  yield event;
@@ -160,6 +171,11 @@ export class OpenAIResponsesProvider {
160
171
  requestExtensions(extensions) {
161
172
  return this.responses.requestExtensions(extensions);
162
173
  }
174
+ /** P4-S1: transport facts of the most recent execution. Host evidence only (B7). */
175
+ lastTelemetry;
176
+ peekTransportTelemetry() {
177
+ return this.lastTelemetry;
178
+ }
163
179
  asRunState(state) {
164
180
  if (!state)
165
181
  return this.createRunState();
@@ -1,5 +1,5 @@
1
1
  import OpenAI from "openai";
2
- import type { LLMProvider, Message, ProviderDescriptor, ProviderReplay, ProviderRunState, RenderedContext, ReplayabilityAssessment, RuntimePolicy, StreamEvent, ToolSchema } from "../types.js";
2
+ import type { LLMProvider, Message, ProviderDescriptor, ProviderReplay, ProviderRunState, ProviderTransportTelemetry, RenderedContext, ReplayabilityAssessment, RuntimePolicy, StreamEvent, ToolSchema } from "../types.js";
3
3
  import { CircuitBreaker } from "./base.js";
4
4
  import { type CanonicalAdapterInput } from "./content-normalization.js";
5
5
  import { OpenAIChatAdapter } from "./openai-chat.js";
@@ -35,6 +35,9 @@ export declare class OpenAIChatProvider implements LLMProvider {
35
35
  descriptor(): ProviderDescriptor;
36
36
  bindResolvedRuntime(resolved: ResolvedOpenAIChatRuntime): void;
37
37
  assessReplayability(context: RenderedContext, extensions?: Record<string, unknown>): ReplayabilityAssessment;
38
+ /** P4-S1: transport facts of the most recent execution. Host evidence only (B7). */
39
+ private lastTelemetry;
40
+ peekTransportTelemetry(): ProviderTransportTelemetry | undefined;
38
41
  peekProviderReplay(message: Pick<Message, "content" | "toolCalls">): ProviderReplay | undefined;
39
42
  seedProviderReplay(message: Pick<Message, "content" | "toolCalls">, replay: ProviderReplay): void;
40
43
  private rememberReplay;
@@ -75,6 +75,11 @@ export class OpenAIChatProvider {
75
75
  });
76
76
  return { ok: offendingCallIds.length === 0, offendingCallIds };
77
77
  }
78
+ /** P4-S1: transport facts of the most recent execution. Host evidence only (B7). */
79
+ lastTelemetry;
80
+ peekTransportTelemetry() {
81
+ return this.lastTelemetry;
82
+ }
78
83
  peekProviderReplay(message) {
79
84
  const replay = this.replayStore.get(assistantReplayKey(message));
80
85
  if (!replay || !("reasoning_content" in replay || "reasoning_details" in replay))
@@ -139,8 +144,12 @@ export class OpenAIChatProvider {
139
144
  let lastError;
140
145
  for (let attempt = 0; attempt < this.maxRetries; attempt++) {
141
146
  try {
147
+ this.lastTelemetry = { rungs: attempt + 1 };
142
148
  const response = await this.client.chat.completions.create(plan.params);
143
149
  this.circuit.recordSuccess();
150
+ const responseId = response.id;
151
+ if (typeof responseId === "string")
152
+ this.lastTelemetry = { rungs: attempt + 1, responseId };
144
153
  const decoded = this.chat.decodeComplete(response, { input }, this.dialect);
145
154
  this.rememberReplay(decoded.message, decoded.replay);
146
155
  return decoded.message;
@@ -166,7 +175,11 @@ export class OpenAIChatProvider {
166
175
  stream: true,
167
176
  stream_options: { include_usage: true },
168
177
  }, signal ? { signal } : undefined);
178
+ this.lastTelemetry = { rungs: 1 };
169
179
  for await (const chunk of stream) {
180
+ if (this.lastTelemetry.responseId === undefined && typeof chunk.id === "string") {
181
+ this.lastTelemetry = { rungs: 1, responseId: chunk.id };
182
+ }
170
183
  const output = this.chat.pushStreamChunk(chunk, state);
171
184
  if (output.replay) {
172
185
  this.rememberReplay({
@@ -1,4 +1,5 @@
1
1
  import type { RenderedContext, ToolSchema, ProviderUsage } from "../types.js";
2
+ import type { GenerationProtocol } from "./protocol-capabilities.js";
2
3
  export interface ProviderRequestEndpoint {
3
4
  id: string;
4
5
  protocol: string;
@@ -79,6 +80,45 @@ export declare function createProviderRequestPlanForProvider(provider: {
79
80
  };
80
81
  };
81
82
  }, context: RenderedContext, tools: ToolSchema[], options?: Record<string, unknown>): ProviderRequestPlan;
83
+ /**
84
+ * P4 §1.3: the resolved route one provider execution is pinned to. Content-addressed
85
+ * (`routeId` = stable hash of every field except `capabilitiesRef`); the capability table's
86
+ * authority stays the static vocabulary in protocol-capabilities.ts — this holds a reference,
87
+ * never a copy.
88
+ */
89
+ export interface ResolvedProviderRoute {
90
+ routeId: string;
91
+ provider: string;
92
+ protocol: GenerationProtocol;
93
+ model: string;
94
+ endpoint: ProviderRequestEndpoint;
95
+ /** Adapter implementation version (the @deepstrike/sdk package version; F8). */
96
+ adapterVersion: string;
97
+ /** Capability snapshot reference: the protocol constant name (e.g. "anthropic-messages").
98
+ * A provider exposing capability overrides would append a summary here — none does today. */
99
+ capabilitiesRef: string;
100
+ }
101
+ /**
102
+ * P4-S1: assemble the run's route once at runner construction (P4 §0.2 — the provider is
103
+ * fixed for the run today; a future failover resolver re-evaluates per attempt with the same
104
+ * shape). Never throws: evidence assembly degrades to "unknown" fields rather than breaking a run.
105
+ */
106
+ export declare function resolveProviderRoute(provider: {
107
+ descriptor?(): {
108
+ provider: string;
109
+ protocol: string;
110
+ model: string;
111
+ };
112
+ requestPlanIdentity?(): {
113
+ providerId?: string;
114
+ modelId?: string;
115
+ endpoint?: {
116
+ id?: string;
117
+ protocol?: string;
118
+ baseURL?: string;
119
+ };
120
+ };
121
+ }): ResolvedProviderRoute;
82
122
  export declare function estimateProviderPromptTokens(context: RenderedContext, tools: ToolSchema[]): number;
83
123
  /** Bind a preflight count to its exact provider-visible request. Replay only reuses matching facts. */
84
124
  export declare function recordPromptMeasurement(plan: Pick<ProviderRequestPlan, "fingerprint">, measurement: Omit<RecordedPromptMeasurement, "requestFingerprint">): RecordedPromptMeasurement;
@@ -1,4 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
+ import { createRequire } from "node:module";
2
3
  const TRANSPORT_ONLY_KEYS = new Set([
3
4
  "apiKey", "api_key", "bearerToken", "bearer_token", "authorization", "credential",
4
5
  "credentials", "retry", "maxRetries", "baseDelay", "timeout", "signal", "access_token", "refresh_token", "token", "secret", "x-api-key",
@@ -44,6 +45,66 @@ export function createProviderRequestPlanForProvider(provider, context, tools, o
44
45
  options,
45
46
  });
46
47
  }
48
+ const KNOWN_GENERATION_PROTOCOLS = new Set([
49
+ "anthropic-messages",
50
+ "openai-chat",
51
+ "openai-responses",
52
+ "gemini",
53
+ "ollama-chat",
54
+ ]);
55
+ /**
56
+ * P4-S1: assemble the run's route once at runner construction (P4 §0.2 — the provider is
57
+ * fixed for the run today; a future failover resolver re-evaluates per attempt with the same
58
+ * shape). Never throws: evidence assembly degrades to "unknown" fields rather than breaking a run.
59
+ */
60
+ export function resolveProviderRoute(provider) {
61
+ try {
62
+ const descriptor = provider.descriptor?.() ?? { provider: "unknown", protocol: "unknown", model: "unknown" };
63
+ const identity = provider.requestPlanIdentity?.();
64
+ const protocolRaw = identity?.endpoint?.protocol ?? descriptor.protocol;
65
+ // Evidence records what the descriptor said, even when a foreign provider speaks a protocol
66
+ // outside the in-tree vocabulary — the field is a report, not a gate.
67
+ const protocol = protocolRaw;
68
+ const route = {
69
+ provider: identity?.providerId ?? descriptor.provider,
70
+ protocol,
71
+ model: identity?.modelId ?? descriptor.model,
72
+ endpoint: sanitizeEndpoint({
73
+ id: identity?.endpoint?.id ?? `${descriptor.provider}.${descriptor.protocol}`,
74
+ protocol: protocolRaw,
75
+ baseURL: identity?.endpoint?.baseURL ?? "",
76
+ }),
77
+ adapterVersion: adapterPackageVersion(),
78
+ capabilitiesRef: KNOWN_GENERATION_PROTOCOLS.has(protocol) ? protocol : "unknown",
79
+ };
80
+ // §1.3: content addressing covers every field EXCEPT capabilitiesRef (a reference, not content).
81
+ const { capabilitiesRef: _ref, ...addressed } = route;
82
+ return { ...route, routeId: sha256(stableJson(addressed)) };
83
+ }
84
+ catch {
85
+ const fallback = {
86
+ provider: "unknown",
87
+ protocol: "unknown",
88
+ model: "unknown",
89
+ endpoint: { id: "unknown", protocol: "unknown", baseURL: "" },
90
+ adapterVersion: "unknown",
91
+ };
92
+ return { ...fallback, capabilitiesRef: "unknown", routeId: sha256(stableJson(fallback)) };
93
+ }
94
+ }
95
+ /** The adapter's package version, read from package.json at runtime. "unknown" when unreadable —
96
+ * route assembly is evidence plumbing and must never throw (B7: evidence, not kernel input). */
97
+ function adapterPackageVersion() {
98
+ try {
99
+ // From both src/providers/ (ts) and dist/providers/ (js), ../../package.json is the SDK manifest.
100
+ const require = createRequire(import.meta.url);
101
+ const manifest = require("../../package.json");
102
+ return typeof manifest.version === "string" && manifest.version.length > 0 ? manifest.version : "unknown";
103
+ }
104
+ catch {
105
+ return "unknown";
106
+ }
107
+ }
47
108
  export function estimateProviderPromptTokens(context, tools) {
48
109
  const bytes = new TextEncoder().encode(stableJson({ context, tools })).byteLength;
49
110
  return Math.max(1, Math.ceil(bytes / 4));