@rebon/cli-darwin-arm64 0.17.2 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/compose-runtime/package.json +17 -0
- package/bin/compose-runtime/payload/compose/credentials-runtime.js +38 -0
- package/bin/compose-runtime/payload/compose/llm-runtime.js +330 -0
- package/bin/compose-runtime/payload/compose/loop-assembly.js +149 -0
- package/bin/compose-runtime/payload/compose/serve-dispatch.js +82 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-anonymous-user-id.js +10 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-credentials.js +13 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-launch-environment.js +21 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-llm.js +313 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-settings.js +43 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-tools.js +20 -0
- package/bin/compose-runtime/payload/compose/shims/dsh-web.js +10 -0
- package/bin/compose-runtime/payload/compose/shims/llm-adapter.js +32 -0
- package/bin/compose-runtime/payload/compose/shims/zod-lite.js +49 -0
- package/bin/compose-runtime/payload/compose/systemprompt-runtime.js +74 -0
- package/bin/compose-runtime/payload/compose/tools-runtime.js +228 -0
- package/bin/compose-runtime/payload/compose/web-runtime.js +204 -0
- package/bin/compose-runtime/payload/vendor/cordis/index.js +1530 -0
- package/bin/compose-runtime/payload/vendor/cosmokit/LICENSE +21 -0
- package/bin/compose-runtime/payload/vendor/cosmokit/index.mjs +357 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-agent +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-agent-loop +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-llm-core +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-llm-deepseek +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-logger-console +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-scope +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-session +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-system-prompt +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-timeout +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-timer +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-tool-todo +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-tool-web +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-tools-schema +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/LICENSE-web-search-exa +21 -0
- package/bin/compose-runtime/payload/vendor/dsh/agent-loop.js +1193 -0
- package/bin/compose-runtime/payload/vendor/dsh/agent.js +714 -0
- package/bin/compose-runtime/payload/vendor/dsh/llm-core.js +269 -0
- package/bin/compose-runtime/payload/vendor/dsh/llm-deepseek.js +672 -0
- package/bin/compose-runtime/payload/vendor/dsh/logger-console.js +83 -0
- package/bin/compose-runtime/payload/vendor/dsh/scope.js +287 -0
- package/bin/compose-runtime/payload/vendor/dsh/session.js +1668 -0
- package/bin/compose-runtime/payload/vendor/dsh/system-prompt.js +309 -0
- package/bin/compose-runtime/payload/vendor/dsh/timeout.js +100 -0
- package/bin/compose-runtime/payload/vendor/dsh/timer.js +128 -0
- package/bin/compose-runtime/payload/vendor/dsh/tool-todo.js +143 -0
- package/bin/compose-runtime/payload/vendor/dsh/tool-web.js +1527 -0
- package/bin/compose-runtime/payload/vendor/dsh/tools-schema.js +849 -0
- package/bin/compose-runtime/payload/vendor/dsh/web-search-exa.js +122 -0
- package/bin/compose-runtime/payload/vendor/eventsource-parser/LICENSE +21 -0
- package/bin/compose-runtime/payload/vendor/eventsource-parser/index.js +177 -0
- package/bin/compose-runtime/payload/vendor/eventsource-parser/stream.js +48 -0
- package/bin/compose-runtime/payload/vendor/schemastery/index.mjs +656 -0
- package/bin/compose-runtime/payload-manifests.json +48 -0
- package/bin/compose-runtime/src/bridge.mjs +142 -0
- package/bin/compose-runtime/src/credentials-runtime.mjs +50 -0
- package/bin/compose-runtime/src/eventsource-stream.mjs +48 -0
- package/bin/compose-runtime/src/index.mjs +7 -0
- package/bin/compose-runtime/src/llm-runtime.mjs +326 -0
- package/bin/compose-runtime/src/loader.mjs +78 -0
- package/bin/compose-runtime/src/loop-assembly.mjs +237 -0
- package/bin/compose-runtime/src/payload.mjs +49 -0
- package/bin/compose-runtime/src/plugin.mjs +59 -0
- package/bin/compose-runtime/src/realm.mjs +223 -0
- package/bin/compose-runtime/src/registry.mjs +191 -0
- package/bin/compose-runtime/src/resolve.mjs +115 -0
- package/bin/compose-runtime/src/systemprompt-runtime.mjs +67 -0
- package/bin/compose-runtime/src/tools-runtime.mjs +239 -0
- package/bin/compose-runtime/src/web-runtime.mjs +209 -0
- package/bin/plugin-host/package.json +11 -0
- package/bin/plugin-host/src/bridge.mjs +64 -0
- package/bin/plugin-host/src/cli.mjs +105 -0
- package/bin/plugin-host/src/framing.mjs +113 -0
- package/bin/plugin-host/src/host.mjs +624 -0
- package/bin/plugin-host/src/json.mjs +196 -0
- package/bin/plugin-host/src/lifecycle.mjs +114 -0
- package/bin/plugin-host/src/loader.mjs +142 -0
- package/bin/plugin-host/src/methods.mjs +256 -0
- package/bin/plugin-host/src/protocol.mjs +129 -0
- package/bin/plugin-host/src/sdk.mjs +7 -0
- package/bin/rebon +0 -0
- package/bin/rebon-boa-helper +0 -0
- package/package.json +4 -1
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
var __knownSymbol = (name2, symbol) => (symbol = Symbol[name2]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name2);
|
|
2
|
+
var __typeError = (msg) => {
|
|
3
|
+
throw TypeError(msg);
|
|
4
|
+
};
|
|
5
|
+
var __using = (stack, value, async) => {
|
|
6
|
+
if (value != null) {
|
|
7
|
+
if (typeof value !== "object" && typeof value !== "function") __typeError("Object expected");
|
|
8
|
+
var dispose, inner;
|
|
9
|
+
if (async) dispose = value[__knownSymbol("asyncDispose")];
|
|
10
|
+
if (dispose === void 0) {
|
|
11
|
+
dispose = value[__knownSymbol("dispose")];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") __typeError("Object not disposable");
|
|
15
|
+
if (inner) dispose = function() {
|
|
16
|
+
try {
|
|
17
|
+
inner.call(this);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
return Promise.reject(e);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
stack.push([async, dispose, value]);
|
|
23
|
+
} else if (async) {
|
|
24
|
+
stack.push([async]);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
};
|
|
28
|
+
var __callDispose = (stack, error, hasError) => {
|
|
29
|
+
var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
|
|
30
|
+
return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
|
|
31
|
+
};
|
|
32
|
+
var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
|
|
33
|
+
var next = (it) => {
|
|
34
|
+
while (it = stack.pop()) {
|
|
35
|
+
try {
|
|
36
|
+
var result = it[1] && it[1].call(it[2]);
|
|
37
|
+
if (it[0]) return Promise.resolve(result).then(next, (e) => (fail(e), next()));
|
|
38
|
+
} catch (e) {
|
|
39
|
+
fail(e);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (hasError) throw error;
|
|
43
|
+
};
|
|
44
|
+
return next();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// packages/llm/llm-deepseek/src/index.ts
|
|
48
|
+
import z from "@deepseek-ai/schemastery";
|
|
49
|
+
import { assertUsableApiKey, LlmError as LlmError5, resolveRetryPolicy, RetryPolicySchema } from "@deepseek-ai/dsh-llm";
|
|
50
|
+
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
51
|
+
import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
|
|
52
|
+
import { deepEqualJson, installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
53
|
+
import { MAX_TIMER_DELAY_MS } from "@deepseek-ai/dsh-timeout";
|
|
54
|
+
import { getOrCreateAnonymousUserId } from "@deepseek-ai/dsh-anonymous-user-id";
|
|
55
|
+
|
|
56
|
+
// packages/llm/llm-deepseek/src/adapter.ts
|
|
57
|
+
import { attributionHeaders, CONTEXT_WINDOW_EXCEEDED_CODE, isContextWindowExceededError, isQuotaExceededError, LlmAdapter, LlmError as LlmError4, ProviderRequestId, QUOTA_EXCEEDED_CODE, ReasoningEffortId } from "@deepseek-ai/dsh-llm";
|
|
58
|
+
import { idleWatchdog, timeoutOf } from "@deepseek-ai/dsh-timeout";
|
|
59
|
+
|
|
60
|
+
// packages/llm/llm-deepseek/src/serialize.ts
|
|
61
|
+
import { contentHasImage, LlmError } from "@deepseek-ai/dsh-llm";
|
|
62
|
+
function reasoningEffort(effort) {
|
|
63
|
+
if (effort === "off" || effort === "high" || effort === "max") {
|
|
64
|
+
return effort;
|
|
65
|
+
}
|
|
66
|
+
throw new LlmError(
|
|
67
|
+
`DeepSeek does not support reasoning effort "${effort}"`,
|
|
68
|
+
"UNSUPPORTED_REASONING_EFFORT"
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
function resolveThinking(options, defaults) {
|
|
72
|
+
if (options.purpose === "session-title") return { thinking: "disabled" };
|
|
73
|
+
const effort = options.reasoningEffort === void 0 ? defaults.reasoningEffort : reasoningEffort(options.reasoningEffort);
|
|
74
|
+
if (defaults.thinking === "disabled" && effort !== void 0 && effort !== "off") {
|
|
75
|
+
throw new LlmError(
|
|
76
|
+
`DeepSeek deployment does not support reasoning effort "${effort}"`,
|
|
77
|
+
"UNSUPPORTED_REASONING_EFFORT"
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
if (effort === "off") return { thinking: "disabled" };
|
|
81
|
+
if (effort === "high" || effort === "max") {
|
|
82
|
+
return { thinking: "enabled", reasoningEffort: effort };
|
|
83
|
+
}
|
|
84
|
+
return defaults.thinking === void 0 ? {} : { thinking: defaults.thinking };
|
|
85
|
+
}
|
|
86
|
+
function flattenText(blocks) {
|
|
87
|
+
return blocks.filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
88
|
+
}
|
|
89
|
+
function assertTextOnly(blocks) {
|
|
90
|
+
if (contentHasImage(blocks)) {
|
|
91
|
+
throw new LlmError("The DeepSeek chat-completions adapter does not support image content.", "UNSUPPORTED_CONTENT");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function serializeAssistant(message) {
|
|
95
|
+
const text = flattenText(message.content);
|
|
96
|
+
const reasoning = message.content.filter((block) => block.type === "reasoning").map((block) => block.text).join("");
|
|
97
|
+
const toolCalls = message.content.filter((block) => block.type === "tool-call").map((block) => ({
|
|
98
|
+
id: block.id,
|
|
99
|
+
type: "function",
|
|
100
|
+
function: { name: block.name, arguments: block.arguments }
|
|
101
|
+
}));
|
|
102
|
+
return {
|
|
103
|
+
role: "assistant",
|
|
104
|
+
// Text-less turns send "" — NEVER null. Pure tool-call turns: the
|
|
105
|
+
// official samples replay message.content verbatim (which is "") and
|
|
106
|
+
// some gateways reject null outright. Reasoning-ONLY turns (the model
|
|
107
|
+
// can answer entirely in the reasoning channel, e.g. a v4-flash
|
|
108
|
+
// greeting): the live API rejects null-content/no-tool_calls assistant
|
|
109
|
+
// messages with a 400 ("content or tool_calls must be set"), and since
|
|
110
|
+
// the message sits durably in the session log, a null here bricks every
|
|
111
|
+
// later turn of that session.
|
|
112
|
+
content: text,
|
|
113
|
+
// Official passback rule (guides/thinking_mode.mdx): reasoning_content
|
|
114
|
+
// must return on tool-call turns; it is ignored on plain turns, so we
|
|
115
|
+
// drop it there to save tokens.
|
|
116
|
+
...toolCalls.length > 0 && reasoning.length > 0 ? { reasoning_content: reasoning } : {},
|
|
117
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function serializeMessages(messages) {
|
|
121
|
+
const wire = [];
|
|
122
|
+
for (const message of messages) {
|
|
123
|
+
assertTextOnly(message.content);
|
|
124
|
+
if (message.role === "system") {
|
|
125
|
+
wire.push({ role: "system", content: flattenText(message.content) });
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (message.role === "assistant") {
|
|
129
|
+
wire.push(serializeAssistant(message));
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const toolResults = message.content.filter((block) => block.type === "tool-result");
|
|
133
|
+
const text = flattenText(message.content);
|
|
134
|
+
if (text.length > 0 || toolResults.length === 0) {
|
|
135
|
+
wire.push({ role: "user", content: text });
|
|
136
|
+
}
|
|
137
|
+
for (const result of toolResults) {
|
|
138
|
+
wire.push({
|
|
139
|
+
role: "tool",
|
|
140
|
+
tool_call_id: result.toolCallId,
|
|
141
|
+
// Empty tool output still needs SOME content on the wire.
|
|
142
|
+
content: flattenText(result.content) || "(no output)"
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return wire;
|
|
147
|
+
}
|
|
148
|
+
function serializeRequest(options, defaults = {}) {
|
|
149
|
+
const messages = [];
|
|
150
|
+
if (options.system !== void 0) {
|
|
151
|
+
messages.push({ role: "system", content: options.system });
|
|
152
|
+
}
|
|
153
|
+
messages.push(...serializeMessages(options.messages));
|
|
154
|
+
const tools = options.tools?.map((tool) => ({
|
|
155
|
+
type: "function",
|
|
156
|
+
function: {
|
|
157
|
+
name: tool.name,
|
|
158
|
+
description: tool.description,
|
|
159
|
+
parameters: tool.parameters
|
|
160
|
+
}
|
|
161
|
+
}));
|
|
162
|
+
const resolvedThinking = resolveThinking(options, defaults);
|
|
163
|
+
return {
|
|
164
|
+
model: options.model,
|
|
165
|
+
messages,
|
|
166
|
+
stream: true,
|
|
167
|
+
stream_options: { include_usage: true },
|
|
168
|
+
...resolvedThinking.thinking !== void 0 ? { thinking: { type: resolvedThinking.thinking } } : {},
|
|
169
|
+
...resolvedThinking.reasoningEffort !== void 0 ? { reasoning_effort: resolvedThinking.reasoningEffort } : {},
|
|
170
|
+
...tools !== void 0 && tools.length > 0 ? { tools } : {},
|
|
171
|
+
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
172
|
+
...options.maxTokens === void 0 ? {} : { max_tokens: options.maxTokens },
|
|
173
|
+
...options.stop !== void 0 ? { stop: options.stop } : {}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// packages/llm/llm-deepseek/src/sse.ts
|
|
178
|
+
import { EventSourceParserStream } from "eventsource-parser/stream";
|
|
179
|
+
import { LlmError as LlmError2 } from "@deepseek-ai/dsh-llm";
|
|
180
|
+
var DONE = "[DONE]";
|
|
181
|
+
async function* parseSse(stream, onComment) {
|
|
182
|
+
const events = stream.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream({ onComment }));
|
|
183
|
+
for await (const { data } of events) {
|
|
184
|
+
yield data;
|
|
185
|
+
if (data === DONE) return;
|
|
186
|
+
}
|
|
187
|
+
throw new LlmError2("SSE stream ended without [DONE]", "STREAM_CLOSED");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// packages/llm/llm-deepseek/src/translate.ts
|
|
191
|
+
import { CallId, EMPTY_RESPONSE_CODE, LlmError as LlmError3 } from "@deepseek-ai/dsh-llm";
|
|
192
|
+
function mapFinishReason(reason) {
|
|
193
|
+
switch (reason) {
|
|
194
|
+
case "stop":
|
|
195
|
+
return { kind: "stop" };
|
|
196
|
+
case "tool_calls":
|
|
197
|
+
return { kind: "tool-calls" };
|
|
198
|
+
case "length":
|
|
199
|
+
return { kind: "max-tokens" };
|
|
200
|
+
default:
|
|
201
|
+
return {
|
|
202
|
+
kind: "error",
|
|
203
|
+
failure: { message: `model stopped: ${reason}`, code: reason.toUpperCase() }
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function mapUsage(usage) {
|
|
208
|
+
const cacheRead = usage.prompt_tokens_details?.cached_tokens ?? usage.prompt_cache_hit_tokens;
|
|
209
|
+
const reasoning = usage.completion_tokens_details?.reasoning_tokens;
|
|
210
|
+
return {
|
|
211
|
+
inputTokens: usage.prompt_tokens - (cacheRead ?? 0),
|
|
212
|
+
outputTokens: usage.completion_tokens,
|
|
213
|
+
...cacheRead !== void 0 ? { cacheReadTokens: cacheRead } : {},
|
|
214
|
+
...reasoning !== void 0 ? { reasoningTokens: reasoning } : {}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function closeBlock(block) {
|
|
218
|
+
switch (block.kind) {
|
|
219
|
+
case "text":
|
|
220
|
+
return { type: "text", text: block.text };
|
|
221
|
+
case "reasoning":
|
|
222
|
+
return { type: "reasoning", text: block.text };
|
|
223
|
+
case "tool-call":
|
|
224
|
+
return {
|
|
225
|
+
type: "tool-call",
|
|
226
|
+
id: CallId(block.callId ?? ""),
|
|
227
|
+
name: block.name ?? "",
|
|
228
|
+
arguments: block.text
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function* translate(payloads) {
|
|
233
|
+
let nextIndex = 0;
|
|
234
|
+
let textBlock;
|
|
235
|
+
let reasoningBlock;
|
|
236
|
+
const toolBlocks = /* @__PURE__ */ new Map();
|
|
237
|
+
const order = [];
|
|
238
|
+
let pendingFinish;
|
|
239
|
+
let pendingUsage;
|
|
240
|
+
function open(kind) {
|
|
241
|
+
const block = { index: nextIndex++, kind, text: "" };
|
|
242
|
+
order.push(block);
|
|
243
|
+
return block;
|
|
244
|
+
}
|
|
245
|
+
for await (const payload of payloads) {
|
|
246
|
+
if (payload === DONE) {
|
|
247
|
+
for (const block of order) {
|
|
248
|
+
yield { type: "block-end", index: block.index, block: closeBlock(block) };
|
|
249
|
+
}
|
|
250
|
+
if (pendingUsage) yield { type: "usage", usage: pendingUsage };
|
|
251
|
+
const reason = pendingFinish ?? { kind: "stop" };
|
|
252
|
+
yield {
|
|
253
|
+
type: "finish",
|
|
254
|
+
reason: reason.kind === "stop" && order.length === 0 ? {
|
|
255
|
+
kind: "error",
|
|
256
|
+
failure: { message: "model returned a completed response with no content", code: EMPTY_RESPONSE_CODE }
|
|
257
|
+
} : reason
|
|
258
|
+
};
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
let chunk;
|
|
262
|
+
try {
|
|
263
|
+
chunk = JSON.parse(payload);
|
|
264
|
+
} catch {
|
|
265
|
+
throw new LlmError3(`malformed SSE payload: ${payload.slice(0, 120)}`, "MALFORMED_RESPONSE");
|
|
266
|
+
}
|
|
267
|
+
for (const choice of chunk.choices ?? []) {
|
|
268
|
+
const delta = choice.delta;
|
|
269
|
+
const reasoning = delta?.reasoning_content;
|
|
270
|
+
if (typeof reasoning === "string" && reasoning.length > 0) {
|
|
271
|
+
if (!reasoningBlock) {
|
|
272
|
+
reasoningBlock = open("reasoning");
|
|
273
|
+
yield { type: "block-start", index: reasoningBlock.index, blockType: "reasoning" };
|
|
274
|
+
}
|
|
275
|
+
reasoningBlock.text += reasoning;
|
|
276
|
+
yield { type: "reasoning-delta", index: reasoningBlock.index, text: reasoning };
|
|
277
|
+
}
|
|
278
|
+
const content = delta?.content;
|
|
279
|
+
if (typeof content === "string" && content.length > 0) {
|
|
280
|
+
if (!textBlock) {
|
|
281
|
+
textBlock = open("text");
|
|
282
|
+
yield { type: "block-start", index: textBlock.index, blockType: "text" };
|
|
283
|
+
}
|
|
284
|
+
textBlock.text += content;
|
|
285
|
+
yield { type: "text-delta", index: textBlock.index, text: content };
|
|
286
|
+
}
|
|
287
|
+
for (const call of delta?.tool_calls ?? []) {
|
|
288
|
+
let block = toolBlocks.get(call.index);
|
|
289
|
+
if (!block) {
|
|
290
|
+
block = open("tool-call");
|
|
291
|
+
toolBlocks.set(call.index, block);
|
|
292
|
+
yield { type: "block-start", index: block.index, blockType: "tool-call" };
|
|
293
|
+
}
|
|
294
|
+
if (call.id !== void 0) block.callId = call.id;
|
|
295
|
+
if (call.function?.name !== void 0) block.name = call.function.name;
|
|
296
|
+
const fragment = call.function?.arguments ?? "";
|
|
297
|
+
block.text += fragment;
|
|
298
|
+
yield {
|
|
299
|
+
type: "tool-call-delta",
|
|
300
|
+
index: block.index,
|
|
301
|
+
id: CallId(block.callId ?? ""),
|
|
302
|
+
...block.name !== void 0 ? { name: block.name } : {},
|
|
303
|
+
argumentsDelta: fragment
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
if (typeof choice.finish_reason === "string") {
|
|
307
|
+
pendingFinish = mapFinishReason(choice.finish_reason);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (chunk.usage) pendingUsage = mapUsage(chunk.usage);
|
|
311
|
+
}
|
|
312
|
+
throw new LlmError3("SSE payload stream ended without [DONE]", "STREAM_CLOSED");
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// packages/llm/llm-deepseek/src/adapter.ts
|
|
316
|
+
var DEFAULT_STREAM_IDLE_TIMEOUT_MS = 3e5;
|
|
317
|
+
var DEFAULT_CONTEXT_WINDOW = 1e6;
|
|
318
|
+
var DEFAULT_MAX_TOKENS = 256e3;
|
|
319
|
+
var STREAM_IDLE_TIMEOUT_CODE = "LLM_STREAM_IDLE_TIMEOUT";
|
|
320
|
+
var OFF_REASONING_EFFORT = ReasoningEffortId("off");
|
|
321
|
+
var HIGH_REASONING_EFFORT = ReasoningEffortId("high");
|
|
322
|
+
var MAX_REASONING_EFFORT = ReasoningEffortId("max");
|
|
323
|
+
var REASONING_EFFORTS = [
|
|
324
|
+
{ id: OFF_REASONING_EFFORT, name: "Off" },
|
|
325
|
+
{ id: HIGH_REASONING_EFFORT, name: "High" },
|
|
326
|
+
{ id: MAX_REASONING_EFFORT, name: "Max" }
|
|
327
|
+
];
|
|
328
|
+
var OFF_ONLY_REASONING_EFFORTS = [
|
|
329
|
+
{ id: OFF_REASONING_EFFORT, name: "Off" }
|
|
330
|
+
];
|
|
331
|
+
function modelInfo(provider, model) {
|
|
332
|
+
return {
|
|
333
|
+
provider,
|
|
334
|
+
id: model.id,
|
|
335
|
+
name: model.name ?? model.id,
|
|
336
|
+
...model.description === void 0 ? {} : { description: model.description },
|
|
337
|
+
inputModalities: ["text"]
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function providerRetryAfterMs(value) {
|
|
341
|
+
if (value === null) return void 0;
|
|
342
|
+
if (/^\d+$/.test(value)) {
|
|
343
|
+
const delay2 = Number(value) * 1e3;
|
|
344
|
+
return Number.isFinite(delay2) && delay2 > 0 ? delay2 : void 0;
|
|
345
|
+
}
|
|
346
|
+
const delay = Date.parse(value) - Date.now();
|
|
347
|
+
return Number.isFinite(delay) && delay > 0 ? delay : void 0;
|
|
348
|
+
}
|
|
349
|
+
function requestId(headers) {
|
|
350
|
+
const value = headers.get("x-request-id") ?? headers.get("x-deepseek-request-id");
|
|
351
|
+
return value === null || value.length === 0 ? void 0 : ProviderRequestId(value);
|
|
352
|
+
}
|
|
353
|
+
function httpErrorCode(status, error) {
|
|
354
|
+
if (status === 401 || status === 403) return "AUTH";
|
|
355
|
+
const detail = [error?.code, error?.type, error?.message].filter(Boolean).join(" ");
|
|
356
|
+
if (isQuotaExceededError(detail)) return QUOTA_EXCEEDED_CODE;
|
|
357
|
+
if (status === 429) return "RATE_LIMIT";
|
|
358
|
+
if (status === 400) {
|
|
359
|
+
if (isContextWindowExceededError(detail)) return CONTEXT_WINDOW_EXCEEDED_CODE;
|
|
360
|
+
return "INVALID_REQUEST";
|
|
361
|
+
}
|
|
362
|
+
if (status >= 500) return "SERVER";
|
|
363
|
+
return `HTTP_${status}`;
|
|
364
|
+
}
|
|
365
|
+
var DeepSeekAdapter = class extends LlmAdapter {
|
|
366
|
+
constructor(config) {
|
|
367
|
+
super();
|
|
368
|
+
this.config = config;
|
|
369
|
+
}
|
|
370
|
+
config;
|
|
371
|
+
providerInfo(provider) {
|
|
372
|
+
return { id: provider, name: "DeepSeek" };
|
|
373
|
+
}
|
|
374
|
+
providerRetryPolicy(_provider) {
|
|
375
|
+
return this.config.options().retryPolicy;
|
|
376
|
+
}
|
|
377
|
+
listModels(provider) {
|
|
378
|
+
return Promise.resolve(this.config.options().models.map((model) => modelInfo(provider, model)));
|
|
379
|
+
}
|
|
380
|
+
resolveModel(provider, model, _signal) {
|
|
381
|
+
const connection = this.config.options();
|
|
382
|
+
const configured = connection.models.find((entry) => entry.id === model);
|
|
383
|
+
const contextWindow = configured?.contextWindow ?? connection.defaultContextWindow;
|
|
384
|
+
return Promise.resolve({
|
|
385
|
+
// The chat-completions wire route is text-only regardless of catalog
|
|
386
|
+
// membership, so the uncatalogued fallback declares the same negative
|
|
387
|
+
// capability — "unknown" here would let the host accept and persist
|
|
388
|
+
// images the serializer must then reject.
|
|
389
|
+
...configured === void 0 ? { provider, id: model, name: model, inputModalities: ["text"] } : modelInfo(provider, configured),
|
|
390
|
+
context: { contextWindow },
|
|
391
|
+
defaultMaxTokens: configured?.maxTokens ?? connection.maxTokens,
|
|
392
|
+
...connection.defaults.thinking === "disabled" ? {
|
|
393
|
+
reasoning: {
|
|
394
|
+
efforts: OFF_ONLY_REASONING_EFFORTS,
|
|
395
|
+
defaultEffort: OFF_REASONING_EFFORT
|
|
396
|
+
}
|
|
397
|
+
} : {
|
|
398
|
+
reasoning: {
|
|
399
|
+
efforts: REASONING_EFFORTS,
|
|
400
|
+
defaultEffort: connection.defaults.reasoningEffort === "off" ? OFF_REASONING_EFFORT : connection.defaults.reasoningEffort === "max" ? MAX_REASONING_EFFORT : HIGH_REASONING_EFFORT
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
async *stream(options) {
|
|
406
|
+
var _stack = [];
|
|
407
|
+
try {
|
|
408
|
+
const connection = this.config.options();
|
|
409
|
+
const apiKey = await this.config.resolveApiKey(connection);
|
|
410
|
+
const userId = this.config.resolveUserId();
|
|
411
|
+
const consumer = new AbortController();
|
|
412
|
+
const upstream = options.signal === void 0 ? consumer.signal : AbortSignal.any([options.signal, consumer.signal]);
|
|
413
|
+
const watchdog = __using(_stack, idleWatchdog(upstream, connection.streamIdleTimeoutMs, STREAM_IDLE_TIMEOUT_CODE));
|
|
414
|
+
const iterator = this.request(
|
|
415
|
+
options,
|
|
416
|
+
watchdog.signal,
|
|
417
|
+
connection,
|
|
418
|
+
apiKey,
|
|
419
|
+
userId,
|
|
420
|
+
() => {
|
|
421
|
+
watchdog.pulse();
|
|
422
|
+
}
|
|
423
|
+
)[Symbol.asyncIterator]();
|
|
424
|
+
let exhausted = false;
|
|
425
|
+
try {
|
|
426
|
+
while (true) {
|
|
427
|
+
const result = await watchdog.next(iterator);
|
|
428
|
+
if (result.done) {
|
|
429
|
+
exhausted = true;
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
yield result.value;
|
|
433
|
+
}
|
|
434
|
+
} catch (error) {
|
|
435
|
+
if (timeoutOf(watchdog.signal, STREAM_IDLE_TIMEOUT_CODE) !== void 0) {
|
|
436
|
+
throw new LlmError4(
|
|
437
|
+
`DeepSeek stream idle timeout after ${connection.streamIdleTimeoutMs}ms`,
|
|
438
|
+
"TIMEOUT",
|
|
439
|
+
{ cause: error }
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
if (options.signal?.aborted) {
|
|
443
|
+
throw new LlmError4("DeepSeek request aborted by caller", "ABORTED", { cause: error });
|
|
444
|
+
}
|
|
445
|
+
if (error instanceof LlmError4) throw error;
|
|
446
|
+
throw new LlmError4(`DeepSeek API stream from ${connection.baseURL} failed`, "TRANSPORT", { cause: error });
|
|
447
|
+
} finally {
|
|
448
|
+
consumer.abort("DeepSeek stream consumer stopped");
|
|
449
|
+
if (!exhausted && iterator.return !== void 0) {
|
|
450
|
+
try {
|
|
451
|
+
await iterator.return();
|
|
452
|
+
} catch (_abortedTransportTeardown) {
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
} catch (_) {
|
|
457
|
+
var _error = _, _hasError = true;
|
|
458
|
+
} finally {
|
|
459
|
+
__callDispose(_stack, _error, _hasError);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async *request(options, signal, connection, apiKey, userId, onComment) {
|
|
463
|
+
const body = serializeRequest(options, connection.defaults);
|
|
464
|
+
const payload = JSON.stringify(body);
|
|
465
|
+
const headers = {
|
|
466
|
+
"authorization": `Bearer ${apiKey}`,
|
|
467
|
+
"content-type": "application/json",
|
|
468
|
+
"accept": "text/event-stream",
|
|
469
|
+
...attributionHeaders(),
|
|
470
|
+
"x-deepseek-harness-user-id": String(userId),
|
|
471
|
+
...options.sessionId !== void 0 ? { "x-deepseek-harness-session-id": String(options.sessionId) } : {},
|
|
472
|
+
...options.purpose === "compaction" ? { "x-deepseek-harness-compact": "1" } : {}
|
|
473
|
+
};
|
|
474
|
+
let response;
|
|
475
|
+
try {
|
|
476
|
+
response = await fetch(`${connection.baseURL}/chat/completions`, {
|
|
477
|
+
method: "POST",
|
|
478
|
+
headers,
|
|
479
|
+
body: payload,
|
|
480
|
+
signal
|
|
481
|
+
});
|
|
482
|
+
} catch (error) {
|
|
483
|
+
if (signal.aborted) throw error;
|
|
484
|
+
throw new LlmError4(
|
|
485
|
+
`DeepSeek API request to ${connection.baseURL} failed`,
|
|
486
|
+
"TRANSPORT",
|
|
487
|
+
{ cause: error }
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
if (!response.ok) {
|
|
491
|
+
let message = `DeepSeek API error (HTTP ${response.status})`;
|
|
492
|
+
let providerError;
|
|
493
|
+
try {
|
|
494
|
+
const parsed = await response.json();
|
|
495
|
+
providerError = parsed.error;
|
|
496
|
+
if (providerError?.message) message = providerError.message;
|
|
497
|
+
} catch {
|
|
498
|
+
}
|
|
499
|
+
const delay = providerRetryAfterMs(response.headers.get("retry-after"));
|
|
500
|
+
const id = requestId(response.headers);
|
|
501
|
+
throw new LlmError4(message, httpErrorCode(response.status, providerError), {
|
|
502
|
+
status: response.status,
|
|
503
|
+
...delay === void 0 ? {} : { providerRetryAfterMs: delay },
|
|
504
|
+
...id === void 0 ? {} : { requestId: id }
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
if (!response.body) {
|
|
508
|
+
throw new LlmError4("DeepSeek API returned no response body", "EMPTY_RESPONSE");
|
|
509
|
+
}
|
|
510
|
+
yield* translate(parseSse(response.body, onComment));
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// packages/llm/llm-deepseek/src/index.ts
|
|
515
|
+
var name = "llm-deepseek";
|
|
516
|
+
var inject = ["llm"];
|
|
517
|
+
var NS = settingsNamespace("llm-deepseek");
|
|
518
|
+
var DEFAULT_API_KEY_ENV = "DEEPSEEK_API_KEY";
|
|
519
|
+
var PROVIDER = "deepseek-official";
|
|
520
|
+
var DEFAULT_MODELS = [
|
|
521
|
+
{ id: "deepseek-v4-flash", name: "DeepSeek-V4-Flash", contextWindow: DEFAULT_CONTEXT_WINDOW },
|
|
522
|
+
{ id: "deepseek-v4-pro", name: "DeepSeek-V4-Pro", contextWindow: DEFAULT_CONTEXT_WINDOW }
|
|
523
|
+
];
|
|
524
|
+
var catalogModel = z.object({
|
|
525
|
+
id: z.string().required(),
|
|
526
|
+
name: z.string(),
|
|
527
|
+
description: z.string(),
|
|
528
|
+
contextWindow: z.number().step(1).min(1),
|
|
529
|
+
maxTokens: z.number().step(1).min(1)
|
|
530
|
+
});
|
|
531
|
+
var Config = z.object({
|
|
532
|
+
apiKeyEnv: z.string().role("credential-ref").default(DEFAULT_API_KEY_ENV),
|
|
533
|
+
baseURL: z.string(),
|
|
534
|
+
thinking: z.union(["enabled", "disabled"]),
|
|
535
|
+
reasoningEffort: z.union(["off", "high", "max"]),
|
|
536
|
+
maxTokens: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER).default(DEFAULT_MAX_TOKENS),
|
|
537
|
+
defaultContextWindow: z.number().step(1).min(1).default(DEFAULT_CONTEXT_WINDOW),
|
|
538
|
+
models: z.array(catalogModel).default(DEFAULT_MODELS),
|
|
539
|
+
streamIdleTimeoutMs: z.number().min(Number.MIN_VALUE).max(MAX_TIMER_DELAY_MS).default(DEFAULT_STREAM_IDLE_TIMEOUT_MS),
|
|
540
|
+
retryPolicy: RetryPolicySchema
|
|
541
|
+
});
|
|
542
|
+
var PUBLIC_BASE_URL = "https://api.deepseek.com";
|
|
543
|
+
var BASE_URL_ENV = "DEEPSEEK_BASE_URL";
|
|
544
|
+
function resolveModels(models) {
|
|
545
|
+
const seen = /* @__PURE__ */ new Set();
|
|
546
|
+
return (models ?? DEFAULT_MODELS).map((model) => {
|
|
547
|
+
if (model.id.length === 0) throw new Error("llm-deepseek: catalog model ids must be non-empty");
|
|
548
|
+
if (model.name !== void 0 && model.name.length === 0) {
|
|
549
|
+
throw new Error(`llm-deepseek: catalog model "${model.id}" has an empty name`);
|
|
550
|
+
}
|
|
551
|
+
if (model.contextWindow !== void 0 && (!Number.isInteger(model.contextWindow) || model.contextWindow <= 0)) {
|
|
552
|
+
throw new Error(
|
|
553
|
+
`llm-deepseek: catalog model "${model.id}" contextWindow must be a positive integer`
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
if (model.maxTokens !== void 0 && (!Number.isInteger(model.maxTokens) || model.maxTokens <= 0)) {
|
|
557
|
+
throw new Error(
|
|
558
|
+
`llm-deepseek: catalog model "${model.id}" maxTokens must be a positive integer`
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
if (seen.has(model.id)) throw new Error(`llm-deepseek: duplicate catalog model "${model.id}"`);
|
|
562
|
+
seen.add(model.id);
|
|
563
|
+
return {
|
|
564
|
+
id: model.id,
|
|
565
|
+
...model.name === void 0 ? {} : { name: model.name },
|
|
566
|
+
...model.description === void 0 ? {} : { description: model.description },
|
|
567
|
+
...model.contextWindow === void 0 ? {} : { contextWindow: model.contextWindow },
|
|
568
|
+
...model.maxTokens === void 0 ? {} : { maxTokens: model.maxTokens }
|
|
569
|
+
};
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
function resolveAdapterOptions(config, environment) {
|
|
573
|
+
if (config.thinking === "disabled" && config.reasoningEffort !== void 0 && config.reasoningEffort !== "off") {
|
|
574
|
+
throw new Error('llm-deepseek: only reasoningEffort "off" can be configured when thinking is disabled');
|
|
575
|
+
}
|
|
576
|
+
if (config.defaultContextWindow !== void 0 && (!Number.isInteger(config.defaultContextWindow) || config.defaultContextWindow <= 0)) {
|
|
577
|
+
throw new Error("llm-deepseek: defaultContextWindow must be a positive integer");
|
|
578
|
+
}
|
|
579
|
+
if (config.maxTokens !== void 0 && (!Number.isSafeInteger(config.maxTokens) || config.maxTokens <= 0)) {
|
|
580
|
+
throw new Error("llm-deepseek: maxTokens must be a positive safe integer");
|
|
581
|
+
}
|
|
582
|
+
const streamIdleTimeoutMs = config.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;
|
|
583
|
+
if (!Number.isFinite(streamIdleTimeoutMs) || streamIdleTimeoutMs <= 0 || streamIdleTimeoutMs > MAX_TIMER_DELAY_MS) {
|
|
584
|
+
throw new Error(
|
|
585
|
+
`llm-deepseek: streamIdleTimeoutMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
return {
|
|
589
|
+
apiKeyEnv: credentialRef(config.apiKeyEnv ?? DEFAULT_API_KEY_ENV),
|
|
590
|
+
baseURL: config.baseURL ?? environment?.get(BASE_URL_ENV)?.value ?? PUBLIC_BASE_URL,
|
|
591
|
+
defaults: {
|
|
592
|
+
thinking: config.thinking,
|
|
593
|
+
reasoningEffort: config.reasoningEffort
|
|
594
|
+
},
|
|
595
|
+
maxTokens: config.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
596
|
+
defaultContextWindow: config.defaultContextWindow ?? DEFAULT_CONTEXT_WINDOW,
|
|
597
|
+
models: resolveModels(config.models),
|
|
598
|
+
streamIdleTimeoutMs,
|
|
599
|
+
retryPolicy: resolveRetryPolicy(config.retryPolicy, "llm-deepseek: retryPolicy")
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
function apply(ctx, config) {
|
|
603
|
+
let current = () => config;
|
|
604
|
+
let lastRaw;
|
|
605
|
+
let lastGood;
|
|
606
|
+
const options = () => {
|
|
607
|
+
const raw = current();
|
|
608
|
+
if (raw === lastRaw && lastGood !== void 0) return lastGood;
|
|
609
|
+
try {
|
|
610
|
+
const next = resolveAdapterOptions(raw, launchEnvironmentOf(ctx));
|
|
611
|
+
lastRaw = raw;
|
|
612
|
+
lastGood = next;
|
|
613
|
+
return next;
|
|
614
|
+
} catch (error) {
|
|
615
|
+
if (lastGood === void 0) throw error;
|
|
616
|
+
lastRaw = raw;
|
|
617
|
+
ctx.logger.error("llm-deepseek: keeping the last good configuration after an invalid settings section");
|
|
618
|
+
ctx.logger.error(error);
|
|
619
|
+
return lastGood;
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
options();
|
|
623
|
+
const resolveApiKey = async (connection) => {
|
|
624
|
+
const ref = connection.apiKeyEnv;
|
|
625
|
+
const credentials = ctx.get("credentials");
|
|
626
|
+
if (credentials !== void 0) {
|
|
627
|
+
const hit = await credentials.resolve(ref);
|
|
628
|
+
if (hit !== void 0) return assertUsableApiKey(hit.value, "llm-deepseek", ref);
|
|
629
|
+
} else {
|
|
630
|
+
const ambient = launchEnvironmentOf(ctx).get(ref);
|
|
631
|
+
if (ambient !== void 0 && ambient.value.length > 0) {
|
|
632
|
+
return assertUsableApiKey(ambient.value, "llm-deepseek", ref);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
throw new LlmError5(
|
|
636
|
+
`llm-deepseek: no API key for provider route "${PROVIDER}"; store ${ref} through the credentials service (the web Models page writes it), or export ${ref} in the launching environment`,
|
|
637
|
+
"MISSING_CREDENTIAL"
|
|
638
|
+
);
|
|
639
|
+
};
|
|
640
|
+
let userId;
|
|
641
|
+
const resolveUserId = () => userId ??= getOrCreateAnonymousUserId();
|
|
642
|
+
const adapter = new DeepSeekAdapter({ options, resolveApiKey, resolveUserId });
|
|
643
|
+
ctx.llm.registerConfigurableProviders([
|
|
644
|
+
{ provider: PROVIDER, displayName: "DeepSeek", settingsNs: NS, settingsPath: [] }
|
|
645
|
+
]);
|
|
646
|
+
const registration = ctx.llm.registerAdapter([PROVIDER], adapter);
|
|
647
|
+
let registeredPolicy = options().retryPolicy;
|
|
648
|
+
const ensureRegistrationFacts = () => {
|
|
649
|
+
const policy = options().retryPolicy;
|
|
650
|
+
if (deepEqualJson(policy, registeredPolicy)) return;
|
|
651
|
+
registration.replace([PROVIDER]);
|
|
652
|
+
registeredPolicy = policy;
|
|
653
|
+
};
|
|
654
|
+
installSettingsSection(ctx, NS, Config, config, {
|
|
655
|
+
setSource: (source) => {
|
|
656
|
+
current = source;
|
|
657
|
+
},
|
|
658
|
+
onChange: ensureRegistrationFacts
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
export {
|
|
662
|
+
Config,
|
|
663
|
+
DEFAULT_CONTEXT_WINDOW,
|
|
664
|
+
DEFAULT_MAX_TOKENS,
|
|
665
|
+
DEFAULT_STREAM_IDLE_TIMEOUT_MS,
|
|
666
|
+
DeepSeekAdapter,
|
|
667
|
+
PUBLIC_BASE_URL,
|
|
668
|
+
apply,
|
|
669
|
+
inject,
|
|
670
|
+
name,
|
|
671
|
+
resolveAdapterOptions
|
|
672
|
+
};
|