@deepstrike/sdk 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/dist/agent.d.ts +10 -9
- package/dist/agent.js +64 -12
- package/dist/collaboration/contract.d.ts +55 -0
- package/dist/collaboration/contract.js +65 -0
- package/dist/collaboration/handoff.d.ts +79 -0
- package/dist/collaboration/handoff.js +98 -0
- package/dist/collaboration/harness.d.ts +55 -0
- package/dist/collaboration/harness.js +150 -0
- package/dist/collaboration/index.d.ts +10 -0
- package/dist/collaboration/index.js +9 -0
- package/dist/collaboration/modes/creator-verifier.d.ts +69 -0
- package/dist/collaboration/modes/creator-verifier.js +124 -0
- package/dist/collaboration/pool.d.ts +46 -0
- package/dist/collaboration/pool.js +80 -0
- package/dist/harness/harness.js +7 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.js +5 -0
- package/dist/kernel.d.ts +5 -2
- package/dist/memory/protocols.d.ts +8 -1
- package/dist/providers/anthropic.d.ts +3 -3
- package/dist/providers/anthropic.js +9 -9
- package/dist/providers/base.d.ts +7 -4
- package/dist/providers/base.js +41 -38
- package/dist/providers/deepseek.d.ts +2 -2
- package/dist/providers/deepseek.js +2 -2
- package/dist/providers/gemini.d.ts +3 -3
- package/dist/providers/gemini.js +8 -13
- package/dist/providers/ollama.d.ts +3 -3
- package/dist/providers/ollama.js +12 -8
- package/dist/providers/openai-chat.d.ts +2 -2
- package/dist/providers/openai-chat.js +6 -4
- package/dist/providers/openai-responses.d.ts +5 -5
- package/dist/providers/openai-responses.js +13 -19
- package/dist/providers/openai.d.ts +3 -3
- package/dist/providers/openai.js +4 -4
- package/dist/providers/qwen.d.ts +3 -3
- package/dist/providers/qwen.js +4 -4
- package/dist/types.d.ts +12 -2
- package/package.json +2 -2
package/dist/providers/base.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Message, RenderedContext } from "../types.js";
|
|
1
2
|
export declare class CircuitBreaker {
|
|
2
3
|
private readonly openAfter;
|
|
3
4
|
private readonly resetAfter;
|
|
@@ -13,9 +14,11 @@ export declare function normalizeToolCall(id: string, name: string, args: unknow
|
|
|
13
14
|
name: string;
|
|
14
15
|
arguments: string;
|
|
15
16
|
} | null;
|
|
16
|
-
import type { Message } from "../types.js";
|
|
17
17
|
export declare function toAnthropicContent(msg: Message): string | Array<Record<string, unknown>>;
|
|
18
|
+
/** Convert RenderedContext.turns to Anthropic messages array.
|
|
19
|
+
* `turns` contains only user / assistant / tool roles — no system filtering needed. */
|
|
20
|
+
export declare function toAnthropicMessages(turns: Message[], nativeReplay?: (message: Message) => Array<Record<string, unknown>> | undefined): Array<Record<string, unknown>>;
|
|
18
21
|
export declare function toOpenAIContent(msg: Message): string | Array<Record<string, unknown>>;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export declare function toOpenAIMessageParams(
|
|
22
|
+
/** Build the full OpenAI messages array from a RenderedContext.
|
|
23
|
+
* Prepends systemText as the first system message, then converts turns. */
|
|
24
|
+
export declare function toOpenAIMessageParams(context: RenderedContext): Array<Record<string, unknown>>;
|
package/dist/providers/base.js
CHANGED
|
@@ -44,6 +44,15 @@ export function normalizeToolCall(id, name, args) {
|
|
|
44
44
|
}
|
|
45
45
|
return { id: String(id ?? ""), name: n, arguments: JSON.stringify(parsed) };
|
|
46
46
|
}
|
|
47
|
+
function parseToolArguments(args) {
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(args || "{}");
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// ─── Anthropic message conversion ────────────────────────────────────────────
|
|
47
56
|
export function toAnthropicContent(msg) {
|
|
48
57
|
if (!msg.contentParts?.length)
|
|
49
58
|
return msg.content;
|
|
@@ -65,39 +74,11 @@ export function toAnthropicContent(msg) {
|
|
|
65
74
|
return { type: "text", text: "" };
|
|
66
75
|
});
|
|
67
76
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return msg.contentParts.map(p => {
|
|
72
|
-
if (p.type === "text")
|
|
73
|
-
return { type: "text", text: p.text };
|
|
74
|
-
if (p.type === "image") {
|
|
75
|
-
const url = p.data ? `data:${p.mediaType ?? "image/png"};base64,${p.data}` : p.url;
|
|
76
|
-
return { type: "image_url", image_url: { url, ...(p.detail ? { detail: p.detail } : {}) } };
|
|
77
|
-
}
|
|
78
|
-
if (p.type === "audio") {
|
|
79
|
-
return { type: "input_audio", input_audio: { data: p.data, format: p.mediaType?.split("/")[1] ?? "wav" } };
|
|
80
|
-
}
|
|
81
|
-
if (p.type === "tool_result") {
|
|
82
|
-
return { type: "text", text: p.output };
|
|
83
|
-
}
|
|
84
|
-
return { type: "text", text: "" };
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
function parseToolArguments(args) {
|
|
88
|
-
try {
|
|
89
|
-
return JSON.parse(args || "{}");
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
return {};
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
export function splitAnthropicSystem(messages) {
|
|
96
|
-
return messages.filter(m => m.role === "system").map(m => m.content).join("\n\n");
|
|
97
|
-
}
|
|
98
|
-
export function toAnthropicMessages(messages, nativeReplay) {
|
|
77
|
+
/** Convert RenderedContext.turns to Anthropic messages array.
|
|
78
|
+
* `turns` contains only user / assistant / tool roles — no system filtering needed. */
|
|
79
|
+
export function toAnthropicMessages(turns, nativeReplay) {
|
|
99
80
|
const result = [];
|
|
100
|
-
for (const msg of
|
|
81
|
+
for (const msg of turns) {
|
|
101
82
|
if (msg.role === "tool") {
|
|
102
83
|
const parts = (msg.contentParts ?? [])
|
|
103
84
|
.filter((p) => p.type === "tool_result")
|
|
@@ -124,16 +105,38 @@ export function toAnthropicMessages(messages, nativeReplay) {
|
|
|
124
105
|
result.push({ role: "assistant", content: blocks });
|
|
125
106
|
continue;
|
|
126
107
|
}
|
|
127
|
-
result.push({
|
|
128
|
-
role: msg.role,
|
|
129
|
-
content: toAnthropicContent(msg),
|
|
130
|
-
});
|
|
108
|
+
result.push({ role: msg.role, content: toAnthropicContent(msg) });
|
|
131
109
|
}
|
|
132
110
|
return result;
|
|
133
111
|
}
|
|
134
|
-
|
|
112
|
+
// ─── OpenAI-compatible message conversion ────────────────────────────────────
|
|
113
|
+
export function toOpenAIContent(msg) {
|
|
114
|
+
if (!msg.contentParts?.length)
|
|
115
|
+
return msg.content;
|
|
116
|
+
return msg.contentParts.map(p => {
|
|
117
|
+
if (p.type === "text")
|
|
118
|
+
return { type: "text", text: p.text };
|
|
119
|
+
if (p.type === "image") {
|
|
120
|
+
const url = p.data ? `data:${p.mediaType ?? "image/png"};base64,${p.data}` : p.url;
|
|
121
|
+
return { type: "image_url", image_url: { url, ...(p.detail ? { detail: p.detail } : {}) } };
|
|
122
|
+
}
|
|
123
|
+
if (p.type === "audio") {
|
|
124
|
+
return { type: "input_audio", input_audio: { data: p.data, format: p.mediaType?.split("/")[1] ?? "wav" } };
|
|
125
|
+
}
|
|
126
|
+
if (p.type === "tool_result") {
|
|
127
|
+
return { type: "text", text: p.output };
|
|
128
|
+
}
|
|
129
|
+
return { type: "text", text: "" };
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/** Build the full OpenAI messages array from a RenderedContext.
|
|
133
|
+
* Prepends systemText as the first system message, then converts turns. */
|
|
134
|
+
export function toOpenAIMessageParams(context) {
|
|
135
135
|
const result = [];
|
|
136
|
-
|
|
136
|
+
if (context.systemText) {
|
|
137
|
+
result.push({ role: "system", content: context.systemText });
|
|
138
|
+
}
|
|
139
|
+
for (const msg of context.turns) {
|
|
137
140
|
if (msg.role === "tool") {
|
|
138
141
|
const parts = (msg.contentParts ?? [])
|
|
139
142
|
.filter((p) => p.type === "tool_result");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RenderedContext, ToolSchema, StreamEvent } from "../types.js";
|
|
2
2
|
import { OpenAIChatProvider } from "./openai.js";
|
|
3
3
|
export declare class DeepSeekProvider extends OpenAIChatProvider {
|
|
4
4
|
constructor(apiKey: string, model?: "deepseek-v4-flash" | "deepseek-v4-pro", retry?: {
|
|
5
5
|
maxRetries: number;
|
|
6
6
|
baseDelay: number;
|
|
7
7
|
}, baseURL?: string);
|
|
8
|
-
stream(
|
|
8
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
9
9
|
}
|
|
@@ -5,11 +5,11 @@ export class DeepSeekProvider extends OpenAIChatProvider {
|
|
|
5
5
|
constructor(apiKey, model = "deepseek-v4-flash", retry, baseURL = DEEPSEEK_BASE) {
|
|
6
6
|
super(apiKey, model, retry, baseURL);
|
|
7
7
|
}
|
|
8
|
-
async *stream(
|
|
8
|
+
async *stream(context, tools, extensions) {
|
|
9
9
|
const exposeReasoning = extensions?.exposeReasoning ?? false;
|
|
10
10
|
const thinking = extensions?.thinking === false ? "disabled" : "enabled";
|
|
11
11
|
const reasoningEffort = extensions?.reasoningEffort === "max" ? "max" : "high";
|
|
12
|
-
const msgs = this.chat.buildMessages(
|
|
12
|
+
const msgs = this.chat.buildMessages(context);
|
|
13
13
|
const toolCallBufs = {};
|
|
14
14
|
let reasoningContent = "";
|
|
15
15
|
let finalText = "";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Message, ToolSchema, StreamEvent, LLMProvider } from "../types.js";
|
|
1
|
+
import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider } from "../types.js";
|
|
2
2
|
export declare class GeminiProvider implements LLMProvider {
|
|
3
3
|
private readonly model;
|
|
4
4
|
private genAI;
|
|
@@ -9,6 +9,6 @@ export declare class GeminiProvider implements LLMProvider {
|
|
|
9
9
|
maxRetries: number;
|
|
10
10
|
baseDelay: number;
|
|
11
11
|
}, baseURL?: string);
|
|
12
|
-
complete(
|
|
13
|
-
stream(
|
|
12
|
+
complete(context: RenderedContext, tools: ToolSchema[]): Promise<Message>;
|
|
13
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
14
14
|
}
|
package/dist/providers/gemini.js
CHANGED
|
@@ -3,11 +3,9 @@ import { withServerRuntimeGuard } from "../runtime/server.js";
|
|
|
3
3
|
import { CircuitBreaker, normalizeToolCall } from "./base.js";
|
|
4
4
|
import { endpointProfiles } from "./profiles.js";
|
|
5
5
|
const GEMINI_BASE = endpointProfiles["gemini.google"].baseURL;
|
|
6
|
-
function buildContents(
|
|
6
|
+
function buildContents(turns) {
|
|
7
7
|
const contents = [];
|
|
8
|
-
for (const msg of
|
|
9
|
-
if (msg.role === "system")
|
|
10
|
-
continue;
|
|
8
|
+
for (const msg of turns) {
|
|
11
9
|
if (msg.role === "tool") {
|
|
12
10
|
const parts = (msg.contentParts ?? [])
|
|
13
11
|
.filter(p => p.type === "tool_result")
|
|
@@ -50,9 +48,6 @@ function buildTools(tools) {
|
|
|
50
48
|
})),
|
|
51
49
|
}];
|
|
52
50
|
}
|
|
53
|
-
function systemInstruction(messages) {
|
|
54
|
-
return messages.find(m => m.role === "system")?.content;
|
|
55
|
-
}
|
|
56
51
|
export class GeminiProvider {
|
|
57
52
|
model;
|
|
58
53
|
genAI;
|
|
@@ -66,11 +61,11 @@ export class GeminiProvider {
|
|
|
66
61
|
this.maxRetries = retry.maxRetries;
|
|
67
62
|
this.baseDelay = retry.baseDelay;
|
|
68
63
|
}
|
|
69
|
-
async complete(
|
|
64
|
+
async complete(context, tools) {
|
|
70
65
|
if (this.circuit.isOpen())
|
|
71
66
|
throw new Error("Circuit breaker open");
|
|
72
|
-
const system =
|
|
73
|
-
const contents = buildContents(
|
|
67
|
+
const system = context.systemText || undefined;
|
|
68
|
+
const contents = buildContents(context.turns);
|
|
74
69
|
const geminiTools = buildTools(tools);
|
|
75
70
|
let lastErr;
|
|
76
71
|
for (let i = 0; i < this.maxRetries; i++) {
|
|
@@ -111,9 +106,9 @@ export class GeminiProvider {
|
|
|
111
106
|
}
|
|
112
107
|
throw lastErr;
|
|
113
108
|
}
|
|
114
|
-
async *stream(
|
|
115
|
-
const system =
|
|
116
|
-
const contents = buildContents(
|
|
109
|
+
async *stream(context, tools, extensions) {
|
|
110
|
+
const system = context.systemText || undefined;
|
|
111
|
+
const contents = buildContents(context.turns);
|
|
117
112
|
const geminiTools = buildTools(tools);
|
|
118
113
|
const m = this.genAI.getGenerativeModel({
|
|
119
114
|
model: this.model,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { Message, ToolSchema, StreamEvent, LLMProvider } from "../types.js";
|
|
1
|
+
import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider } from "../types.js";
|
|
2
2
|
export declare class OllamaProvider implements LLMProvider {
|
|
3
3
|
private readonly model;
|
|
4
4
|
private readonly baseUrl;
|
|
5
5
|
constructor(model?: string, baseUrl?: string);
|
|
6
6
|
private toOllamaMessages;
|
|
7
|
-
complete(
|
|
8
|
-
stream(
|
|
7
|
+
complete(context: RenderedContext, tools: ToolSchema[]): Promise<Message>;
|
|
8
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
9
9
|
}
|
package/dist/providers/ollama.js
CHANGED
|
@@ -6,8 +6,11 @@ export class OllamaProvider {
|
|
|
6
6
|
this.model = model;
|
|
7
7
|
this.baseUrl = baseUrl;
|
|
8
8
|
}
|
|
9
|
-
toOllamaMessages(
|
|
10
|
-
|
|
9
|
+
toOllamaMessages(context) {
|
|
10
|
+
const result = [];
|
|
11
|
+
if (context.systemText)
|
|
12
|
+
result.push({ role: "system", content: context.systemText });
|
|
13
|
+
for (const m of context.turns) {
|
|
11
14
|
const images = [];
|
|
12
15
|
if (m.contentParts?.length) {
|
|
13
16
|
for (const p of m.contentParts) {
|
|
@@ -15,25 +18,26 @@ export class OllamaProvider {
|
|
|
15
18
|
images.push(p.data);
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
|
-
|
|
19
|
-
}
|
|
21
|
+
result.push({ role: m.role, content: m.content, ...(images.length ? { images } : {}) });
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
20
24
|
}
|
|
21
|
-
async complete(
|
|
25
|
+
async complete(context, tools) {
|
|
22
26
|
const resp = await fetch(`${this.baseUrl}/api/chat`, {
|
|
23
27
|
method: "POST",
|
|
24
28
|
headers: { "Content-Type": "application/json" },
|
|
25
|
-
body: JSON.stringify({ model: this.model, messages: this.toOllamaMessages(
|
|
29
|
+
body: JSON.stringify({ model: this.model, messages: this.toOllamaMessages(context), stream: false }),
|
|
26
30
|
});
|
|
27
31
|
if (!resp.ok)
|
|
28
32
|
throw new Error(`Ollama error: ${resp.status}`);
|
|
29
33
|
const data = await resp.json();
|
|
30
34
|
return { role: "assistant", content: data.message.content };
|
|
31
35
|
}
|
|
32
|
-
async *stream(
|
|
36
|
+
async *stream(context, tools, extensions) {
|
|
33
37
|
const resp = await fetch(`${this.baseUrl}/api/chat`, {
|
|
34
38
|
method: "POST",
|
|
35
39
|
headers: { "Content-Type": "application/json" },
|
|
36
|
-
body: JSON.stringify({ model: this.model, messages: this.toOllamaMessages(
|
|
40
|
+
body: JSON.stringify({ model: this.model, messages: this.toOllamaMessages(context), stream: true }),
|
|
37
41
|
});
|
|
38
42
|
if (!resp.ok)
|
|
39
43
|
throw new Error(`Ollama error: ${resp.status}`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type OpenAI from "openai";
|
|
2
|
-
import type { Message, ToolSchema } from "../types.js";
|
|
2
|
+
import type { Message, RenderedContext, ToolSchema } from "../types.js";
|
|
3
3
|
export declare class OpenAIChatAdapter {
|
|
4
4
|
private replayFields;
|
|
5
5
|
buildTools(tools: ToolSchema[]): {
|
|
@@ -10,7 +10,7 @@ export declare class OpenAIChatAdapter {
|
|
|
10
10
|
parameters: any;
|
|
11
11
|
};
|
|
12
12
|
}[];
|
|
13
|
-
buildMessages(
|
|
13
|
+
buildMessages(context: RenderedContext): OpenAI.ChatCompletionMessageParam[];
|
|
14
14
|
normalizeToolCalls(toolCalls?: Array<{
|
|
15
15
|
id: string;
|
|
16
16
|
function: {
|
|
@@ -7,10 +7,12 @@ export class OpenAIChatAdapter {
|
|
|
7
7
|
function: { name: t.name, description: t.description, parameters: JSON.parse(t.parameters) },
|
|
8
8
|
}));
|
|
9
9
|
}
|
|
10
|
-
buildMessages(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
buildMessages(context) {
|
|
11
|
+
// toOpenAIMessageParams prepends systemText as messages[0], then turns.
|
|
12
|
+
const serialized = toOpenAIMessageParams(context);
|
|
13
|
+
// Cursor starts at 1 to skip the system message injected by toOpenAIMessageParams.
|
|
14
|
+
let cursor = context.systemText ? 1 : 0;
|
|
15
|
+
for (const source of context.turns) {
|
|
14
16
|
if (source.role === "tool") {
|
|
15
17
|
cursor += (source.contentParts ?? []).filter(p => p.type === "tool_result").length;
|
|
16
18
|
continue;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import OpenAI from "openai";
|
|
2
|
-
import type { Message, ProviderRunState, StreamEvent, ToolSchema, LLMProvider } from "../types.js";
|
|
2
|
+
import type { Message, ProviderRunState, RenderedContext, StreamEvent, ToolSchema, LLMProvider } from "../types.js";
|
|
3
3
|
import { CircuitBreaker } from "./base.js";
|
|
4
4
|
export interface OpenAIResponsesRunState extends ProviderRunState {
|
|
5
5
|
previousResponseId?: string;
|
|
@@ -12,8 +12,8 @@ export declare class OpenAIResponsesAdapter {
|
|
|
12
12
|
description: string;
|
|
13
13
|
parameters: any;
|
|
14
14
|
}[];
|
|
15
|
-
buildInstructions(
|
|
16
|
-
buildInput(
|
|
15
|
+
buildInstructions(context: RenderedContext): string | undefined;
|
|
16
|
+
buildInput(context: RenderedContext, state?: OpenAIResponsesRunState): Array<Record<string, unknown>>;
|
|
17
17
|
decodeOutput(output: Array<Record<string, unknown>>): {
|
|
18
18
|
content: string;
|
|
19
19
|
toolCalls: Array<{
|
|
@@ -36,7 +36,7 @@ export declare class OpenAIResponsesProvider implements LLMProvider {
|
|
|
36
36
|
baseDelay: number;
|
|
37
37
|
}, baseURL?: string);
|
|
38
38
|
createRunState(): OpenAIResponsesRunState;
|
|
39
|
-
complete(
|
|
40
|
-
stream(
|
|
39
|
+
complete(context: RenderedContext, tools: ToolSchema[]): Promise<Message>;
|
|
40
|
+
stream(context: RenderedContext, tools: ToolSchema[], _extensions?: Record<string, unknown>, state?: ProviderRunState): AsyncIterable<StreamEvent>;
|
|
41
41
|
private asRunState;
|
|
42
42
|
}
|
|
@@ -11,22 +11,16 @@ export class OpenAIResponsesAdapter {
|
|
|
11
11
|
parameters: JSON.parse(t.parameters),
|
|
12
12
|
}));
|
|
13
13
|
}
|
|
14
|
-
buildInstructions(
|
|
15
|
-
|
|
16
|
-
.filter(message => message.role === "system")
|
|
17
|
-
.map(message => message.content)
|
|
18
|
-
.filter(Boolean);
|
|
19
|
-
return instructions.length ? instructions.join("\n\n") : undefined;
|
|
14
|
+
buildInstructions(context) {
|
|
15
|
+
return context.systemText || undefined;
|
|
20
16
|
}
|
|
21
|
-
buildInput(
|
|
17
|
+
buildInput(context, state) {
|
|
22
18
|
const input = [];
|
|
19
|
+
const turns = context.turns;
|
|
23
20
|
const uncoveredMessages = state?.previousResponseId
|
|
24
|
-
?
|
|
25
|
-
:
|
|
21
|
+
? turns.slice(state.coveredMessageCount)
|
|
22
|
+
: turns;
|
|
26
23
|
for (const message of uncoveredMessages) {
|
|
27
|
-
if (message.role === "system") {
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
24
|
if (message.role === "assistant" && message.toolCalls?.length) {
|
|
31
25
|
if (message.content || message.contentParts?.length) {
|
|
32
26
|
input.push({
|
|
@@ -122,16 +116,16 @@ export class OpenAIResponsesProvider {
|
|
|
122
116
|
createRunState() {
|
|
123
117
|
return { coveredMessageCount: 0 };
|
|
124
118
|
}
|
|
125
|
-
async complete(
|
|
119
|
+
async complete(context, tools) {
|
|
126
120
|
if (this.circuit.isOpen())
|
|
127
121
|
throw new Error("Circuit breaker open");
|
|
128
122
|
let lastErr;
|
|
129
123
|
for (let i = 0; i < this.maxRetries; i++) {
|
|
130
124
|
try {
|
|
131
|
-
const instructions = this.responses.buildInstructions(
|
|
125
|
+
const instructions = this.responses.buildInstructions(context);
|
|
132
126
|
const resp = await this.client.responses.create({
|
|
133
127
|
model: this.model,
|
|
134
|
-
input: this.responses.buildInput(
|
|
128
|
+
input: this.responses.buildInput(context),
|
|
135
129
|
...(instructions ? { instructions } : {}),
|
|
136
130
|
...(tools.length ? { tools: this.responses.buildTools(tools) } : {}),
|
|
137
131
|
});
|
|
@@ -153,13 +147,13 @@ export class OpenAIResponsesProvider {
|
|
|
153
147
|
}
|
|
154
148
|
throw lastErr;
|
|
155
149
|
}
|
|
156
|
-
async *stream(
|
|
150
|
+
async *stream(context, tools, _extensions, state) {
|
|
157
151
|
const runState = this.asRunState(state);
|
|
158
152
|
const functionCalls = new Map();
|
|
159
|
-
const instructions = this.responses.buildInstructions(
|
|
153
|
+
const instructions = this.responses.buildInstructions(context);
|
|
160
154
|
const stream = await this.client.responses.create({
|
|
161
155
|
model: this.model,
|
|
162
|
-
input: this.responses.buildInput(
|
|
156
|
+
input: this.responses.buildInput(context, runState),
|
|
163
157
|
...(instructions ? { instructions } : {}),
|
|
164
158
|
...(runState.previousResponseId ? { previous_response_id: runState.previousResponseId } : {}),
|
|
165
159
|
...(tools.length ? { tools: this.responses.buildTools(tools) } : {}),
|
|
@@ -203,7 +197,7 @@ export class OpenAIResponsesProvider {
|
|
|
203
197
|
}
|
|
204
198
|
else if (evt.type === "response.completed") {
|
|
205
199
|
runState.previousResponseId = evt.response.id;
|
|
206
|
-
runState.coveredMessageCount =
|
|
200
|
+
runState.coveredMessageCount = context.turns.length + 1;
|
|
207
201
|
if (evt.response.usage?.total_tokens) {
|
|
208
202
|
yield { type: "usage", totalTokens: evt.response.usage.total_tokens };
|
|
209
203
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import OpenAI from "openai";
|
|
2
|
-
import type { Message, ToolSchema, StreamEvent, LLMProvider } from "../types.js";
|
|
2
|
+
import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider } from "../types.js";
|
|
3
3
|
import { CircuitBreaker } from "./base.js";
|
|
4
4
|
import { OpenAIChatAdapter } from "./openai-chat.js";
|
|
5
5
|
export declare class OpenAIChatProvider implements LLMProvider {
|
|
@@ -13,7 +13,7 @@ export declare class OpenAIChatProvider implements LLMProvider {
|
|
|
13
13
|
maxRetries: number;
|
|
14
14
|
baseDelay: number;
|
|
15
15
|
}, baseURL?: string);
|
|
16
|
-
complete(
|
|
17
|
-
stream(
|
|
16
|
+
complete(context: RenderedContext, tools: ToolSchema[]): Promise<Message>;
|
|
17
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
18
18
|
}
|
|
19
19
|
export { OpenAIChatProvider as OpenAIProvider };
|
package/dist/providers/openai.js
CHANGED
|
@@ -16,10 +16,10 @@ export class OpenAIChatProvider {
|
|
|
16
16
|
this.maxRetries = retry.maxRetries;
|
|
17
17
|
this.baseDelay = retry.baseDelay;
|
|
18
18
|
}
|
|
19
|
-
async complete(
|
|
19
|
+
async complete(context, tools) {
|
|
20
20
|
if (this.circuit.isOpen())
|
|
21
21
|
throw new Error("Circuit breaker open");
|
|
22
|
-
const msgs = this.chat.buildMessages(
|
|
22
|
+
const msgs = this.chat.buildMessages(context);
|
|
23
23
|
let lastErr;
|
|
24
24
|
for (let i = 0; i < this.maxRetries; i++) {
|
|
25
25
|
try {
|
|
@@ -42,8 +42,8 @@ export class OpenAIChatProvider {
|
|
|
42
42
|
}
|
|
43
43
|
throw lastErr;
|
|
44
44
|
}
|
|
45
|
-
async *stream(
|
|
46
|
-
const msgs = this.chat.buildMessages(
|
|
45
|
+
async *stream(context, tools, extensions) {
|
|
46
|
+
const msgs = this.chat.buildMessages(context);
|
|
47
47
|
const toolCallBufs = {};
|
|
48
48
|
const stream = await this.client.chat.completions.create({
|
|
49
49
|
model: this.model,
|
package/dist/providers/qwen.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import OpenAI from "openai";
|
|
2
|
-
import type { LLMProvider, Message, StreamEvent, ToolSchema } from "../types.js";
|
|
2
|
+
import type { LLMProvider, Message, RenderedContext, StreamEvent, ToolSchema } from "../types.js";
|
|
3
3
|
import { CircuitBreaker } from "./base.js";
|
|
4
4
|
import { OpenAIChatAdapter } from "./openai-chat.js";
|
|
5
5
|
export declare class QwenProvider implements LLMProvider {
|
|
@@ -13,6 +13,6 @@ export declare class QwenProvider implements LLMProvider {
|
|
|
13
13
|
maxRetries: number;
|
|
14
14
|
baseDelay: number;
|
|
15
15
|
}, baseURL?: string);
|
|
16
|
-
complete(
|
|
17
|
-
stream(
|
|
16
|
+
complete(context: RenderedContext, tools: ToolSchema[]): Promise<Message>;
|
|
17
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
18
18
|
}
|
package/dist/providers/qwen.js
CHANGED
|
@@ -18,10 +18,10 @@ export class QwenProvider {
|
|
|
18
18
|
this.maxRetries = retry.maxRetries;
|
|
19
19
|
this.baseDelay = retry.baseDelay;
|
|
20
20
|
}
|
|
21
|
-
async complete(
|
|
21
|
+
async complete(context, tools) {
|
|
22
22
|
if (this.circuit.isOpen())
|
|
23
23
|
throw new Error("Circuit breaker open");
|
|
24
|
-
const msgs = this.chat.buildMessages(
|
|
24
|
+
const msgs = this.chat.buildMessages(context);
|
|
25
25
|
let lastErr;
|
|
26
26
|
for (let i = 0; i < this.maxRetries; i++) {
|
|
27
27
|
try {
|
|
@@ -44,10 +44,10 @@ export class QwenProvider {
|
|
|
44
44
|
}
|
|
45
45
|
throw lastErr;
|
|
46
46
|
}
|
|
47
|
-
async *stream(
|
|
47
|
+
async *stream(context, tools, extensions) {
|
|
48
48
|
const enableThinking = Boolean(extensions?.enableThinking ?? extensions?.enable_thinking);
|
|
49
49
|
const thinkingBudget = extensions?.thinkingBudget ?? extensions?.thinking_budget;
|
|
50
|
-
const msgs = this.chat.buildMessages(
|
|
50
|
+
const msgs = this.chat.buildMessages(context);
|
|
51
51
|
const toolCallBufs = {};
|
|
52
52
|
const stream = await this.client.chat.completions.create({
|
|
53
53
|
model: this.model,
|
package/dist/types.d.ts
CHANGED
|
@@ -117,8 +117,18 @@ export interface RetryConfig {
|
|
|
117
117
|
* Responses `previous_response_id` without leaking those semantics into the kernel.
|
|
118
118
|
*/
|
|
119
119
|
export type ProviderRunState = Record<string, unknown>;
|
|
120
|
+
/** Structured render output produced by the kernel for each LLM call. */
|
|
121
|
+
export interface RenderedContext {
|
|
122
|
+
/** Combined system text: system partition + dashboard (when non-empty).
|
|
123
|
+
* Anthropic → `system` param · OpenAI → messages[0] system role ·
|
|
124
|
+
* Gemini → `systemInstruction`. */
|
|
125
|
+
systemText: string;
|
|
126
|
+
/** Strictly alternating user / assistant / tool turns.
|
|
127
|
+
* Working-partition signals are already folded into the first user turn. */
|
|
128
|
+
turns: Message[];
|
|
129
|
+
}
|
|
120
130
|
export interface LLMProvider {
|
|
121
131
|
createRunState?(): ProviderRunState;
|
|
122
|
-
complete(
|
|
123
|
-
stream(
|
|
132
|
+
complete(context: RenderedContext, tools: ToolSchema[]): Promise<Message>;
|
|
133
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState): AsyncIterable<StreamEvent>;
|
|
124
134
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstrike/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "DeepStrike Node.js SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
19
|
-
"@deepstrike/core": "0.1.
|
|
19
|
+
"@deepstrike/core": "0.1.12",
|
|
20
20
|
"@google/generative-ai": "^0.24.1",
|
|
21
21
|
"openai": "^4.77.0"
|
|
22
22
|
},
|