@deepseek-ai/dsh-llm 0.1.7-alpha.2 → 0.1.7-rc.2
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.i18n.yaml +63 -5
- package/README.md +5 -3
- package/README.zh.md +5 -3
- package/lib/index.js +107 -12
- package/lib/typert.host.js +16 -20
- package/lib/typert.remote-client.js +3 -3
- package/lib/types/content.d.ts +19 -1
- package/lib/types/content.js +107 -0
- package/lib/types/error.d.ts +2 -0
- package/lib/types/error.js +2 -0
- package/lib/types/index.d.ts +8 -4
- package/lib/types/index.js +26 -9
- package/lib/types/types.d.ts +29 -4
- package/package.json +8 -8
package/README.i18n.yaml
CHANGED
|
@@ -1,6 +1,64 @@
|
|
|
1
|
-
# Bilingual-pair consistency record (docs/i18n/README.md):
|
|
2
|
-
#
|
|
3
|
-
#
|
|
1
|
+
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
2
|
+
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
3
|
+
# After editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/llm/llm/README.md
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/:
|
|
6
|
+
en: 860509fb08c860f4
|
|
7
|
+
zh: b2c4448e8afc1f12
|
|
8
|
+
/deepseek-ai-dsh-llm:
|
|
9
|
+
en: 919467ab4b4ef583
|
|
10
|
+
zh: cb5752f140e58813
|
|
11
|
+
/deepseek-ai-dsh-llm/summary:
|
|
12
|
+
en: 9b9ea6fea3088244
|
|
13
|
+
zh: 09f2eb6606a030da
|
|
14
|
+
/deepseek-ai-dsh-llm/table-of-contents:
|
|
15
|
+
en: d152484eb41ac6b4
|
|
16
|
+
zh: 09388d293f9be9cb
|
|
17
|
+
/deepseek-ai-dsh-llm/use-this-package:
|
|
18
|
+
en: 33738e61ce410ac0
|
|
19
|
+
zh: 363760460f4d4bed
|
|
20
|
+
/deepseek-ai-dsh-llm/use-this-package/when-to-choose-it:
|
|
21
|
+
en: c3ecb5a1421f27db
|
|
22
|
+
zh: 4bbd3c0e513845e1
|
|
23
|
+
/deepseek-ai-dsh-llm/use-this-package/minimal-composition:
|
|
24
|
+
en: 7550d716b90fcb09
|
|
25
|
+
zh: 77891a44ee623c7a
|
|
26
|
+
/deepseek-ai-dsh-llm/use-this-package/what-you-can-do:
|
|
27
|
+
en: b45d7a414141734e
|
|
28
|
+
zh: a641c8ea3827cee6
|
|
29
|
+
/deepseek-ai-dsh-llm/use-this-package/failures-and-recovery:
|
|
30
|
+
en: 311d8c92447b7094
|
|
31
|
+
zh: 68cf5cb1c3853cc1
|
|
32
|
+
/deepseek-ai-dsh-llm/understand-the-implementation:
|
|
33
|
+
en: 9630d7e26193a512
|
|
34
|
+
zh: 94222c2a487c4b8c
|
|
35
|
+
/deepseek-ai-dsh-llm/understand-the-implementation/design-philosophy:
|
|
36
|
+
en: 12d0444c18a397c7
|
|
37
|
+
zh: 9d4a5468b4bb7fcd
|
|
38
|
+
/deepseek-ai-dsh-llm/understand-the-implementation/source-map:
|
|
39
|
+
en: ae1618577f4e8364
|
|
40
|
+
zh: a6e8ab1563c08dfb
|
|
41
|
+
/deepseek-ai-dsh-llm/understand-the-implementation/main-flow:
|
|
42
|
+
en: 6dc955a0d80f6ca0
|
|
43
|
+
zh: f81dbcaeacd8b269
|
|
44
|
+
/deepseek-ai-dsh-llm/understand-the-implementation/invariants:
|
|
45
|
+
en: 0163a050239248e5
|
|
46
|
+
zh: 885c95bedcbe2ff4
|
|
47
|
+
/deepseek-ai-dsh-llm/further-exploration:
|
|
48
|
+
en: 37e1d696afef8a88
|
|
49
|
+
zh: 81f99c4507663cad
|
|
50
|
+
/deepseek-ai-dsh-llm/model-experience:
|
|
51
|
+
en: fa5677003ad6bc0a
|
|
52
|
+
zh: ba33cfc860d9c37c
|
|
53
|
+
/deepseek-ai-dsh-llm/model-experience/kv-cache-effect:
|
|
54
|
+
en: a81634136baef72f
|
|
55
|
+
zh: b92dda883986b0e1
|
|
56
|
+
/deepseek-ai-dsh-llm/known-limitations-and-deferred-work:
|
|
57
|
+
en: d60b9121545c99ec
|
|
58
|
+
zh: 3d4434a0e427470b
|
|
59
|
+
/deepseek-ai-dsh-llm/known-limitations-and-deferred-work/dev-note:
|
|
60
|
+
en: ecbc333b88e14d88
|
|
61
|
+
zh: 77c725d92efd8646
|
|
62
|
+
/deepseek-ai-dsh-llm/known-limitations-and-deferred-work/dev-note/open-items:
|
|
63
|
+
en: 6b1a7e903e13ee21
|
|
64
|
+
zh: bb62f2b1cc484bd5
|
package/README.md
CHANGED
|
@@ -25,6 +25,8 @@ Use `@deepseek-ai/dsh-llm` to stream model calls through configured provider ada
|
|
|
25
25
|
<a id="use-this-package"></a>
|
|
26
26
|
## Use this package
|
|
27
27
|
|
|
28
|
+
`listModels` describes models offered by catalog-driven interfaces. Core resolution and streaming can still accept unlisted ids. The GUI requires catalog membership for selection and submission; adapters intended for GUI use must implement `listModels` and advertise their available models. The base implementation returns an empty list and therefore offers no GUI models.
|
|
29
|
+
|
|
28
30
|
Any composition that calls a model provider — an agent loop, a session-title generator, a compaction summarizer — streams its requests through this service. Mount it together with at least one provider adapter; the service itself has no configuration and no provider wire code.
|
|
29
31
|
|
|
30
32
|
### When to choose it
|
|
@@ -37,7 +39,7 @@ Mount the service and at least one adapter, then select the provider by name in
|
|
|
37
39
|
|
|
38
40
|
```yaml
|
|
39
41
|
- name: '@deepseek-ai/dsh-llm'
|
|
40
|
-
- name: '@deepseek-ai/dsh-llm-deepseek'
|
|
42
|
+
- name: '@deepseek-ai/dsh-llm-deepseek-api-key'
|
|
41
43
|
config:
|
|
42
44
|
apiKeyEnv: DEEPSEEK_API_KEY
|
|
43
45
|
```
|
|
@@ -69,7 +71,7 @@ After a successful mount, `ctx.llm.listProviders()` reports the registered route
|
|
|
69
71
|
|
|
70
72
|
### Failures and recovery
|
|
71
73
|
|
|
72
|
-
Every stream ends in exactly one terminal `finish` chunk: `{ kind: 'error', failure }` on failure, `{ kind: 'aborted', failure }` on cancellation. Failures carry stable codes such as `NO_ADAPTER`, `MISSING_CREDENTIAL`, `AUTH`, `RATE_LIMIT`, and `CONTEXT_WINDOW_EXCEEDED`; consumers route on the code, never on message text. A request naming an unregistered provider fails with `NO_ADAPTER`, and a malformed credential fails with `INVALID_CREDENTIAL` instead of surfacing as an opaque fetch error. This service never re-runs a request: retrying is the job of `dsh-llm-retry` at the agent's failed-step extension point.
|
|
74
|
+
Every stream ends in exactly one terminal `finish` chunk: `{ kind: 'error', failure }` on failure, `{ kind: 'aborted', failure }` on cancellation. Failures carry stable codes such as `NO_ADAPTER`, `MISSING_CREDENTIAL`, `AUTH`, `RATE_LIMIT`, and `CONTEXT_WINDOW_EXCEEDED`; consumers route on the code, never on message text. `QUOTA` is provider-neutral exhaustion, while `ACCOUNT_QUOTA` is reserved for a first-party account balance that the current product can replenish. A request naming an unregistered provider fails with `NO_ADAPTER`, and a malformed credential fails with `INVALID_CREDENTIAL` instead of surfacing as an opaque fetch error. This service never re-runs a request: retrying is the job of `dsh-llm-retry` at the agent's failed-step extension point.
|
|
73
75
|
|
|
74
76
|
-----
|
|
75
77
|
|
|
@@ -157,7 +159,7 @@ These limits define where this service stops and other packages or future work b
|
|
|
157
159
|
- **Variants normally require a producer** — `prefill`, per-tool `strict`, block `cache` hints, and the `agent` message-source variant have no producer ([Agent Note](../../../.agents/notes/archived/simplification/2026-07-04-prune-producerless-vocabulary-variants.md)).
|
|
158
160
|
- **`BlockAssembler` handles core block kinds only** — a plugin-added block type whose stream is never closed by `block-end` makes `blocks()` throw.
|
|
159
161
|
- **`GenerateOptions.sessionId` is a locally-declared brand** — importing dsh-session's `SessionId` would create a dependency cycle.
|
|
160
|
-
- **
|
|
162
|
+
- **Tool updates require session history** — `GenerateOptions.tools` contains active definitions. `toolHistory` supplies the initial declarations and historically resolved additions from `Session.toolHistory()`. At adapter dispatch, `projectToolUpdates` constructs deferred declarations and retains removed definitions for `in-history`; `addition-only` omits removed definitions and removal messages. Unsupported routes receive active tools without developer messages or `deferLoading`. Missing history or a request prefix omitting recorded updates falls back to current declarations without developer messages. Explicitly deferred baseline tools remain deferred until their first retained addition block; declaring a deferred tool does not activate it.
|
|
161
163
|
|
|
162
164
|
<a id="dev-note"></a>
|
|
163
165
|
### Dev Note
|
package/README.zh.md
CHANGED
|
@@ -25,6 +25,8 @@ kind: "package-reference"
|
|
|
25
25
|
<a id="use-this-package"></a>
|
|
26
26
|
## 使用本包
|
|
27
27
|
|
|
28
|
+
`listModels` 描述目录驱动界面提供的模型。核心解析与流式调用仍可接受未列出的 ID。GUI 的模型选择与提交要求模型出现在目录中;供 GUI 使用的适配器必须实现 `listModels`,公布其可用模型。基类实现返回空列表,因此不向 GUI 提供模型。
|
|
29
|
+
|
|
28
30
|
任何调用模型提供方的组合——agent loop(智能体循环)、会话标题生成器、压缩(compaction)摘要器——都会通过本服务流式发起请求。与至少一个提供方适配器一起挂载它;服务本身没有任何配置,也不包含提供方协议代码。
|
|
29
31
|
|
|
30
32
|
### 何时选择
|
|
@@ -37,7 +39,7 @@ kind: "package-reference"
|
|
|
37
39
|
|
|
38
40
|
```yaml
|
|
39
41
|
- name: '@deepseek-ai/dsh-llm'
|
|
40
|
-
- name: '@deepseek-ai/dsh-llm-deepseek'
|
|
42
|
+
- name: '@deepseek-ai/dsh-llm-deepseek-api-key'
|
|
41
43
|
config:
|
|
42
44
|
apiKeyEnv: DEEPSEEK_API_KEY
|
|
43
45
|
```
|
|
@@ -69,7 +71,7 @@ for await (const chunk of ctx.llm.stream({
|
|
|
69
71
|
|
|
70
72
|
### 失败与恢复
|
|
71
73
|
|
|
72
|
-
每个流都恰好以一个终止 `finish` 分片结束:失败为 `{ kind: 'error', failure }`,取消为 `{ kind: 'aborted', failure }`。失败携带稳定 code,如 `NO_ADAPTER`、`MISSING_CREDENTIAL`、`AUTH`、`RATE_LIMIT` 与 `CONTEXT_WINDOW_EXCEEDED`;消费方依据 code
|
|
74
|
+
每个流都恰好以一个终止 `finish` 分片结束:失败为 `{ kind: 'error', failure }`,取消为 `{ kind: 'aborted', failure }`。失败携带稳定 code,如 `NO_ADAPTER`、`MISSING_CREDENTIAL`、`AUTH`、`RATE_LIMIT` 与 `CONTEXT_WINDOW_EXCEEDED`;消费方依据 code 路由,绝不解析消息文本。`QUOTA` 表示提供方中立的额度耗尽,`ACCOUNT_QUOTA` 专用于当前产品能够充值的第一方账号余额不足。点名未注册提供方的请求会以 `NO_ADAPTER` 失败,格式错误的凭据会以 `INVALID_CREDENTIAL` 失败,而不是表现为不透明的 fetch 错误。本服务从不自行重跑请求:重试是 `dsh-llm-retry` 在 agent 失败步骤扩展点上的职责。
|
|
73
75
|
|
|
74
76
|
-----
|
|
75
77
|
|
|
@@ -157,7 +159,7 @@ for await (const chunk of ctx.llm.stream({
|
|
|
157
159
|
- **变体通常要求实际产生方**——`prefill`、逐工具 `strict`、内容块 `cache` 提示和 `agent` 消息来源变体都没有产生方(见 [Agent Note](../../../.agents/notes/archived/simplification/2026-07-04-prune-producerless-vocabulary-variants.md))。
|
|
158
160
|
- **`BlockAssembler` 只处理核心块类型**——插件添加块类型的流若从未由 `block-end` 关闭,`blocks()` 会抛出异常。
|
|
159
161
|
- **`GenerateOptions.sessionId` 是本地声明的品牌类型**——导入 dsh-session 的 `SessionId` 会产生依赖循环。
|
|
160
|
-
-
|
|
162
|
+
- **工具更新需要会话历史** — `GenerateOptions.tools` 包含当前有效定义。`toolHistory` 提供 `Session.toolHistory()` 派生的初始声明及已解析历史定义的添加记录。适配器分发时,`projectToolUpdates` 构造延迟声明,并在 `in-history` 模式保留已移除定义;`addition-only` 省略已移除定义和移除消息。不支持更新的路由接收有效工具,不携带 developer 消息或 `deferLoading`。缺少历史或请求前缀遗漏已记录更新时,回退为当前声明且不发送 developer 消息。 显式延迟加载的初始工具在首个保留的添加块出现前保持延迟状态;声明延迟加载工具不会使其激活。
|
|
161
163
|
|
|
162
164
|
<a id="dev-note"></a>
|
|
163
165
|
### 开发备注
|
package/lib/index.js
CHANGED
|
@@ -136,6 +136,8 @@ var HarnessError = class extends Error {
|
|
|
136
136
|
const CONTEXT_WINDOW_EXCEEDED_CODE = "CONTEXT_WINDOW_EXCEEDED";
|
|
137
137
|
/** Canonical provider-neutral code for an exhausted account quota or balance. */
|
|
138
138
|
const QUOTA_EXCEEDED_CODE = "QUOTA";
|
|
139
|
+
/** Account-token quota that can be replenished through the first-party billing page. */
|
|
140
|
+
const ACCOUNT_QUOTA_EXCEEDED_CODE = "ACCOUNT_QUOTA";
|
|
139
141
|
/**
|
|
140
142
|
* Canonical provider-neutral code for a response that completed normally but
|
|
141
143
|
* carried no content blocks at all. Providers occasionally emit a degenerate
|
|
@@ -750,6 +752,89 @@ function projectImagesForTextModel(messages) {
|
|
|
750
752
|
};
|
|
751
753
|
});
|
|
752
754
|
}
|
|
755
|
+
function withoutDeveloperMessages(messages) {
|
|
756
|
+
const retained = messages.filter((message) => message.role !== "developer");
|
|
757
|
+
return retained.length === messages.length ? messages : retained;
|
|
758
|
+
}
|
|
759
|
+
function toolDeclarations(tools, mode, history) {
|
|
760
|
+
const declarations = new Map(history.tools.map((tool) => [tool.name, tool]));
|
|
761
|
+
for (const update of history.updates) for (const tool of update.additions) if (!declarations.has(tool.name)) declarations.set(tool.name, {
|
|
762
|
+
...tool,
|
|
763
|
+
deferLoading: true
|
|
764
|
+
});
|
|
765
|
+
switch (mode) {
|
|
766
|
+
case "in-history": return declarations;
|
|
767
|
+
case "addition-only": {
|
|
768
|
+
const activeNames = new Set(tools?.map((tool) => tool.name));
|
|
769
|
+
for (const name of declarations.keys()) if (!activeNames.has(name)) declarations.delete(name);
|
|
770
|
+
return declarations;
|
|
771
|
+
}
|
|
772
|
+
/* v8 ignore next 2 -- closed-union exhaustiveness guard */
|
|
773
|
+
default: return assertNever(mode);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Construct provider declarations from session-folded history without changing logged active tools.
|
|
778
|
+
* Unsupported routes and incomplete history use current declarations without developer updates.
|
|
779
|
+
* Explicitly deferred baseline tools become available only after their first retained addition.
|
|
780
|
+
* @param messages - complete request inputs, or the prefix selected for an auxiliary call.
|
|
781
|
+
* @param tools - currently active tool schemas.
|
|
782
|
+
* @param toolUpdate - the resolved route's update mode.
|
|
783
|
+
* @param history - immutable state folded from committed headers and developer messages.
|
|
784
|
+
* @returns provider declarations and the corresponding filtered history.
|
|
785
|
+
*/
|
|
786
|
+
function projectToolUpdates(messages, tools, toolUpdate, history) {
|
|
787
|
+
if (toolUpdate === void 0) {
|
|
788
|
+
let immediateTools = tools;
|
|
789
|
+
if (tools?.some((tool) => tool.deferLoading === true)) immediateTools = tools.map(({ deferLoading: _loading, ...tool }) => tool);
|
|
790
|
+
return {
|
|
791
|
+
messages: withoutDeveloperMessages(messages),
|
|
792
|
+
tools: immediateTools
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
if (history === void 0) return {
|
|
796
|
+
messages: withoutDeveloperMessages(messages),
|
|
797
|
+
tools
|
|
798
|
+
};
|
|
799
|
+
const messageIds = new Set(messages.flatMap((message) => message.role === "developer" ? [message.id] : []));
|
|
800
|
+
if (history.updates.some((update) => !messageIds.has(update.messageId))) return {
|
|
801
|
+
messages: withoutDeveloperMessages(messages),
|
|
802
|
+
tools
|
|
803
|
+
};
|
|
804
|
+
const declarations = toolDeclarations(tools, toolUpdate, history);
|
|
805
|
+
const updateIds = new Set(history.updates.map((update) => update.messageId));
|
|
806
|
+
const offered = new Set(history.tools.filter((tool) => !tool.deferLoading).map((tool) => tool.name));
|
|
807
|
+
const projectedMessages = [];
|
|
808
|
+
for (const message of messages) {
|
|
809
|
+
if (message.role !== "developer") {
|
|
810
|
+
projectedMessages.push(message);
|
|
811
|
+
continue;
|
|
812
|
+
}
|
|
813
|
+
if (!updateIds.has(message.id)) continue;
|
|
814
|
+
const content = message.content.filter((block) => {
|
|
815
|
+
switch (block.type) {
|
|
816
|
+
case "tool-addition":
|
|
817
|
+
if (!declarations.has(block.toolName) || offered.has(block.toolName)) return false;
|
|
818
|
+
offered.add(block.toolName);
|
|
819
|
+
return true;
|
|
820
|
+
case "tool-removal":
|
|
821
|
+
if (toolUpdate !== "in-history") return false;
|
|
822
|
+
return offered.delete(block.toolName);
|
|
823
|
+
default: return true;
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
if (content.length === 0) continue;
|
|
827
|
+
if (content.length === message.content.length) projectedMessages.push(message);
|
|
828
|
+
else projectedMessages.push({
|
|
829
|
+
...message,
|
|
830
|
+
content
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
return {
|
|
834
|
+
messages: projectedMessages.length === messages.length && projectedMessages.every((message, index) => message === messages[index]) ? messages : projectedMessages,
|
|
835
|
+
tools: [...declarations.values()]
|
|
836
|
+
};
|
|
837
|
+
}
|
|
753
838
|
//#endregion
|
|
754
839
|
//#region lib/types/attribution.js
|
|
755
840
|
/**
|
|
@@ -1612,8 +1697,9 @@ var LlmAdapter = class {
|
|
|
1612
1697
|
imageRequestPricing(_provider, _model) {}
|
|
1613
1698
|
/**
|
|
1614
1699
|
* List models this adapter can currently advertise for one owned provider.
|
|
1615
|
-
*
|
|
1616
|
-
*
|
|
1700
|
+
* Core routing accepts unlisted model ids; catalog-driven entry points such
|
|
1701
|
+
* as the GUI may require membership. Adapters used there must advertise
|
|
1702
|
+
* their available models; the base empty catalog offers no GUI selection.
|
|
1617
1703
|
* @param _provider - one provider route owned by this adapter.
|
|
1618
1704
|
* @returns discoverable models in adapter-preferred order.
|
|
1619
1705
|
*/
|
|
@@ -1979,7 +2065,8 @@ let LlmRuntime = (() => {
|
|
|
1979
2065
|
}
|
|
1980
2066
|
/**
|
|
1981
2067
|
* Discover models advertised by one registered provider. Catalog membership
|
|
1982
|
-
*
|
|
2068
|
+
* does not constrain core routing. Catalog-driven entry points may restrict
|
|
2069
|
+
* selection and submission to the advertised models.
|
|
1983
2070
|
* @param provider - registered provider route to inspect.
|
|
1984
2071
|
* @returns detached model metadata in adapter-preferred order.
|
|
1985
2072
|
*/
|
|
@@ -2024,6 +2111,8 @@ let LlmRuntime = (() => {
|
|
|
2024
2111
|
const inputModalities = this.detachedModalities(resolved.inputModalities);
|
|
2025
2112
|
const systemPromptUpdate = resolved.systemPromptUpdate;
|
|
2026
2113
|
if (systemPromptUpdate !== void 0 && systemPromptUpdate !== "in-history") throw new LlmError(`adapter returned invalid system prompt update mode for provider "${provider}" model "${model}"`, "INVALID_MODEL_INFO");
|
|
2114
|
+
const toolUpdate = resolved.toolUpdate;
|
|
2115
|
+
if (toolUpdate !== void 0 && toolUpdate !== "in-history" && toolUpdate !== "addition-only") throw new LlmError(`adapter returned invalid tool update mode for provider "${provider}" model "${model}"`, "INVALID_MODEL_INFO");
|
|
2027
2116
|
const defaultMaxTokens = resolved.defaultMaxTokens;
|
|
2028
2117
|
if (defaultMaxTokens !== void 0 && (!Number.isSafeInteger(defaultMaxTokens) || defaultMaxTokens <= 0)) throw new LlmError(`adapter returned invalid default maxTokens for provider "${provider}" model "${model}"`, "INVALID_MODEL_MAX_TOKENS");
|
|
2029
2118
|
const info = {
|
|
@@ -2034,7 +2123,8 @@ let LlmRuntime = (() => {
|
|
|
2034
2123
|
...inputModalities === void 0 ? {} : { inputModalities },
|
|
2035
2124
|
...context === void 0 ? {} : { context: { contextWindow: context.contextWindow } },
|
|
2036
2125
|
...defaultMaxTokens === void 0 ? {} : { defaultMaxTokens },
|
|
2037
|
-
...resolved.systemPromptUpdate === void 0 ? {} : { systemPromptUpdate: resolved.systemPromptUpdate }
|
|
2126
|
+
...resolved.systemPromptUpdate === void 0 ? {} : { systemPromptUpdate: resolved.systemPromptUpdate },
|
|
2127
|
+
...resolved.toolUpdate === void 0 ? {} : { toolUpdate: resolved.toolUpdate }
|
|
2038
2128
|
};
|
|
2039
2129
|
const reasoning = resolved.reasoning;
|
|
2040
2130
|
if (reasoning === void 0) return info;
|
|
@@ -2129,6 +2219,7 @@ let LlmRuntime = (() => {
|
|
|
2129
2219
|
...context === void 0 ? {} : { context },
|
|
2130
2220
|
...modelInfo.inputModalities === void 0 ? {} : { inputModalities: Object.freeze([...modelInfo.inputModalities]) },
|
|
2131
2221
|
...modelInfo.systemPromptUpdate === void 0 ? {} : { systemPromptUpdate: modelInfo.systemPromptUpdate },
|
|
2222
|
+
...modelInfo.toolUpdate === void 0 ? {} : { toolUpdate: modelInfo.toolUpdate },
|
|
2132
2223
|
stream: (options) => {
|
|
2133
2224
|
if (dispatched) throw new LlmError("a prepared LLM call can only be dispatched once", "INVALID_PREPARED_CALL");
|
|
2134
2225
|
if (!callConfigEquals(options, resolvedConfig)) throw new LlmError("prepared LLM call config changed before adapter dispatch", "INVALID_PREPARED_CALL");
|
|
@@ -2218,13 +2309,17 @@ let LlmRuntime = (() => {
|
|
|
2218
2309
|
let projectedMessages = resolvedOptions.messages;
|
|
2219
2310
|
if (projectedMessages.some((message) => contentHasFile(message.content))) projectedMessages = projectFilesToText(projectedMessages, (ref) => this.fileReadPath(ref));
|
|
2220
2311
|
if (modelInfo.inputModalities !== void 0 && !modelInfo.inputModalities.includes("image") && projectedMessages.some((message) => contentHasImage(message.content))) projectedMessages = projectImagesForTextModel(projectedMessages);
|
|
2221
|
-
const
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2312
|
+
const projectedTools = projectToolUpdates(projectedMessages, resolvedOptions.tools, modelInfo.toolUpdate, resolvedOptions.toolHistory);
|
|
2313
|
+
projectedMessages = projectedTools.messages;
|
|
2314
|
+
let projectedOptions = resolvedOptions;
|
|
2315
|
+
if (projectedMessages !== resolvedOptions.messages || projectedTools.tools !== resolvedOptions.tools) {
|
|
2316
|
+
projectedOptions = {
|
|
2317
|
+
...resolvedOptions,
|
|
2318
|
+
messages: projectedMessages,
|
|
2319
|
+
...projectedTools.tools === void 0 ? {} : { tools: projectedTools.tools }
|
|
2320
|
+
};
|
|
2321
|
+
if (Object.isFrozen(resolvedOptions)) deepFreeze(projectedOptions);
|
|
2322
|
+
}
|
|
2228
2323
|
iterator = dispatch(this.forAdapter(projectedOptions, adapter))[Symbol.asyncIterator]();
|
|
2229
2324
|
} catch (error) {
|
|
2230
2325
|
yield adapterFailureChunk(error, options.signal);
|
|
@@ -2292,4 +2387,4 @@ function adapterFailureChunk(error, signal) {
|
|
|
2292
2387
|
};
|
|
2293
2388
|
}
|
|
2294
2389
|
//#endregion
|
|
2295
|
-
export { APP_IDENTITY, AssistantStreamAccumulator, BlockAssembler, CONTEXT_SUMMARY_MAX_CHARS, CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, HarnessError, IMAGE_OFFLOAD_REQUIRED_CODE, INVALID_CREDENTIAL_CODE, LlmAdapter, LlmAttemptId, LlmError, LlmRuntime, LlmRuntime as default, MessageId, ProviderRequestId, QUOTA_EXCEEDED_CODE, ReasoningEffortId, RetryPolicySchema, ToolCallId, assembleAssistantStream, assertUsableApiKey, assistantStreamChunks, assistantStreamFirstTokenTime, assistantStreamHasVisibleContent, assistantStreamHasVisibleText, attributionHeaders, boundContextSummary, callConfigEquals, chunkHasVisibleText, contentHasFile, contentHasImage, createAssistantMessage, createDeveloperMessage, createMessage, createSystemMessage, createToolResultMessage, createUserMessage, errorChain, expandAssistantStream, fileHandleText, freezeMessage, isAgentLoopRequest, isContextWindowExceededError, isHarnessError, isQuotaExceededError, isTokenDelta, isVisibleChunk, joinAssistantStreamText, lastAssistantStreamChunk, markAgentLoopRequest, normalizeApiKey, offloadedImageText, projectFilesToText, projectImagesForTextModel, projectOffloadedImages, requestImageHandleText, requiredImageOffload, resolveImageAttachmentAccess, resolveRetryPolicy, runFirstTokenTime, runFirstVisibleTime, textOnlyImageText, userAgent };
|
|
2390
|
+
export { ACCOUNT_QUOTA_EXCEEDED_CODE, APP_IDENTITY, AssistantStreamAccumulator, BlockAssembler, CONTEXT_SUMMARY_MAX_CHARS, CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, HarnessError, IMAGE_OFFLOAD_REQUIRED_CODE, INVALID_CREDENTIAL_CODE, LlmAdapter, LlmAttemptId, LlmError, LlmRuntime, LlmRuntime as default, MessageId, ProviderRequestId, QUOTA_EXCEEDED_CODE, ReasoningEffortId, RetryPolicySchema, ToolCallId, assembleAssistantStream, assertUsableApiKey, assistantStreamChunks, assistantStreamFirstTokenTime, assistantStreamHasVisibleContent, assistantStreamHasVisibleText, attributionHeaders, boundContextSummary, callConfigEquals, chunkHasVisibleText, contentHasFile, contentHasImage, createAssistantMessage, createDeveloperMessage, createMessage, createSystemMessage, createToolResultMessage, createUserMessage, errorChain, expandAssistantStream, fileHandleText, freezeMessage, isAgentLoopRequest, isContextWindowExceededError, isHarnessError, isQuotaExceededError, isTokenDelta, isVisibleChunk, joinAssistantStreamText, lastAssistantStreamChunk, markAgentLoopRequest, normalizeApiKey, offloadedImageText, projectFilesToText, projectImagesForTextModel, projectOffloadedImages, projectToolUpdates, requestImageHandleText, requiredImageOffload, resolveImageAttachmentAccess, resolveRetryPolicy, runFirstTokenTime, runFirstVisibleTime, textOnlyImageText, userAgent };
|
package/lib/typert.host.js
CHANGED
|
@@ -74,7 +74,7 @@ export const TYPERT = {
|
|
|
74
74
|
typeSymbol: '@deepseek-ai/dsh-llm#llm/discoverModels:result',
|
|
75
75
|
create: _deepseek_ai_dsh_llm_llm_discoverModels_result$schema,
|
|
76
76
|
},
|
|
77
|
-
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":
|
|
77
|
+
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":638,"column":9},
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
id: '@deepseek-ai/dsh-llm#llm/listConfigurableProviders',
|
|
@@ -89,7 +89,7 @@ export const TYPERT = {
|
|
|
89
89
|
typeSymbol: '@deepseek-ai/dsh-llm#llm/listConfigurableProviders:result',
|
|
90
90
|
create: _deepseek_ai_dsh_llm_llm_listConfigurableProviders_result$schema,
|
|
91
91
|
},
|
|
92
|
-
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":
|
|
92
|
+
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":550,"column":3},
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
id: '@deepseek-ai/dsh-llm#llm/listProviders',
|
|
@@ -104,7 +104,7 @@ export const TYPERT = {
|
|
|
104
104
|
typeSymbol: '@deepseek-ai/dsh-llm#llm/listProviders:result',
|
|
105
105
|
create: _deepseek_ai_dsh_llm_llm_listProviders_result$schema,
|
|
106
106
|
},
|
|
107
|
-
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":
|
|
107
|
+
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":478,"column":3},
|
|
108
108
|
},
|
|
109
109
|
],
|
|
110
110
|
model: {
|
|
@@ -192,7 +192,7 @@ export const TYPERT = {
|
|
|
192
192
|
"name": "listModels",
|
|
193
193
|
"signature": "async listModels(provider: string): Promise<LlmModelInfo[]>",
|
|
194
194
|
"summary": "Discover models advertised by one registered provider.",
|
|
195
|
-
"jsDoc": "/**\n * Discover models advertised by one registered provider. Catalog membership\n *
|
|
195
|
+
"jsDoc": "/**\n * Discover models advertised by one registered provider. Catalog membership\n * does not constrain core routing. Catalog-driven entry points may restrict\n * selection and submission to the advertised models.\n * @param provider - registered provider route to inspect.\n * @returns detached model metadata in adapter-preferred order.\n */"
|
|
196
196
|
},
|
|
197
197
|
{
|
|
198
198
|
"kind": "method",
|
|
@@ -310,7 +310,7 @@ export const TYPERT = {
|
|
|
310
310
|
},
|
|
311
311
|
{
|
|
312
312
|
"name": "GenerateOptions",
|
|
313
|
-
"declaration": "export interface GenerateOptions {\n provider: string;\n model: string;\n reasoningEffort?: ReasoningEffortId;\n messages: RequestMessage[];\n system?: string;\n tools?: ToolSchema[];\n temperature?: number;\n maxTokens?: number;\n stop?: string[];\n signal?: AbortSignal;\n sessionId?: Branded<'SessionId'>;\n purpose?: 'compaction' | 'session-title';\n}"
|
|
313
|
+
"declaration": "export interface GenerateOptions {\n provider: string;\n model: string;\n reasoningEffort?: ReasoningEffortId;\n messages: RequestMessage[];\n system?: string;\n tools?: ToolSchema[];\n toolHistory?: ToolHistory;\n temperature?: number;\n maxTokens?: number;\n stop?: string[];\n signal?: AbortSignal;\n sessionId?: Branded<'SessionId'>;\n purpose?: 'compaction' | 'session-title';\n}"
|
|
314
314
|
},
|
|
315
315
|
{
|
|
316
316
|
"name": "GoalId",
|
|
@@ -390,7 +390,7 @@ export const TYPERT = {
|
|
|
390
390
|
},
|
|
391
391
|
{
|
|
392
392
|
"name": "LlmResolvedModelInfo",
|
|
393
|
-
"declaration": "export interface LlmResolvedModelInfo extends LlmModelInfo {\n context?: LlmModelContext;\n defaultMaxTokens?: number;\n reasoning?: LlmModelReasoningInfo;\n systemPromptUpdate?: SystemPromptUpdate;\n}"
|
|
393
|
+
"declaration": "export interface LlmResolvedModelInfo extends LlmModelInfo {\n context?: LlmModelContext;\n defaultMaxTokens?: number;\n reasoning?: LlmModelReasoningInfo;\n systemPromptUpdate?: SystemPromptUpdate;\n toolUpdate?: ToolUpdate;\n}"
|
|
394
394
|
},
|
|
395
395
|
{
|
|
396
396
|
"name": "Message",
|
|
@@ -414,7 +414,7 @@ export const TYPERT = {
|
|
|
414
414
|
},
|
|
415
415
|
{
|
|
416
416
|
"name": "MessageSourceMap",
|
|
417
|
-
"declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n model: ModelMessageSource;\n tool: ToolMessageSource;\n 'system-prompt': SystemPromptMessageSource;\n 'model-selection': { kind: 'model-selection'; } & ContextFormed;\n 'user-approval': { kind: 'user-approval'; } & ContextFormed;\n 'ptc-mode': { kind: 'ptc-mode'; };\n 'tool-registry': { kind: 'tool-registry'; };\n 'user-rpc': { kind: 'user'; rpcId: SessionRequestId; clientTimeZone?: string; };\n 'agent-message': AgentMessageSource;\n 'subagent-settled': SubagentSettledMessageSource;\n 'skill-invocation': SkillInvocationSource;\n 'cordis-host-runner': { kind: 'cordis-host-runner'; };\n
|
|
417
|
+
"declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n model: ModelMessageSource;\n tool: ToolMessageSource;\n 'system-prompt': SystemPromptMessageSource;\n 'model-selection': { kind: 'model-selection'; } & ContextFormed;\n 'user-approval': { kind: 'user-approval'; } & ContextFormed;\n 'ptc-mode': { kind: 'ptc-mode'; };\n 'tool-registry': { kind: 'tool-registry'; };\n 'user-rpc': { kind: 'user'; rpcId: SessionRequestId; clientTimeZone?: string; };\n 'agent-message': AgentMessageSource;\n 'subagent-settled': SubagentSettledMessageSource;\n 'skill-invocation': SkillInvocationSource;\n 'cordis-host-runner': { kind: 'cordis-host-runner'; };\n goal: GoalMessageSource;\n schedule: { kind: 'schedule'; } & ContextFormed;\n 'compact-checkpoint': CompactionCheckpointSource;\n 'session-reference': SessionReferenceSource;\n}"
|
|
418
418
|
},
|
|
419
419
|
{
|
|
420
420
|
"name": "ModelMessageSource",
|
|
@@ -438,7 +438,7 @@ export const TYPERT = {
|
|
|
438
438
|
},
|
|
439
439
|
{
|
|
440
440
|
"name": "PreparedLlmCall",
|
|
441
|
-
"declaration": "export interface PreparedLlmCall {\n readonly config: LlmCallConfig;\n readonly retryPolicy: ResolvedRetryPolicy;\n readonly context?: LlmModelContext;\n readonly inputModalities?: readonly ModelModality[];\n readonly systemPromptUpdate?: SystemPromptUpdate;\n readonly adapterDefaults: LlmCallConfigAdapterDefaults;\n stream(options: GenerateOptions): AsyncIterable<StreamChunk>;\n}"
|
|
441
|
+
"declaration": "export interface PreparedLlmCall {\n readonly config: LlmCallConfig;\n readonly retryPolicy: ResolvedRetryPolicy;\n readonly context?: LlmModelContext;\n readonly inputModalities?: readonly ModelModality[];\n readonly systemPromptUpdate?: SystemPromptUpdate;\n readonly toolUpdate?: ToolUpdate;\n readonly adapterDefaults: LlmCallConfigAdapterDefaults;\n stream(options: GenerateOptions): AsyncIterable<StreamChunk>;\n}"
|
|
442
442
|
},
|
|
443
443
|
{
|
|
444
444
|
"name": "ProviderRequestId",
|
|
@@ -520,18 +520,6 @@ export const TYPERT = {
|
|
|
520
520
|
"name": "SystemPromptUpdate",
|
|
521
521
|
"declaration": "export type SystemPromptUpdate = 'in-history';"
|
|
522
522
|
},
|
|
523
|
-
{
|
|
524
|
-
"name": "TeamId",
|
|
525
|
-
"declaration": "export type TeamId = Branded<'TeamId'>;"
|
|
526
|
-
},
|
|
527
|
-
{
|
|
528
|
-
"name": "TeamMessageId",
|
|
529
|
-
"declaration": "export type TeamMessageId = Branded<'TeamMessageId'>;"
|
|
530
|
-
},
|
|
531
|
-
{
|
|
532
|
-
"name": "TeamMessageSource",
|
|
533
|
-
"declaration": "export interface TeamMessageSource {\n readonly kind: 'team-message';\n readonly teamId: TeamId;\n readonly messageId: TeamMessageId;\n readonly senderId: SessionId;\n readonly senderName: string;\n}"
|
|
534
|
-
},
|
|
535
523
|
{
|
|
536
524
|
"name": "TextBlock",
|
|
537
525
|
"declaration": "export interface TextBlock {\n type: 'text';\n text: string;\n}"
|
|
@@ -552,6 +540,10 @@ export const TYPERT = {
|
|
|
552
540
|
"name": "ToolCallId",
|
|
553
541
|
"declaration": "export type ToolCallId = Branded<'ToolCallId'>;"
|
|
554
542
|
},
|
|
543
|
+
{
|
|
544
|
+
"name": "ToolHistory",
|
|
545
|
+
"declaration": "export interface ToolHistory {\n readonly tools: readonly ToolSchema[];\n readonly updates: readonly { readonly messageId: MessageId; readonly additions: readonly ToolSchema[]; }[];\n}"
|
|
546
|
+
},
|
|
555
547
|
{
|
|
556
548
|
"name": "ToolMessageSource",
|
|
557
549
|
"declaration": "export interface ToolMessageSource {\n kind: 'tool';\n callId: ToolCallId;\n}"
|
|
@@ -568,6 +560,10 @@ export const TYPERT = {
|
|
|
568
560
|
"name": "ToolSchema",
|
|
569
561
|
"declaration": "export interface ToolSchema {\n deferLoading?: true;\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n}"
|
|
570
562
|
},
|
|
563
|
+
{
|
|
564
|
+
"name": "ToolUpdate",
|
|
565
|
+
"declaration": "export type ToolUpdate = 'in-history' | 'addition-only';"
|
|
566
|
+
},
|
|
571
567
|
{
|
|
572
568
|
"name": "UserMessage",
|
|
573
569
|
"declaration": "export interface UserMessage extends MessageBase {\n readonly role: 'user';\n}"
|
|
@@ -71,7 +71,7 @@ export const TYPERT_REMOTE = {
|
|
|
71
71
|
typeSymbol: '@deepseek-ai/dsh-llm#llm/discoverModels:result',
|
|
72
72
|
create: _deepseek_ai_dsh_llm_llm_discoverModels_result$schema,
|
|
73
73
|
},
|
|
74
|
-
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":
|
|
74
|
+
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":638,"column":9},
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
77
|
id: '@deepseek-ai/dsh-llm#llm/listConfigurableProviders',
|
|
@@ -86,7 +86,7 @@ export const TYPERT_REMOTE = {
|
|
|
86
86
|
typeSymbol: '@deepseek-ai/dsh-llm#llm/listConfigurableProviders:result',
|
|
87
87
|
create: _deepseek_ai_dsh_llm_llm_listConfigurableProviders_result$schema,
|
|
88
88
|
},
|
|
89
|
-
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":
|
|
89
|
+
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":550,"column":3},
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
id: '@deepseek-ai/dsh-llm#llm/listProviders',
|
|
@@ -101,7 +101,7 @@ export const TYPERT_REMOTE = {
|
|
|
101
101
|
typeSymbol: '@deepseek-ai/dsh-llm#llm/listProviders:result',
|
|
102
102
|
create: _deepseek_ai_dsh_llm_llm_listProviders_result$schema,
|
|
103
103
|
},
|
|
104
|
-
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":
|
|
104
|
+
sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":478,"column":3},
|
|
105
105
|
},
|
|
106
106
|
],
|
|
107
107
|
}
|
package/lib/types/content.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Content-block structure helpers. @module @deepseek-ai/dsh-llm/content */
|
|
2
|
-
import type { ContentBlock, ImageBlock, LlmImageRequestBudget } from './types.ts';
|
|
2
|
+
import type { ContentBlock, ImageBlock, LlmImageRequestBudget, ToolSchema, ToolUpdate, ToolHistory } from './types.ts';
|
|
3
3
|
import type { RequestMessage } from './types.ts';
|
|
4
4
|
import type { Message } from './message.ts';
|
|
5
5
|
import type { AttachmentStore, FileAttachmentRef, ImageAttachmentRef, RequestImageAttachment } from '@deepseek-ai/dsh-attachment';
|
|
@@ -128,4 +128,22 @@ export declare function projectImagesForTextModel(messages: readonly Message[]):
|
|
|
128
128
|
* @returns original inputs without images, otherwise copies with stable placeholders.
|
|
129
129
|
*/
|
|
130
130
|
export declare function projectImagesForTextModel(messages: readonly RequestMessage[]): readonly RequestMessage[];
|
|
131
|
+
/** Request messages and tools after one route's tool update projection. */
|
|
132
|
+
export interface ProjectedToolUpdates {
|
|
133
|
+
/** History with only the developer updates supported by this route and declaration series. */
|
|
134
|
+
readonly messages: readonly RequestMessage[];
|
|
135
|
+
/** Provider declarations, including deferred and retained definitions when supported. */
|
|
136
|
+
readonly tools: readonly ToolSchema[] | undefined;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Construct provider declarations from session-folded history without changing logged active tools.
|
|
140
|
+
* Unsupported routes and incomplete history use current declarations without developer updates.
|
|
141
|
+
* Explicitly deferred baseline tools become available only after their first retained addition.
|
|
142
|
+
* @param messages - complete request inputs, or the prefix selected for an auxiliary call.
|
|
143
|
+
* @param tools - currently active tool schemas.
|
|
144
|
+
* @param toolUpdate - the resolved route's update mode.
|
|
145
|
+
* @param history - immutable state folded from committed headers and developer messages.
|
|
146
|
+
* @returns provider declarations and the corresponding filtered history.
|
|
147
|
+
*/
|
|
148
|
+
export declare function projectToolUpdates(messages: readonly RequestMessage[], tools: readonly ToolSchema[] | undefined, toolUpdate: ToolUpdate | undefined, history?: ToolHistory): ProjectedToolUpdates;
|
|
131
149
|
//# sourceMappingURL=content.d.ts.map
|
package/lib/types/content.js
CHANGED
|
@@ -245,4 +245,111 @@ export function projectImagesForTextModel(messages) {
|
|
|
245
245
|
return content === message.content ? message : { ...message, content };
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
|
+
function withoutDeveloperMessages(messages) {
|
|
249
|
+
const retained = messages.filter(message => message.role !== 'developer');
|
|
250
|
+
return retained.length === messages.length ? messages : retained;
|
|
251
|
+
}
|
|
252
|
+
function toolDeclarations(tools, mode, history) {
|
|
253
|
+
const declarations = new Map(history.tools.map(tool => [tool.name, tool]));
|
|
254
|
+
for (const update of history.updates) {
|
|
255
|
+
for (const tool of update.additions) {
|
|
256
|
+
if (!declarations.has(tool.name)) {
|
|
257
|
+
// Later additions activate these definitions at their recorded position.
|
|
258
|
+
declarations.set(tool.name, { ...tool, deferLoading: true });
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
switch (mode) {
|
|
263
|
+
case 'in-history':
|
|
264
|
+
// Removal blocks disable tools without discarding their historical definitions.
|
|
265
|
+
return declarations;
|
|
266
|
+
case 'addition-only': {
|
|
267
|
+
// Without removal support, the declaration list must omit inactive tools.
|
|
268
|
+
const activeNames = new Set(tools?.map(tool => tool.name));
|
|
269
|
+
for (const name of declarations.keys()) {
|
|
270
|
+
if (!activeNames.has(name))
|
|
271
|
+
declarations.delete(name);
|
|
272
|
+
}
|
|
273
|
+
return declarations;
|
|
274
|
+
}
|
|
275
|
+
/* v8 ignore next 2 -- closed-union exhaustiveness guard */
|
|
276
|
+
default:
|
|
277
|
+
return assertNever(mode);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Construct provider declarations from session-folded history without changing logged active tools.
|
|
282
|
+
* Unsupported routes and incomplete history use current declarations without developer updates.
|
|
283
|
+
* Explicitly deferred baseline tools become available only after their first retained addition.
|
|
284
|
+
* @param messages - complete request inputs, or the prefix selected for an auxiliary call.
|
|
285
|
+
* @param tools - currently active tool schemas.
|
|
286
|
+
* @param toolUpdate - the resolved route's update mode.
|
|
287
|
+
* @param history - immutable state folded from committed headers and developer messages.
|
|
288
|
+
* @returns provider declarations and the corresponding filtered history.
|
|
289
|
+
*/
|
|
290
|
+
export function projectToolUpdates(messages, tools, toolUpdate, history) {
|
|
291
|
+
if (toolUpdate === undefined) {
|
|
292
|
+
// Unsupported routes need immediately available tools and no update messages.
|
|
293
|
+
let immediateTools = tools;
|
|
294
|
+
if (tools?.some(tool => tool.deferLoading === true)) {
|
|
295
|
+
immediateTools = tools.map(({ deferLoading: _loading, ...tool }) => tool);
|
|
296
|
+
}
|
|
297
|
+
return { messages: withoutDeveloperMessages(messages), tools: immediateTools };
|
|
298
|
+
}
|
|
299
|
+
if (history === undefined) {
|
|
300
|
+
// Current schemas alone cannot resolve definitions referenced by past updates.
|
|
301
|
+
return { messages: withoutDeveloperMessages(messages), tools };
|
|
302
|
+
}
|
|
303
|
+
const messageIds = new Set(messages.flatMap(message => message.role === 'developer' ? [message.id] : []));
|
|
304
|
+
if (history.updates.some(update => !messageIds.has(update.messageId))) {
|
|
305
|
+
// An auxiliary prefix may omit updates needed to activate historical declarations.
|
|
306
|
+
return { messages: withoutDeveloperMessages(messages), tools };
|
|
307
|
+
}
|
|
308
|
+
const declarations = toolDeclarations(tools, toolUpdate, history);
|
|
309
|
+
const updateIds = new Set(history.updates.map(update => update.messageId));
|
|
310
|
+
// Deferred baseline tools still need their first addition to become available.
|
|
311
|
+
const offered = new Set(history.tools.filter(tool => !tool.deferLoading).map(tool => tool.name));
|
|
312
|
+
const projectedMessages = [];
|
|
313
|
+
for (const message of messages) {
|
|
314
|
+
if (message.role !== 'developer') {
|
|
315
|
+
projectedMessages.push(message);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
// Earlier declaration series do not govern the current tool set.
|
|
319
|
+
if (!updateIds.has(message.id))
|
|
320
|
+
continue;
|
|
321
|
+
const content = message.content.filter((block) => {
|
|
322
|
+
switch (block.type) {
|
|
323
|
+
case 'tool-addition':
|
|
324
|
+
// Only declared tools that are not already available need activation.
|
|
325
|
+
if (!declarations.has(block.toolName) || offered.has(block.toolName))
|
|
326
|
+
return false;
|
|
327
|
+
offered.add(block.toolName);
|
|
328
|
+
return true;
|
|
329
|
+
case 'tool-removal':
|
|
330
|
+
// Addition-only routes cannot deactivate a tool through history.
|
|
331
|
+
if (toolUpdate !== 'in-history')
|
|
332
|
+
return false;
|
|
333
|
+
return offered.delete(block.toolName);
|
|
334
|
+
default:
|
|
335
|
+
// Other core and plugin-defined blocks retain their content and order.
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
if (content.length === 0)
|
|
340
|
+
continue;
|
|
341
|
+
if (content.length === message.content.length) {
|
|
342
|
+
projectedMessages.push(message);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
projectedMessages.push({ ...message, content });
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const unchanged = projectedMessages.length === messages.length
|
|
349
|
+
&& projectedMessages.every((message, index) => message === messages[index]);
|
|
350
|
+
return {
|
|
351
|
+
messages: unchanged ? messages : projectedMessages,
|
|
352
|
+
tools: [...declarations.values()],
|
|
353
|
+
};
|
|
354
|
+
}
|
|
248
355
|
//# sourceMappingURL=content.js.map
|
package/lib/types/error.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export declare class HarnessError extends Error {
|
|
|
18
18
|
export declare const CONTEXT_WINDOW_EXCEEDED_CODE = "CONTEXT_WINDOW_EXCEEDED";
|
|
19
19
|
/** Canonical provider-neutral code for an exhausted account quota or balance. */
|
|
20
20
|
export declare const QUOTA_EXCEEDED_CODE = "QUOTA";
|
|
21
|
+
/** Account-token quota that can be replenished through the first-party billing page. */
|
|
22
|
+
export declare const ACCOUNT_QUOTA_EXCEEDED_CODE = "ACCOUNT_QUOTA";
|
|
21
23
|
/**
|
|
22
24
|
* Canonical provider-neutral code for a response that completed normally but
|
|
23
25
|
* carried no content blocks at all. Providers occasionally emit a degenerate
|
package/lib/types/error.js
CHANGED
|
@@ -22,6 +22,8 @@ export class HarnessError extends Error {
|
|
|
22
22
|
export const CONTEXT_WINDOW_EXCEEDED_CODE = 'CONTEXT_WINDOW_EXCEEDED';
|
|
23
23
|
/** Canonical provider-neutral code for an exhausted account quota or balance. */
|
|
24
24
|
export const QUOTA_EXCEEDED_CODE = 'QUOTA';
|
|
25
|
+
/** Account-token quota that can be replenished through the first-party billing page. */
|
|
26
|
+
export const ACCOUNT_QUOTA_EXCEEDED_CODE = 'ACCOUNT_QUOTA';
|
|
25
27
|
/**
|
|
26
28
|
* Canonical provider-neutral code for a response that completed normally but
|
|
27
29
|
* carried no content blocks at all. Providers occasionally emit a degenerate
|
package/lib/types/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { Context } from '@deepseek-ai/cordis';
|
|
9
9
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
10
|
-
import type { GenerateOptions, LlmConfigurableProvider, LlmDiscoveredModel, LlmFailure, LlmImageRequestPricing, LlmModelContext, LlmModelDiscoveryRequest, LlmModelInfo, LlmResolvedModelInfo, LlmProviderInfo, ModelModality, StreamChunk, SystemPromptUpdate } from './types.ts';
|
|
10
|
+
import type { GenerateOptions, LlmConfigurableProvider, LlmDiscoveredModel, LlmFailure, LlmImageRequestPricing, LlmModelContext, LlmModelDiscoveryRequest, LlmModelInfo, LlmResolvedModelInfo, LlmProviderInfo, ModelModality, StreamChunk, SystemPromptUpdate, ToolUpdate } from './types.ts';
|
|
11
11
|
import type { ResolvedRetryPolicy } from './retry-policy.ts';
|
|
12
12
|
import type { ProviderRequestId } from './brand.ts';
|
|
13
13
|
import type { LlmCallConfig, LlmCallConfigAdapterDefaults } from './call-config.ts';
|
|
@@ -101,6 +101,8 @@ export interface PreparedLlmCall {
|
|
|
101
101
|
readonly inputModalities?: readonly ModelModality[];
|
|
102
102
|
/** Exact model system prompt update mode captured with the adapter dispatch generation. */
|
|
103
103
|
readonly systemPromptUpdate?: SystemPromptUpdate;
|
|
104
|
+
/** Exact model tool update mode captured with the adapter dispatch generation. */
|
|
105
|
+
readonly toolUpdate?: ToolUpdate;
|
|
104
106
|
/** Config fields materialized by the captured adapter rather than proposed by the caller. */
|
|
105
107
|
readonly adapterDefaults: LlmCallConfigAdapterDefaults;
|
|
106
108
|
/**
|
|
@@ -150,8 +152,9 @@ export declare abstract class LlmAdapter {
|
|
|
150
152
|
imageRequestPricing(_provider: string, _model: string): LlmImageRequestPricing | undefined;
|
|
151
153
|
/**
|
|
152
154
|
* List models this adapter can currently advertise for one owned provider.
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
+
* Core routing accepts unlisted model ids; catalog-driven entry points such
|
|
156
|
+
* as the GUI may require membership. Adapters used there must advertise
|
|
157
|
+
* their available models; the base empty catalog offers no GUI selection.
|
|
155
158
|
* @param _provider - one provider route owned by this adapter.
|
|
156
159
|
* @returns discoverable models in adapter-preferred order.
|
|
157
160
|
*/
|
|
@@ -339,7 +342,8 @@ export declare class LlmRuntime extends TypertRemoteService {
|
|
|
339
342
|
private detachedModalities;
|
|
340
343
|
/**
|
|
341
344
|
* Discover models advertised by one registered provider. Catalog membership
|
|
342
|
-
*
|
|
345
|
+
* does not constrain core routing. Catalog-driven entry points may restrict
|
|
346
|
+
* selection and submission to the advertised models.
|
|
343
347
|
* @param provider - registered provider route to inspect.
|
|
344
348
|
* @returns detached model metadata in adapter-preferred order.
|
|
345
349
|
*/
|
package/lib/types/index.js
CHANGED
|
@@ -47,7 +47,7 @@ import { callConfigEquals } from "./call-config.js";
|
|
|
47
47
|
import { HarnessError, INVALID_CREDENTIAL_CODE } from "./error.js";
|
|
48
48
|
import { normalizeLlmFailure } from "./adapter-failure.js";
|
|
49
49
|
import { normalizeApiKey } from "./api-key.js";
|
|
50
|
-
import { contentHasFile, contentHasImage, fileHandleText, projectFilesToText, projectImagesForTextModel, } from "./content.js";
|
|
50
|
+
import { contentHasFile, contentHasImage, fileHandleText, projectFilesToText, projectImagesForTextModel, projectToolUpdates, } from "./content.js";
|
|
51
51
|
export * from "./attribution.js";
|
|
52
52
|
export * from "./brand.js";
|
|
53
53
|
export * from "./error.js";
|
|
@@ -169,8 +169,9 @@ export class LlmAdapter {
|
|
|
169
169
|
}
|
|
170
170
|
/**
|
|
171
171
|
* List models this adapter can currently advertise for one owned provider.
|
|
172
|
-
*
|
|
173
|
-
*
|
|
172
|
+
* Core routing accepts unlisted model ids; catalog-driven entry points such
|
|
173
|
+
* as the GUI may require membership. Adapters used there must advertise
|
|
174
|
+
* their available models; the base empty catalog offers no GUI selection.
|
|
174
175
|
* @param _provider - one provider route owned by this adapter.
|
|
175
176
|
* @returns discoverable models in adapter-preferred order.
|
|
176
177
|
*/
|
|
@@ -547,7 +548,8 @@ let LlmRuntime = (() => {
|
|
|
547
548
|
}
|
|
548
549
|
/**
|
|
549
550
|
* Discover models advertised by one registered provider. Catalog membership
|
|
550
|
-
*
|
|
551
|
+
* does not constrain core routing. Catalog-driven entry points may restrict
|
|
552
|
+
* selection and submission to the advertised models.
|
|
551
553
|
* @param provider - registered provider route to inspect.
|
|
552
554
|
* @returns detached model metadata in adapter-preferred order.
|
|
553
555
|
*/
|
|
@@ -617,6 +619,11 @@ let LlmRuntime = (() => {
|
|
|
617
619
|
if (systemPromptUpdate !== undefined && systemPromptUpdate !== 'in-history') {
|
|
618
620
|
throw new LlmError(`adapter returned invalid system prompt update mode for provider "${provider}" model "${model}"`, 'INVALID_MODEL_INFO');
|
|
619
621
|
}
|
|
622
|
+
// Widened for the same reason: catalog config supplies the tool update mode as text.
|
|
623
|
+
const toolUpdate = resolved.toolUpdate;
|
|
624
|
+
if (toolUpdate !== undefined && toolUpdate !== 'in-history' && toolUpdate !== 'addition-only') {
|
|
625
|
+
throw new LlmError(`adapter returned invalid tool update mode for provider "${provider}" model "${model}"`, 'INVALID_MODEL_INFO');
|
|
626
|
+
}
|
|
620
627
|
const defaultMaxTokens = resolved.defaultMaxTokens;
|
|
621
628
|
if (defaultMaxTokens !== undefined
|
|
622
629
|
&& (!Number.isSafeInteger(defaultMaxTokens) || defaultMaxTokens <= 0)) {
|
|
@@ -631,6 +638,7 @@ let LlmRuntime = (() => {
|
|
|
631
638
|
...context === undefined ? {} : { context: { contextWindow: context.contextWindow } },
|
|
632
639
|
...defaultMaxTokens === undefined ? {} : { defaultMaxTokens },
|
|
633
640
|
...resolved.systemPromptUpdate === undefined ? {} : { systemPromptUpdate: resolved.systemPromptUpdate },
|
|
641
|
+
...resolved.toolUpdate === undefined ? {} : { toolUpdate: resolved.toolUpdate },
|
|
634
642
|
};
|
|
635
643
|
const reasoning = resolved.reasoning;
|
|
636
644
|
if (reasoning === undefined)
|
|
@@ -747,6 +755,7 @@ let LlmRuntime = (() => {
|
|
|
747
755
|
? {}
|
|
748
756
|
: { inputModalities: Object.freeze([...modelInfo.inputModalities]) },
|
|
749
757
|
...modelInfo.systemPromptUpdate === undefined ? {} : { systemPromptUpdate: modelInfo.systemPromptUpdate },
|
|
758
|
+
...modelInfo.toolUpdate === undefined ? {} : { toolUpdate: modelInfo.toolUpdate },
|
|
750
759
|
stream: (options) => {
|
|
751
760
|
if (dispatched) {
|
|
752
761
|
throw new LlmError('a prepared LLM call can only be dispatched once', 'INVALID_PREPARED_CALL');
|
|
@@ -853,11 +862,19 @@ let LlmRuntime = (() => {
|
|
|
853
862
|
&& projectedMessages.some(message => contentHasImage(message.content))) {
|
|
854
863
|
projectedMessages = projectImagesForTextModel(projectedMessages);
|
|
855
864
|
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
865
|
+
// Tool changes are logged on every route; the route's declared mode selects what it receives.
|
|
866
|
+
const projectedTools = projectToolUpdates(projectedMessages, resolvedOptions.tools, modelInfo.toolUpdate, resolvedOptions.toolHistory);
|
|
867
|
+
projectedMessages = projectedTools.messages;
|
|
868
|
+
let projectedOptions = resolvedOptions;
|
|
869
|
+
if (projectedMessages !== resolvedOptions.messages || projectedTools.tools !== resolvedOptions.tools) {
|
|
870
|
+
projectedOptions = {
|
|
871
|
+
...resolvedOptions,
|
|
872
|
+
messages: projectedMessages,
|
|
873
|
+
...projectedTools.tools === undefined ? {} : { tools: projectedTools.tools },
|
|
874
|
+
};
|
|
875
|
+
if (Object.isFrozen(resolvedOptions))
|
|
876
|
+
deepFreeze(projectedOptions);
|
|
877
|
+
}
|
|
861
878
|
const stream = dispatch(this.forAdapter(projectedOptions, adapter));
|
|
862
879
|
iterator = stream[Symbol.asyncIterator]();
|
|
863
880
|
}
|
package/lib/types/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { Branded } from '@deepseek-ai/dsh-brand';
|
|
7
7
|
import type { FileAttachmentRef, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment';
|
|
8
|
-
import type { ToolCallId, ProviderRequestId, ReasoningEffortId } from './brand.ts';
|
|
8
|
+
import type { MessageId, ToolCallId, ProviderRequestId, ReasoningEffortId } from './brand.ts';
|
|
9
9
|
import type { Message, UserMessage } from './message.ts';
|
|
10
10
|
declare module '@deepseek-ai/cordis' {
|
|
11
11
|
interface Events {
|
|
@@ -108,9 +108,8 @@ export interface ToolRemovalBlock {
|
|
|
108
108
|
}
|
|
109
109
|
/**
|
|
110
110
|
* Merge-extensible content blocks keyed by `type`. New core blocks must land
|
|
111
|
-
* with adapter, UI, and compaction support.
|
|
112
|
-
*
|
|
113
|
-
* their producers and consumers are implemented together.
|
|
111
|
+
* with adapter, UI, and compaction support. Tool-change blocks belong to
|
|
112
|
+
* developer messages; `projectToolUpdates` selects what each route receives.
|
|
114
113
|
*/
|
|
115
114
|
export interface ContentBlockMap {
|
|
116
115
|
'text': TextBlock;
|
|
@@ -364,6 +363,16 @@ export interface LlmModelReasoningInfo {
|
|
|
364
363
|
* can follow the cached history instead of rewriting message 0.
|
|
365
364
|
*/
|
|
366
365
|
export type SystemPromptUpdate = 'in-history';
|
|
366
|
+
/**
|
|
367
|
+
* How a model accepts native tool declarations that change mid-conversation.
|
|
368
|
+
* `'addition-only'`: the model reads a `tool-addition` block in a later
|
|
369
|
+
* developer message as activating a tool declared with `deferLoading`, so an
|
|
370
|
+
* added tool follows the cached history instead of rewriting the declaration
|
|
371
|
+
* list. `'in-history'`: the model additionally reads `tool-removal` blocks,
|
|
372
|
+
* so a removed tool keeps its declaration and the removal follows the history.
|
|
373
|
+
* Absent means every request declares the complete current tool list.
|
|
374
|
+
*/
|
|
375
|
+
export type ToolUpdate = 'in-history' | 'addition-only';
|
|
367
376
|
/** Exact-route model metadata resolved by its owning adapter. */
|
|
368
377
|
export interface LlmResolvedModelInfo extends LlmModelInfo {
|
|
369
378
|
/** Provider-owned context capacity when known. */
|
|
@@ -374,6 +383,8 @@ export interface LlmResolvedModelInfo extends LlmModelInfo {
|
|
|
374
383
|
reasoning?: LlmModelReasoningInfo;
|
|
375
384
|
/** Declared mid-conversation system prompt handling; absent means only a leading system message is read. */
|
|
376
385
|
systemPromptUpdate?: SystemPromptUpdate;
|
|
386
|
+
/** Declared mid-conversation tool declaration handling; absent means every request declares the complete tool list. */
|
|
387
|
+
toolUpdate?: ToolUpdate;
|
|
377
388
|
}
|
|
378
389
|
/**
|
|
379
390
|
* Adapter-private lossless-JSON state for replaying a successful response,
|
|
@@ -462,6 +473,18 @@ export interface RequestUserInput {
|
|
|
462
473
|
}
|
|
463
474
|
/** A durable conversation message or a user input used only for one request. */
|
|
464
475
|
export type RequestMessage = Message | RequestUserInput;
|
|
476
|
+
/** Logged tool declarations and update identities since the last declaration reset. */
|
|
477
|
+
export interface ToolHistory {
|
|
478
|
+
/** Complete active declarations at the start of this history. */
|
|
479
|
+
readonly tools: readonly ToolSchema[];
|
|
480
|
+
/** Ordered developer messages, with additions resolved from their historical headers. */
|
|
481
|
+
readonly updates: readonly {
|
|
482
|
+
/** Identity used to locate this update in the derived request history. */
|
|
483
|
+
readonly messageId: MessageId;
|
|
484
|
+
/** Added definitions resolved from the event's referenced request header. */
|
|
485
|
+
readonly additions: readonly ToolSchema[];
|
|
486
|
+
}[];
|
|
487
|
+
}
|
|
465
488
|
/** A single model request, fully assembled. */
|
|
466
489
|
export interface GenerateOptions {
|
|
467
490
|
/** Registered provider route selecting the adapter instance. */
|
|
@@ -483,6 +506,8 @@ export interface GenerateOptions {
|
|
|
483
506
|
system?: string;
|
|
484
507
|
/** Tool schemas (adapters map to the provider's `tools` field). */
|
|
485
508
|
tools?: ToolSchema[];
|
|
509
|
+
/** Session-folded tool history used for route projection; omission sends complete declarations without tool updates. */
|
|
510
|
+
toolHistory?: ToolHistory;
|
|
486
511
|
temperature?: number;
|
|
487
512
|
maxTokens?: number;
|
|
488
513
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-llm",
|
|
3
3
|
"description": "Provider-neutral LLM service interface for the DeepSeek Harness",
|
|
4
|
-
"version": "0.1.7-
|
|
4
|
+
"version": "0.1.7-rc.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -65,16 +65,16 @@
|
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"zod": "^4.4.3",
|
|
68
|
-
"@deepseek-ai/dsh-util-crypto": "0.1.7-alpha.2",
|
|
69
68
|
"@deepseek-ai/schemastery": "~3.18.4",
|
|
70
|
-
"@deepseek-ai/dsh-timeout": "0.1.7-
|
|
71
|
-
"@deepseek-ai/dsh-
|
|
72
|
-
"@deepseek-ai/dsh-
|
|
73
|
-
"@deepseek-ai/dsh-
|
|
69
|
+
"@deepseek-ai/dsh-timeout": "0.1.7-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-util-values": "0.1.7-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-typert-protocol": "0.1.7-rc.2",
|
|
72
|
+
"@deepseek-ai/dsh-brand": "0.1.7-rc.2",
|
|
73
|
+
"@deepseek-ai/dsh-util-crypto": "0.1.7-rc.2"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@deepseek-ai/dsh-
|
|
77
|
-
"@deepseek-ai/dsh-
|
|
76
|
+
"@deepseek-ai/dsh-invariants": "0.1.7-rc.2",
|
|
77
|
+
"@deepseek-ai/dsh-attachment": "0.1.7-rc.2",
|
|
78
78
|
"@deepseek-ai/cordis": "~4.0.4"
|
|
79
79
|
}
|
|
80
80
|
}
|