@deepstrike/sdk 0.2.30 → 0.2.31
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/dist/harness/harness.d.ts +3 -2
- package/dist/harness/harness.js +15 -35
- package/dist/harness/judge.d.ts +42 -0
- package/dist/harness/judge.js +58 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +4 -0
- package/dist/kernel.d.ts +7 -1
- package/dist/providers/anthropic-compatible.d.ts +23 -0
- package/dist/providers/anthropic-compatible.js +29 -0
- package/dist/providers/catalog.js +5 -53
- package/dist/providers/deepseek.d.ts +28 -8
- package/dist/providers/deepseek.js +38 -157
- package/dist/providers/factories.js +10 -22
- package/dist/providers/glm.d.ts +5 -4
- package/dist/providers/glm.js +8 -23
- package/dist/providers/kimi.d.ts +5 -4
- package/dist/providers/kimi.js +8 -22
- package/dist/providers/minimax.d.ts +26 -12
- package/dist/providers/minimax.js +32 -158
- package/dist/providers/openai.d.ts +43 -0
- package/dist/providers/openai.js +128 -64
- package/dist/providers/qwen.d.ts +19 -19
- package/dist/providers/qwen.js +37 -176
- package/dist/providers/registry.d.ts +18 -0
- package/dist/providers/registry.js +35 -0
- package/dist/providers/vendor-profiles.d.ts +54 -0
- package/dist/providers/vendor-profiles.js +62 -0
- package/dist/runtime/event-stream.d.ts +44 -0
- package/dist/runtime/event-stream.js +39 -0
- package/dist/runtime/reactive-session.d.ts +125 -0
- package/dist/runtime/reactive-session.js +127 -0
- package/dist/runtime/run-group.d.ts +74 -0
- package/dist/runtime/run-group.js +72 -0
- package/dist/runtime/runner.d.ts +9 -0
- package/dist/runtime/runner.js +56 -7
- package/dist/runtime/session-log.d.ts +8 -0
- package/dist/runtime/turn-policy.d.ts +33 -0
- package/dist/runtime/turn-policy.js +58 -0
- package/dist/signals/gateway.d.ts +7 -2
- package/dist/signals/gateway.js +13 -3
- package/dist/signals/types.d.ts +10 -1
- package/package.json +2 -2
|
@@ -1,43 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { KimiProvider, KimiAnthropicProvider } from "./kimi.js";
|
|
3
|
-
import { QwenProvider, QwenAnthropicProvider } from "./qwen.js";
|
|
4
|
-
import { GLMProvider, GLMAnthropicProvider } from "./glm.js";
|
|
5
|
-
import { MiniMaxOpenAIProvider, MiniMaxAnthropicProvider } from "./minimax.js";
|
|
6
|
-
import { GeminiProvider } from "./gemini.js";
|
|
1
|
+
import { PROVIDER_REGISTRY } from "./registry.js";
|
|
7
2
|
import { OllamaProvider } from "./ollama.js";
|
|
3
|
+
function build(providerId, protocol, o) {
|
|
4
|
+
return PROVIDER_REGISTRY[`${providerId}:${protocol}`](o.apiKey, o.model, o.retry, o.baseURL);
|
|
5
|
+
}
|
|
8
6
|
/** DeepSeek. Defaults to the OpenAI-compatible wire (richer reasoning-replay handling). */
|
|
9
7
|
export function deepseek(o) {
|
|
10
|
-
return o.protocol === "anthropic"
|
|
11
|
-
? new DeepSeekAnthropicProvider(o.apiKey, o.model, o.retry, o.baseURL)
|
|
12
|
-
: new DeepSeekProvider(o.apiKey, o.model, o.retry, o.baseURL);
|
|
8
|
+
return build("deepseek", o.protocol === "anthropic" ? "anthropic-messages" : "openai-chat", o);
|
|
13
9
|
}
|
|
14
10
|
/** Moonshot Kimi. Defaults to the OpenAI-compatible wire. */
|
|
15
11
|
export function kimi(o) {
|
|
16
|
-
return o.protocol === "anthropic"
|
|
17
|
-
? new KimiAnthropicProvider(o.apiKey, o.model, o.retry, o.baseURL)
|
|
18
|
-
: new KimiProvider(o.apiKey, o.model, o.retry, o.baseURL);
|
|
12
|
+
return build("kimi", o.protocol === "anthropic" ? "anthropic-messages" : "openai-chat", o);
|
|
19
13
|
}
|
|
20
14
|
/** Alibaba Qwen / DashScope. Defaults to the OpenAI-compatible (DashScope) wire. */
|
|
21
15
|
export function qwen(o) {
|
|
22
|
-
return o.protocol === "anthropic"
|
|
23
|
-
? new QwenAnthropicProvider(o.apiKey, o.model, o.retry, o.baseURL)
|
|
24
|
-
: new QwenProvider(o.apiKey, o.model, o.retry, o.baseURL);
|
|
16
|
+
return build("qwen", o.protocol === "anthropic" ? "anthropic-messages" : "openai-chat", o);
|
|
25
17
|
}
|
|
26
18
|
/** Zhipu GLM. Defaults to the OpenAI-compatible wire. */
|
|
27
19
|
export function glm(o) {
|
|
28
|
-
return o.protocol === "anthropic"
|
|
29
|
-
? new GLMAnthropicProvider(o.apiKey, o.model, o.retry, o.baseURL)
|
|
30
|
-
: new GLMProvider(o.apiKey, o.model, o.retry, o.baseURL);
|
|
20
|
+
return build("glm", o.protocol === "anthropic" ? "anthropic-messages" : "openai-chat", o);
|
|
31
21
|
}
|
|
32
22
|
/** MiniMax. Defaults to the Anthropic-compatible wire (the primary M2.x path). */
|
|
33
23
|
export function minimax(o) {
|
|
34
|
-
return o.protocol === "openai"
|
|
35
|
-
? new MiniMaxOpenAIProvider(o.apiKey, o.model, o.retry, o.baseURL)
|
|
36
|
-
: new MiniMaxAnthropicProvider(o.apiKey, o.model, o.retry, o.baseURL);
|
|
24
|
+
return build("minimax", o.protocol === "openai" ? "openai-chat" : "anthropic-messages", o);
|
|
37
25
|
}
|
|
38
26
|
/** Google Gemini (single wire). */
|
|
39
27
|
export function gemini(o) {
|
|
40
|
-
return
|
|
28
|
+
return PROVIDER_REGISTRY["gemini:gemini"](o.apiKey, o.model, o.retry, o.baseURL);
|
|
41
29
|
}
|
|
42
30
|
/** Local Ollama (single wire, no API key). */
|
|
43
31
|
export function ollama(o = {}) {
|
package/dist/providers/glm.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import type { ProviderDescriptor, RuntimePolicy } from "../types.js";
|
|
2
|
-
import { AnthropicProvider } from "./anthropic.js";
|
|
3
2
|
import { OpenAIChatProvider } from "./openai.js";
|
|
3
|
+
import { AnthropicCompatibleProvider } from "./anthropic-compatible.js";
|
|
4
4
|
/**
|
|
5
5
|
* GLM over its Anthropic-compatible endpoint.
|
|
6
|
+
* @deprecated Prefer `glm({ protocol: "anthropic" })`. Behavior is now fully
|
|
7
|
+
* data-driven via `anthropicVendorProfiles.glm`; this thin shim is kept for
|
|
8
|
+
* backward compatibility and `instanceof` checks.
|
|
6
9
|
*/
|
|
7
|
-
export declare class GLMAnthropicProvider extends
|
|
10
|
+
export declare class GLMAnthropicProvider extends AnthropicCompatibleProvider {
|
|
8
11
|
constructor(apiKey: string, model?: string, retry?: {
|
|
9
12
|
maxRetries: number;
|
|
10
13
|
baseDelay: number;
|
|
11
14
|
}, baseURL?: string);
|
|
12
|
-
protected providerName(): string;
|
|
13
|
-
runtimePolicy(): RuntimePolicy;
|
|
14
15
|
}
|
|
15
16
|
export declare class GLMProvider extends OpenAIChatProvider {
|
|
16
17
|
constructor(apiKey: string, model?: string, retry?: {
|
package/dist/providers/glm.js
CHANGED
|
@@ -1,31 +1,16 @@
|
|
|
1
|
-
import { AnthropicProvider } from "./anthropic.js";
|
|
2
1
|
import { OpenAIChatProvider } from "./openai.js";
|
|
2
|
+
import { AnthropicCompatibleProvider } from "./anthropic-compatible.js";
|
|
3
3
|
import { endpointProfiles } from "./profiles.js";
|
|
4
|
-
|
|
5
|
-
"glm-5.1": { maxTurns: 50 },
|
|
6
|
-
"glm/glm-5.1": { maxTurns: 50 },
|
|
7
|
-
"glm-4-plus": { maxTurns: 35 },
|
|
8
|
-
"glm/glm-4-plus": { maxTurns: 35 },
|
|
9
|
-
"glm-4-flash": { maxTurns: 15 },
|
|
10
|
-
"glm/glm-4-flash": { maxTurns: 15 },
|
|
11
|
-
"glm-4-air": { maxTurns: 20 },
|
|
12
|
-
"glm/glm-4-air": { maxTurns: 20 },
|
|
13
|
-
};
|
|
4
|
+
import { GLM_POLICIES, anthropicVendorProfiles } from "./vendor-profiles.js";
|
|
14
5
|
/**
|
|
15
6
|
* GLM over its Anthropic-compatible endpoint.
|
|
7
|
+
* @deprecated Prefer `glm({ protocol: "anthropic" })`. Behavior is now fully
|
|
8
|
+
* data-driven via `anthropicVendorProfiles.glm`; this thin shim is kept for
|
|
9
|
+
* backward compatibility and `instanceof` checks.
|
|
16
10
|
*/
|
|
17
|
-
export class GLMAnthropicProvider extends
|
|
18
|
-
constructor(apiKey, model
|
|
19
|
-
super(apiKey, model, retry,
|
|
20
|
-
baseURL,
|
|
21
|
-
authMode: "api-key",
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
providerName() {
|
|
25
|
-
return "glm";
|
|
26
|
-
}
|
|
27
|
-
runtimePolicy() {
|
|
28
|
-
return GLM_POLICIES[this.model] ?? {};
|
|
11
|
+
export class GLMAnthropicProvider extends AnthropicCompatibleProvider {
|
|
12
|
+
constructor(apiKey, model, retry, baseURL) {
|
|
13
|
+
super(anthropicVendorProfiles.glm, apiKey, model, retry, baseURL);
|
|
29
14
|
}
|
|
30
15
|
}
|
|
31
16
|
export class GLMProvider extends OpenAIChatProvider {
|
package/dist/providers/kimi.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import type { ProviderDescriptor, RuntimePolicy } from "../types.js";
|
|
2
|
-
import { AnthropicProvider } from "./anthropic.js";
|
|
3
2
|
import { OpenAIChatProvider } from "./openai.js";
|
|
3
|
+
import { AnthropicCompatibleProvider } from "./anthropic-compatible.js";
|
|
4
4
|
/**
|
|
5
5
|
* Kimi over its Anthropic-compatible endpoint.
|
|
6
|
+
* @deprecated Prefer `kimi({ protocol: "anthropic" })`. Behavior is now fully
|
|
7
|
+
* data-driven via `anthropicVendorProfiles.kimi`; this thin shim is kept for
|
|
8
|
+
* backward compatibility and `instanceof` checks.
|
|
6
9
|
*/
|
|
7
|
-
export declare class KimiAnthropicProvider extends
|
|
10
|
+
export declare class KimiAnthropicProvider extends AnthropicCompatibleProvider {
|
|
8
11
|
constructor(apiKey: string, model?: string, retry?: {
|
|
9
12
|
maxRetries: number;
|
|
10
13
|
baseDelay: number;
|
|
11
14
|
}, baseURL?: string);
|
|
12
|
-
protected providerName(): string;
|
|
13
|
-
runtimePolicy(): RuntimePolicy;
|
|
14
15
|
}
|
|
15
16
|
export declare class KimiProvider extends OpenAIChatProvider {
|
|
16
17
|
constructor(apiKey: string, model?: string, retry?: {
|
package/dist/providers/kimi.js
CHANGED
|
@@ -1,30 +1,16 @@
|
|
|
1
|
-
import { AnthropicProvider } from "./anthropic.js";
|
|
2
1
|
import { OpenAIChatProvider } from "./openai.js";
|
|
2
|
+
import { AnthropicCompatibleProvider } from "./anthropic-compatible.js";
|
|
3
3
|
import { endpointProfiles } from "./profiles.js";
|
|
4
|
-
|
|
5
|
-
"moonshot-v1-8k": { maxTurns: 15 },
|
|
6
|
-
"moonshot-v1-32k": { maxTurns: 20 },
|
|
7
|
-
"moonshot-v1-128k": { maxTurns: 30 },
|
|
8
|
-
"kimi-k2.5": { maxTurns: 30 },
|
|
9
|
-
"kimi-k2.6": { maxTurns: 35 },
|
|
10
|
-
"kimi-k2-thinking": { maxTurns: 50 },
|
|
11
|
-
"kimi-k2-thinking-turbo": { maxTurns: 40 },
|
|
12
|
-
};
|
|
4
|
+
import { KIMI_POLICIES, anthropicVendorProfiles } from "./vendor-profiles.js";
|
|
13
5
|
/**
|
|
14
6
|
* Kimi over its Anthropic-compatible endpoint.
|
|
7
|
+
* @deprecated Prefer `kimi({ protocol: "anthropic" })`. Behavior is now fully
|
|
8
|
+
* data-driven via `anthropicVendorProfiles.kimi`; this thin shim is kept for
|
|
9
|
+
* backward compatibility and `instanceof` checks.
|
|
15
10
|
*/
|
|
16
|
-
export class KimiAnthropicProvider extends
|
|
17
|
-
constructor(apiKey, model
|
|
18
|
-
super(apiKey, model, retry,
|
|
19
|
-
baseURL,
|
|
20
|
-
authMode: "api-key",
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
providerName() {
|
|
24
|
-
return "kimi";
|
|
25
|
-
}
|
|
26
|
-
runtimePolicy() {
|
|
27
|
-
return KIMI_POLICIES[this.model] ?? {};
|
|
11
|
+
export class KimiAnthropicProvider extends AnthropicCompatibleProvider {
|
|
12
|
+
constructor(apiKey, model, retry, baseURL) {
|
|
13
|
+
super(anthropicVendorProfiles.kimi, apiKey, model, retry, baseURL);
|
|
28
14
|
}
|
|
29
15
|
}
|
|
30
16
|
export class KimiProvider extends OpenAIChatProvider {
|
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { ProviderDescriptor, RuntimePolicy } from "../types.js";
|
|
2
|
+
import { OpenAIChatProvider, type OpenAIChatTurnReasoning } from "./openai.js";
|
|
3
|
+
import { AnthropicCompatibleProvider } from "./anthropic-compatible.js";
|
|
4
4
|
/**
|
|
5
5
|
* MiniMax over its Anthropic-compatible endpoint. Replay is carried as Anthropic
|
|
6
6
|
* `native_blocks` (thinking/text/tool_use), identical to the first-party
|
|
7
7
|
* Anthropic provider.
|
|
8
|
+
* @deprecated Prefer `minimax({ protocol: "anthropic" })`. Behavior is now fully
|
|
9
|
+
* data-driven via `anthropicVendorProfiles.minimax`; this thin shim is kept for
|
|
10
|
+
* backward compatibility and `instanceof` checks.
|
|
8
11
|
*/
|
|
9
|
-
export declare class MiniMaxAnthropicProvider extends
|
|
12
|
+
export declare class MiniMaxAnthropicProvider extends AnthropicCompatibleProvider {
|
|
10
13
|
constructor(apiKey: string, model?: string, retry?: {
|
|
11
14
|
maxRetries: number;
|
|
12
15
|
baseDelay: number;
|
|
13
16
|
}, baseURL?: string);
|
|
14
|
-
protected providerName(): string;
|
|
15
|
-
runtimePolicy(): RuntimePolicy;
|
|
16
17
|
}
|
|
17
18
|
/**
|
|
18
19
|
* MiniMax over its OpenAI-compatible endpoint. Replay is carried as
|
|
19
|
-
* `reasoning_content` / `reasoning_details` (split reasoning)
|
|
20
|
-
* default to `reasoning_split: true` so reasoning is returned
|
|
21
|
-
* than embedded in the message content.
|
|
20
|
+
* `reasoning_content` / `reasoning_details` (split reasoning) in a schema_version-2
|
|
21
|
+
* envelope; requests default to `reasoning_split: true` so reasoning is returned
|
|
22
|
+
* out-of-band rather than embedded in the message content. Request shaping and replay
|
|
23
|
+
* are supplied via the OpenAIChatProvider Template-Method hooks; the streaming /
|
|
24
|
+
* tool-call machinery is inherited from the base class.
|
|
22
25
|
*/
|
|
23
26
|
export declare class MiniMaxOpenAIProvider extends OpenAIChatProvider {
|
|
24
27
|
constructor(apiKey: string, model?: string, retry?: {
|
|
@@ -28,8 +31,19 @@ export declare class MiniMaxOpenAIProvider extends OpenAIChatProvider {
|
|
|
28
31
|
runtimePolicy(): RuntimePolicy;
|
|
29
32
|
descriptor(): ProviderDescriptor;
|
|
30
33
|
protected requireNonEmptyReasoningReplayForToolTurns(extensions?: Record<string, unknown>): boolean;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
protected cacheKeyParams(): Record<string, unknown>;
|
|
35
|
+
protected usesInlineThinkingTags(): boolean;
|
|
36
|
+
protected exposeReasoningDelta(extensions?: Record<string, unknown>): boolean;
|
|
37
|
+
protected prepareExtensions(extensions?: Record<string, unknown>): Record<string, unknown>;
|
|
38
|
+
protected rememberCompleteReplay(content: string, toolCalls: Array<{
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
arguments: string;
|
|
42
|
+
}>, r: OpenAIChatTurnReasoning): void;
|
|
43
|
+
protected rememberStreamReplay(content: string, toolCalls: Array<{
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
arguments: string;
|
|
47
|
+
}>, r: OpenAIChatTurnReasoning): void;
|
|
34
48
|
private rememberMiniMaxReplay;
|
|
35
49
|
}
|
|
@@ -1,41 +1,28 @@
|
|
|
1
|
-
import { AnthropicProvider } from "./anthropic.js";
|
|
2
1
|
import { OpenAIChatProvider } from "./openai.js";
|
|
2
|
+
import { AnthropicCompatibleProvider } from "./anthropic-compatible.js";
|
|
3
3
|
import { endpointProfiles } from "./profiles.js";
|
|
4
|
-
import { omitExtensionKeys
|
|
5
|
-
|
|
6
|
-
"MiniMax-M2.7": { maxTurns: 35 },
|
|
7
|
-
"MiniMax-M2.7-highspeed": { maxTurns: 35 },
|
|
8
|
-
"MiniMax-M2.5": { maxTurns: 25 },
|
|
9
|
-
"MiniMax-M2.5-highspeed": { maxTurns: 25 },
|
|
10
|
-
"MiniMax-M2.1": { maxTurns: 25 },
|
|
11
|
-
"MiniMax-M2.1-highspeed": { maxTurns: 25 },
|
|
12
|
-
"MiniMax-M2": { maxTurns: 20 },
|
|
13
|
-
"MiniMax-Text-01": { maxTurns: 20 },
|
|
14
|
-
};
|
|
4
|
+
import { omitExtensionKeys } from "./base.js";
|
|
5
|
+
import { MINIMAX_POLICIES, anthropicVendorProfiles } from "./vendor-profiles.js";
|
|
15
6
|
/**
|
|
16
7
|
* MiniMax over its Anthropic-compatible endpoint. Replay is carried as Anthropic
|
|
17
8
|
* `native_blocks` (thinking/text/tool_use), identical to the first-party
|
|
18
9
|
* Anthropic provider.
|
|
10
|
+
* @deprecated Prefer `minimax({ protocol: "anthropic" })`. Behavior is now fully
|
|
11
|
+
* data-driven via `anthropicVendorProfiles.minimax`; this thin shim is kept for
|
|
12
|
+
* backward compatibility and `instanceof` checks.
|
|
19
13
|
*/
|
|
20
|
-
export class MiniMaxAnthropicProvider extends
|
|
21
|
-
constructor(apiKey, model
|
|
22
|
-
super(apiKey, model, retry,
|
|
23
|
-
baseURL,
|
|
24
|
-
authMode: "api-key",
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
providerName() {
|
|
28
|
-
return "minimax";
|
|
29
|
-
}
|
|
30
|
-
runtimePolicy() {
|
|
31
|
-
return MINIMAX_POLICIES[this.model] ?? {};
|
|
14
|
+
export class MiniMaxAnthropicProvider extends AnthropicCompatibleProvider {
|
|
15
|
+
constructor(apiKey, model, retry, baseURL) {
|
|
16
|
+
super(anthropicVendorProfiles.minimax, apiKey, model, retry, baseURL);
|
|
32
17
|
}
|
|
33
18
|
}
|
|
34
19
|
/**
|
|
35
20
|
* MiniMax over its OpenAI-compatible endpoint. Replay is carried as
|
|
36
|
-
* `reasoning_content` / `reasoning_details` (split reasoning)
|
|
37
|
-
* default to `reasoning_split: true` so reasoning is returned
|
|
38
|
-
* than embedded in the message content.
|
|
21
|
+
* `reasoning_content` / `reasoning_details` (split reasoning) in a schema_version-2
|
|
22
|
+
* envelope; requests default to `reasoning_split: true` so reasoning is returned
|
|
23
|
+
* out-of-band rather than embedded in the message content. Request shaping and replay
|
|
24
|
+
* are supplied via the OpenAIChatProvider Template-Method hooks; the streaming /
|
|
25
|
+
* tool-call machinery is inherited from the base class.
|
|
39
26
|
*/
|
|
40
27
|
export class MiniMaxOpenAIProvider extends OpenAIChatProvider {
|
|
41
28
|
constructor(apiKey, model = "MiniMax-M2.7", retry, baseURL = endpointProfiles["minimax.openai"].baseURL) {
|
|
@@ -65,139 +52,33 @@ export class MiniMaxOpenAIProvider extends OpenAIChatProvider {
|
|
|
65
52
|
return false;
|
|
66
53
|
return extensions?.reasoning_split !== false;
|
|
67
54
|
}
|
|
68
|
-
|
|
55
|
+
// MiniMax auto prefix-caches and does not accept OpenAI's `prompt_cache_key`; omit it.
|
|
56
|
+
cacheKeyParams() {
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
// Reasoning arrives out-of-band (reasoning_content / reasoning_details), never inline tags.
|
|
60
|
+
usesInlineThinkingTags() {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
exposeReasoningDelta(extensions) {
|
|
64
|
+
return (extensions?.exposeReasoning ?? false);
|
|
65
|
+
}
|
|
66
|
+
prepareExtensions(extensions) {
|
|
69
67
|
const reasoningSplit = extensions?.reasoning_split !== false;
|
|
70
68
|
return {
|
|
71
69
|
...omitExtensionKeys(extensions, ["reasoning_split", "exposeReasoning"]),
|
|
72
70
|
__deepstrikeThinkingEnabled: reasoningSplit,
|
|
73
|
-
// Re-thread the degrade control flag (omitExtensionKeys strips internal
|
|
74
|
-
//
|
|
71
|
+
// Re-thread the degrade control flag (omitExtensionKeys strips internal keys) so
|
|
72
|
+
// buildChatMessages can honor it; the wire-request omit drops it.
|
|
75
73
|
...(extensions?.degradeMissingReasoningReplay === true ? { degradeMissingReasoningReplay: true } : {}),
|
|
76
74
|
reasoning_split: reasoningSplit,
|
|
77
75
|
};
|
|
78
76
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (this.circuit.isOpen())
|
|
82
|
-
throw new Error("Circuit breaker open");
|
|
83
|
-
const msgs = this.buildChatMessages(context, requestExtensions);
|
|
84
|
-
let lastErr;
|
|
85
|
-
for (let i = 0; i < this.maxRetries; i++) {
|
|
86
|
-
try {
|
|
87
|
-
const resp = await this.client.chat.completions.create({
|
|
88
|
-
...this.requestExtensions(requestExtensions),
|
|
89
|
-
model: this.model,
|
|
90
|
-
messages: msgs,
|
|
91
|
-
...(tools.length ? { tools: this.chat.buildTools(tools) } : {}),
|
|
92
|
-
});
|
|
93
|
-
this.circuit.recordSuccess();
|
|
94
|
-
const choice = resp.choices[0].message;
|
|
95
|
-
const nativeToolCalls = choice.tool_calls ?? [];
|
|
96
|
-
const toolCalls = this.chat.normalizeToolCalls(nativeToolCalls);
|
|
97
|
-
const content = choice.content ?? "";
|
|
98
|
-
this.rememberMiniMaxReplay(content, toolCalls, choice.reasoning_content, choice.reasoning_details, nativeToolCalls);
|
|
99
|
-
return { role: "assistant", content, tokenCount: resp.usage?.completion_tokens ?? resp.usage?.total_tokens, toolCalls };
|
|
100
|
-
}
|
|
101
|
-
catch (err) {
|
|
102
|
-
lastErr = err;
|
|
103
|
-
this.circuit.recordFailure();
|
|
104
|
-
if (i < this.maxRetries - 1)
|
|
105
|
-
await new Promise(r => setTimeout(r, this.baseDelay * 2 ** i));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
throw lastErr;
|
|
77
|
+
rememberCompleteReplay(content, toolCalls, r) {
|
|
78
|
+
this.rememberMiniMaxReplay(content, toolCalls, r.reasoningContent, r.reasoningDetails, r.nativeToolCalls);
|
|
109
79
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const requestExtensions = this.buildRequestExtensions(extensions);
|
|
113
|
-
const msgs = this.buildChatMessages(context, requestExtensions);
|
|
114
|
-
const toolCallBufs = {};
|
|
115
|
-
const emittedToolCallIndexes = new Set();
|
|
116
|
-
let reasoningContent = "";
|
|
117
|
-
let reasoningDetails;
|
|
118
|
-
let finalText = "";
|
|
119
|
-
const stream = await this.client.chat.completions.create({
|
|
120
|
-
...this.requestExtensions(requestExtensions),
|
|
121
|
-
model: this.model,
|
|
122
|
-
messages: msgs,
|
|
123
|
-
...(tools.length ? { tools: this.chat.buildTools(tools) } : {}),
|
|
124
|
-
stream: true,
|
|
125
|
-
stream_options: { include_usage: true },
|
|
126
|
-
});
|
|
127
|
-
let totalTokens = 0;
|
|
128
|
-
let inputTokens = 0;
|
|
129
|
-
let outputTokens = 0;
|
|
130
|
-
let cacheReadTokens = 0;
|
|
131
|
-
for await (const chunk of stream) {
|
|
132
|
-
if (chunk.usage) {
|
|
133
|
-
totalTokens = chunk.usage.total_tokens;
|
|
134
|
-
inputTokens = chunk.usage.prompt_tokens ?? 0;
|
|
135
|
-
outputTokens = chunk.usage.completion_tokens ?? 0;
|
|
136
|
-
cacheReadTokens = openAICachedPromptTokens(chunk.usage);
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
const choice = chunk.choices[0];
|
|
140
|
-
if (!choice)
|
|
141
|
-
continue;
|
|
142
|
-
const delta = choice.delta;
|
|
143
|
-
if (!delta)
|
|
144
|
-
continue;
|
|
145
|
-
if (exposeReasoning && delta.reasoning_content) {
|
|
146
|
-
yield { type: "thinking_delta", delta: String(delta.reasoning_content) };
|
|
147
|
-
}
|
|
148
|
-
if (delta.reasoning_content)
|
|
149
|
-
reasoningContent += String(delta.reasoning_content);
|
|
150
|
-
if (delta.reasoning_details !== undefined && delta.reasoning_details !== null)
|
|
151
|
-
reasoningDetails = delta.reasoning_details;
|
|
152
|
-
if (delta.content) {
|
|
153
|
-
finalText += String(delta.content);
|
|
154
|
-
yield { type: "text_delta", delta: delta.content };
|
|
155
|
-
}
|
|
156
|
-
for (const tc of delta.tool_calls ?? []) {
|
|
157
|
-
const idx = tc.index;
|
|
158
|
-
if (!toolCallBufs[idx])
|
|
159
|
-
toolCallBufs[idx] = { id: tc.id ?? "", name: "", argsBuf: "" };
|
|
160
|
-
if (tc.function?.name)
|
|
161
|
-
toolCallBufs[idx].name += tc.function.name;
|
|
162
|
-
toolCallBufs[idx].argsBuf += tc.function?.arguments ?? "";
|
|
163
|
-
}
|
|
164
|
-
if (choice.finish_reason === "tool_calls") {
|
|
165
|
-
const toolCalls = Object.values(toolCallBufs).map(tb => ({ id: tb.id, name: tb.name, arguments: tb.argsBuf || "{}" }));
|
|
166
|
-
this.rememberMiniMaxReplay(finalText, toolCalls, reasoningContent, reasoningDetails, nativeToolCallsFromBuffers(toolCallBufs));
|
|
167
|
-
for (const [index, tb] of Object.entries(toolCallBufs)) {
|
|
168
|
-
const idx = Number(index);
|
|
169
|
-
if (emittedToolCallIndexes.has(idx))
|
|
170
|
-
continue;
|
|
171
|
-
let args = {};
|
|
172
|
-
try {
|
|
173
|
-
args = JSON.parse(tb.argsBuf || "{}");
|
|
174
|
-
}
|
|
175
|
-
catch {
|
|
176
|
-
args = {};
|
|
177
|
-
}
|
|
178
|
-
emittedToolCallIndexes.add(idx);
|
|
179
|
-
yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args };
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
const toolCalls = Object.values(toolCallBufs).map(tb => ({ id: tb.id, name: tb.name, arguments: tb.argsBuf || "{}" }));
|
|
184
|
-
this.rememberMiniMaxReplay(finalText, toolCalls, reasoningContent, reasoningDetails, nativeToolCallsFromBuffers(toolCallBufs));
|
|
185
|
-
for (const [index, tb] of Object.entries(toolCallBufs)) {
|
|
186
|
-
const idx = Number(index);
|
|
187
|
-
if (emittedToolCallIndexes.has(idx))
|
|
188
|
-
continue;
|
|
189
|
-
let args = {};
|
|
190
|
-
try {
|
|
191
|
-
args = JSON.parse(tb.argsBuf || "{}");
|
|
192
|
-
}
|
|
193
|
-
catch {
|
|
194
|
-
args = {};
|
|
195
|
-
}
|
|
196
|
-
emittedToolCallIndexes.add(idx);
|
|
197
|
-
yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args };
|
|
198
|
-
}
|
|
199
|
-
if (totalTokens > 0)
|
|
200
|
-
yield { type: "usage", totalTokens, inputTokens, outputTokens, ...(cacheReadTokens > 0 ? { cacheReadInputTokens: cacheReadTokens } : {}) };
|
|
80
|
+
rememberStreamReplay(content, toolCalls, r) {
|
|
81
|
+
this.rememberMiniMaxReplay(content, toolCalls, r.reasoningContent, r.reasoningDetails, r.nativeToolCalls);
|
|
201
82
|
}
|
|
202
83
|
rememberMiniMaxReplay(content, toolCalls, reasoningContent, reasoningDetails, nativeToolCalls) {
|
|
203
84
|
const hasReasoning = typeof reasoningContent === "string" && reasoningContent.trim().length > 0;
|
|
@@ -215,10 +96,3 @@ export class MiniMaxOpenAIProvider extends OpenAIChatProvider {
|
|
|
215
96
|
});
|
|
216
97
|
}
|
|
217
98
|
}
|
|
218
|
-
function nativeToolCallsFromBuffers(toolCallBufs) {
|
|
219
|
-
return Object.values(toolCallBufs).map(tb => ({
|
|
220
|
-
id: tb.id,
|
|
221
|
-
type: "function",
|
|
222
|
-
function: { name: tb.name, arguments: tb.argsBuf || "{}" },
|
|
223
|
-
}));
|
|
224
|
-
}
|
|
@@ -15,6 +15,20 @@ export interface OpenAIProviderOptions {
|
|
|
15
15
|
/** Custom OpenAI-compatible endpoint (MiMo, DeepSeek, Kimi, …). Defaults to the OpenAI API. */
|
|
16
16
|
baseURL?: string;
|
|
17
17
|
}
|
|
18
|
+
/** Reasoning captured from a single model turn, handed to the replay-remember hooks so an
|
|
19
|
+
* OpenAI-compatible subclass can persist whatever replay envelope its wire requires. */
|
|
20
|
+
export interface OpenAIChatTurnReasoning {
|
|
21
|
+
reasoningContent: string;
|
|
22
|
+
reasoningDetails?: unknown;
|
|
23
|
+
nativeToolCalls: unknown[];
|
|
24
|
+
}
|
|
25
|
+
/** Rebuild OpenAI-native `tool_calls` blocks from the streamed buffers — needed by reasoning
|
|
26
|
+
* vendors (DeepSeek/MiniMax) that persist the native blocks in their replay envelope. */
|
|
27
|
+
export declare function nativeToolCallsFromBuffers(toolCallBufs: Record<number, {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
argsBuf: string;
|
|
31
|
+
}>): Array<Record<string, unknown>>;
|
|
18
32
|
export declare class OpenAIChatProvider implements LLMProvider {
|
|
19
33
|
protected client: OpenAI;
|
|
20
34
|
protected circuit: CircuitBreaker;
|
|
@@ -31,6 +45,35 @@ export declare class OpenAIChatProvider implements LLMProvider {
|
|
|
31
45
|
protected requireNonEmptyReasoningReplayForToolTurns(_extensions?: Record<string, unknown>): boolean;
|
|
32
46
|
protected degradeMissingReasoningReplay(extensions?: Record<string, unknown>): boolean;
|
|
33
47
|
protected buildChatMessages(context: RenderedContext, extensions?: Record<string, unknown>): OpenAI.Chat.Completions.ChatCompletionMessageParam[];
|
|
48
|
+
/** Pre-process caller extensions before they reach buildChatMessages + the wire request
|
|
49
|
+
* (e.g. set `__deepstrikeThinkingEnabled`). Default: pass through unchanged. */
|
|
50
|
+
protected prepareExtensions(extensions?: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
51
|
+
/** Extra top-level request-body fields merged into the chat.completions call (vendor thinking
|
|
52
|
+
* knobs like `reasoning_effort`, `extra_body`, `reasoning_split`). Default: none. */
|
|
53
|
+
protected requestBodyExtras(_extensions?: Record<string, unknown>): Record<string, unknown>;
|
|
54
|
+
/** Request-body params controlling prompt caching. Default sends OpenAI's `prompt_cache_key`;
|
|
55
|
+
* vendors whose endpoints reject unknown params (e.g. DeepSeek 400s) override to `{}`. */
|
|
56
|
+
protected cacheKeyParams(context: RenderedContext, tools: ToolSchema[]): Record<string, unknown>;
|
|
57
|
+
/** Whether streamed `content` may carry inline `<thinking>…</thinking>` tags to split out.
|
|
58
|
+
* Default true (OpenAI). Reasoning vendors emit reasoning out-of-band, so they return false. */
|
|
59
|
+
protected usesInlineThinkingTags(): boolean;
|
|
60
|
+
/** Whether to surface streamed `reasoning_content` as thinking_delta events. Default true;
|
|
61
|
+
* vendors gate this behind an `exposeReasoning` extension. */
|
|
62
|
+
protected exposeReasoningDelta(_extensions?: Record<string, unknown>): boolean;
|
|
63
|
+
/** Persist replay after a non-streaming turn. Default: nothing (plain OpenAI has no reasoning
|
|
64
|
+
* to replay). Reasoning vendors override to store their envelope. */
|
|
65
|
+
protected rememberCompleteReplay(_content: string, _toolCalls: Array<{
|
|
66
|
+
id: string;
|
|
67
|
+
name: string;
|
|
68
|
+
arguments: string;
|
|
69
|
+
}>, _reasoning: OpenAIChatTurnReasoning): void;
|
|
70
|
+
/** Persist replay after a streamed turn. Default: store `{ reasoning_content }` when there is a
|
|
71
|
+
* tool-call turn or captured reasoning (the prior base behavior). Vendors override. */
|
|
72
|
+
protected rememberStreamReplay(content: string, toolCalls: Array<{
|
|
73
|
+
id: string;
|
|
74
|
+
name: string;
|
|
75
|
+
arguments: string;
|
|
76
|
+
}>, reasoning: OpenAIChatTurnReasoning): void;
|
|
34
77
|
/**
|
|
35
78
|
* Pre-flight query: would this history validate against this provider with the
|
|
36
79
|
* given extensions, without sending the request? Lets an embedder route around
|