@deepseek-ai/dsh-session 0.1.7-rc.2 → 0.2.0-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 +14 -11
- package/README.md +7 -3
- package/README.zh.md +8 -6
- package/lib/index.js +131 -91
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.js +1 -1
- package/lib/types/repair.d.ts +33 -19
- package/lib/types/repair.js +113 -80
- package/package.json +11 -11
package/README.i18n.yaml
CHANGED
|
@@ -42,11 +42,14 @@
|
|
|
42
42
|
en: bbfb53c50100ab13
|
|
43
43
|
zh: 303a8ee47f4f656a
|
|
44
44
|
/deepseek-ai-dsh-session/understand-the-implementation/source-map:
|
|
45
|
-
en:
|
|
46
|
-
zh:
|
|
45
|
+
en: 1268738282846f1d
|
|
46
|
+
zh: 75a9fe0d5088ea09
|
|
47
47
|
/deepseek-ai-dsh-session/understand-the-implementation/append-validation:
|
|
48
48
|
en: 5c09583bc8e1ffc6
|
|
49
49
|
zh: 3b25552de2d1f9b6
|
|
50
|
+
/deepseek-ai-dsh-session/understand-the-implementation/shared-recovery:
|
|
51
|
+
en: 76bb076736b2dd0f
|
|
52
|
+
zh: de8306afc1e5faa1
|
|
50
53
|
/deepseek-ai-dsh-session/understand-the-implementation/derived-history:
|
|
51
54
|
en: 0cc7a06f76bd7eca
|
|
52
55
|
zh: 1db25185b15cad23
|
|
@@ -71,16 +74,16 @@
|
|
|
71
74
|
/deepseek-ai-dsh-session/model-experience/derived-message-history/kv-cache-effect:
|
|
72
75
|
en: 6c8079c7de029ed4
|
|
73
76
|
zh: 634d6f93ce6373c4
|
|
74
|
-
/deepseek-ai-dsh-session/model-experience/
|
|
75
|
-
en:
|
|
76
|
-
zh:
|
|
77
|
-
/deepseek-ai-dsh-session/model-experience/
|
|
77
|
+
/deepseek-ai-dsh-session/model-experience/tool-result-recovery-and-fork-results:
|
|
78
|
+
en: 9c2efc3e9064e3c4
|
|
79
|
+
zh: 9a7783991b322750
|
|
80
|
+
/deepseek-ai-dsh-session/model-experience/tool-result-recovery-and-fork-results/what-the-model-sees:
|
|
78
81
|
en: b2ae41b23519cdc6
|
|
79
|
-
zh:
|
|
80
|
-
/deepseek-ai-dsh-session/model-experience/
|
|
81
|
-
en:
|
|
82
|
-
zh:
|
|
83
|
-
/deepseek-ai-dsh-session/model-experience/
|
|
82
|
+
zh: 0e80c34e3267d098
|
|
83
|
+
/deepseek-ai-dsh-session/model-experience/tool-result-recovery-and-fork-results/token-effect:
|
|
84
|
+
en: 1339facbd3d7cee0
|
|
85
|
+
zh: 9d392a053ef90032
|
|
86
|
+
/deepseek-ai-dsh-session/model-experience/tool-result-recovery-and-fork-results/kv-cache-effect:
|
|
84
87
|
en: f5d5f97a153f7c70
|
|
85
88
|
zh: b84ef7f75f2e25d0
|
|
86
89
|
/deepseek-ai-dsh-session/model-experience/logged-request-header:
|
package/README.md
CHANGED
|
@@ -100,13 +100,17 @@ The package is built on event sourcing: a `Session` is an append-only log of typ
|
|
|
100
100
|
| [`src/surface.ts`](src/surface.ts) | Ordered surface projection, replacement validation, `deriveEventMessage` |
|
|
101
101
|
| [`src/request-header.ts`](src/request-header.ts) | `request/header` folding and reconstruction |
|
|
102
102
|
| [`dsh-util-values`](../../util/values/README.md) | Shared lossless JSON validation and detached snapshots |
|
|
103
|
-
| [`src/repair.ts`](src/repair.ts) |
|
|
103
|
+
| [`src/repair.ts`](src/repair.ts) | Shared tool-result recovery for failed steps, interrupted logs, and fork seeds |
|
|
104
104
|
| [`src/invariant.ts`](src/invariant.ts) | Invariant companion: seq, turn/step enclosure, tool call/result pairing |
|
|
105
105
|
|
|
106
106
|
### Append validation
|
|
107
107
|
|
|
108
108
|
Every append uses the shared iterative `snapshotJsonValue()` pass, which reads, validates, and copies each nested value once, so a stateful getter cannot supply one value to validation and another to storage. Non-lossless-JSON payloads (BigInt, cycles, sparse arrays, `-0`, exotic prototypes) are rejected at the append site, before any backend flush. The append path constructs each `SessionSeq`; surface events additionally validate marker shape, cited source-event sequences, and complete shadowed-node coverage for replacements.
|
|
109
109
|
|
|
110
|
+
### Shared recovery
|
|
111
|
+
|
|
112
|
+
`ToolCallRecovery` tracks unanswered requests from committed events without retaining event history. AgentLoop observes live steps; crash recovery and fork-seed construction replay their prefixes through `openTurnClosers`. Live failures and crash recovery use interrupted-result wording by default; fork construction passes the fork cause to select its distinct retry guidance. The caller appends recovery results before closing the step ([decision](../../../.agents/notes/implemented/bug-fix/2026-09-19-failed-step-tool-results.md)).
|
|
113
|
+
|
|
110
114
|
### Derived history
|
|
111
115
|
|
|
112
116
|
`deriveMessages()` caches deep-frozen projections and returns a fresh array per call. The surface event types (`system/message`, `developer/message`, `user/message`, `assistant/message`, `tool/result`) supply their recorded message identities and content; empty-content system and developer nodes project to no message. Plugin-owned projections change derived content without mutating recorded messages. Replacements and projection decisions invalidate the cache. Embedded Assistant streams and `assistant/attempt` events remain replay and diagnostic data only.
|
|
@@ -149,7 +153,7 @@ Appended surface entries are resent on later steps. A `replace` surface operatio
|
|
|
149
153
|
|
|
150
154
|
Appended surface entries preserve reusable prefixes. A `replace` operation invalidates reuse from the first shadowed message even though the underlying event log stays append-only.
|
|
151
155
|
|
|
152
|
-
###
|
|
156
|
+
### Tool-result recovery and fork results
|
|
153
157
|
|
|
154
158
|
#### What the model sees
|
|
155
159
|
|
|
@@ -157,7 +161,7 @@ If recovery finds an assistant tool request with no durable `tool/call`, its syn
|
|
|
157
161
|
|
|
158
162
|
#### Token effect
|
|
159
163
|
|
|
160
|
-
Zero tokens in an intact session. Each repaired call adds its retained risk-specific error text
|
|
164
|
+
Zero tokens in an intact session. Each repaired call adds its retained risk-specific error text to later requests.
|
|
161
165
|
|
|
162
166
|
#### KV Cache effect
|
|
163
167
|
|
package/README.zh.md
CHANGED
|
@@ -100,13 +100,17 @@ session.deriveMessages() // the derived model history
|
|
|
100
100
|
| [`src/surface.ts`](src/surface.ts) | 有序 surface 投影、替换校验、`deriveEventMessage` |
|
|
101
101
|
| [`src/request-header.ts`](src/request-header.ts) | `request/header` 折叠与重建 |
|
|
102
102
|
| [`dsh-util-values`](../../util/values/README.zh.md) | 共享无损 JSON 校验与分离式快照 |
|
|
103
|
-
| [`src/repair.ts`](src/repair.ts) |
|
|
103
|
+
| [`src/repair.ts`](src/repair.ts) | 失败步骤、中断日志与 fork 种子共享的工具结果恢复 |
|
|
104
104
|
| [`src/invariant.ts`](src/invariant.ts) | 不变式配套:序号、轮次/步骤闭合、工具调用/结果配对 |
|
|
105
105
|
|
|
106
106
|
### 追加校验
|
|
107
107
|
|
|
108
108
|
每次追加都会使用共享的迭代式 `snapshotJsonValue()` 流程,对每个嵌套值只读取、校验并复制一次,因此有状态的 getter 无法给校验提供一个值、给存储提供另一个值。非无损 JSON 载荷(BigInt、循环、稀疏数组、`-0`、特殊原型)会在追加位置被拒绝,先于任何后端刷新。追加路径会构造每个 `SessionSeq`;surface 事件还会校验标记形态、被引用的源事件序号,以及替换的完整遮蔽节点覆盖。
|
|
109
109
|
|
|
110
|
+
### 共享恢复逻辑
|
|
111
|
+
|
|
112
|
+
`ToolCallRecovery` 从已提交事件中跟踪尚无结果的请求,不保留事件历史。AgentLoop 观察实时步骤;崩溃恢复与 fork 种子构造通过 `openTurnClosers` 回放各自的前缀。实时失败与崩溃恢复默认使用中断结果文案;fork 构造传入 fork 原因,以选择其专用的重试指引。调用方在关闭步骤之前追加恢复结果([决策](../../../.agents/notes/implemented/bug-fix/2026-09-19-failed-step-tool-results.zh.md))。
|
|
113
|
+
|
|
110
114
|
### 派生历史
|
|
111
115
|
|
|
112
116
|
`deriveMessages()` 缓存深度冻结的派生消息,每次调用返回新数组。surface 事件类型(`system/message`、`developer/message`、`user/message`、`assistant/message`、`tool/result`)提供记录的消息身份和内容,空内容的 system 和 developer 节点不派生消息。插件拥有的投影修改派生内容,不修改记录的消息。替换和投影决策使缓存失效。嵌入式 Assistant stream 与 `assistant/attempt` 事件只保留回放和诊断数据。
|
|
@@ -149,17 +153,15 @@ session.deriveMessages() // the derived model history
|
|
|
149
153
|
|
|
150
154
|
追加的 surface 条目会保留可复用前缀。即使底层事件日志保持仅追加,`replace` 操作也会从首条被遮蔽消息起使缓存复用失效。
|
|
151
155
|
|
|
152
|
-
###
|
|
156
|
+
### 工具结果恢复与 fork 结果
|
|
153
157
|
|
|
154
158
|
#### 模型看到什么
|
|
155
159
|
|
|
156
|
-
如果恢复发现 assistant 工具请求没有持久 `tool/call`,其合成 `TOOL_NOT_STARTED` 结果内容为 `The tool call was interrupted before the Harness recorded it as started. Retry it if it is still needed.`。如果持久 `tool/call` 没有结果,其 `TOOL_OUTCOME_UNKNOWN` 结果内容为 `The tool call was interrupted after it was recorded, but no result was durably recorded. Its outcome is unknown. Decide whether to retry from the tool semantics: retry only if the operation is read-only or idempotent; if it may have side effects, first verify external state or ask the user. Do not retry blindly.`。
|
|
157
|
-
|
|
158
|
-
Fork 生成的结果只描述继承记录:父会话可能已经在所选事件之后启动或完成调用。`TOOL_NOT_STARTED` 表示前缀中没有启动记录;`TOOL_OUTCOME_UNKNOWN` 表示有启动记录但没有结果。两者都要求模型仅对只读或幂等操作直接重试;有副作用的操作需要先验证外部状态或询问用户。参见 [fork 决策](../../../.agents/notes/implemented/feature/2026-08-18-arbitrary-seq-session-fork.zh.md)。
|
|
160
|
+
如果恢复发现 assistant 工具请求没有持久 `tool/call`,其合成 `TOOL_NOT_STARTED` 结果内容为 `The tool call was interrupted before the Harness recorded it as started. Retry it if it is still needed.`。如果持久 `tool/call` 没有结果,其 `TOOL_OUTCOME_UNKNOWN` 结果内容为 `The tool call was interrupted after it was recorded, but no result was durably recorded. Its outcome is unknown. Decide whether to retry from the tool semantics: retry only if the operation is read-only or idempotent; if it may have side effects, first verify external state or ask the user. Do not retry blindly.`。 Fork 生成的结果只描述继承记录:父会话可能已经在所选事件之后启动或完成调用。`TOOL_NOT_STARTED` 表示前缀中没有启动记录;`TOOL_OUTCOME_UNKNOWN` 表示有启动记录但没有结果。两者都要求模型仅对只读或幂等操作直接重试;有副作用的操作需要先验证外部状态或询问用户。参见 [fork 决策](../../../.agents/notes/implemented/feature/2026-08-18-arbitrary-seq-session-fork.zh.md)。
|
|
159
161
|
|
|
160
162
|
#### Token 影响
|
|
161
163
|
|
|
162
|
-
未受损会话的 token
|
|
164
|
+
未受损会话的 token 增量为零。每个修复后的调用都会向后续请求添加保留的、针对具体风险的错误文本。
|
|
163
165
|
|
|
164
166
|
#### KV Cache 影响
|
|
165
167
|
|
package/lib/index.js
CHANGED
|
@@ -714,12 +714,9 @@ var ToolHistoryProjection = class {
|
|
|
714
714
|
//#endregion
|
|
715
715
|
//#region lib/types/repair.js
|
|
716
716
|
/**
|
|
717
|
-
*
|
|
718
|
-
*
|
|
719
|
-
*
|
|
720
|
-
* inside the source's open turn. Both preserve every fully written event and
|
|
721
|
-
* close the unfinished step and turn. Calls in already closed steps remain
|
|
722
|
-
* unchanged, including any missing results.
|
|
717
|
+
* Pending tool-result recovery shared by failed live steps, interrupted logs,
|
|
718
|
+
* and fork seeds. Tail repair preserves closed steps and supplies only missing
|
|
719
|
+
* tool results and lifecycle boundaries, with cause-specific retry guidance.
|
|
723
720
|
* @module @deepseek-ai/dsh-session/repair
|
|
724
721
|
*/
|
|
725
722
|
/** Recovery code for an assistant tool request that never reached a recorded call start. */
|
|
@@ -739,99 +736,43 @@ const CLOSER_TEXT = {
|
|
|
739
736
|
};
|
|
740
737
|
/**
|
|
741
738
|
* Return deterministic synthetic events that close an open tail turn. Unmatched
|
|
742
|
-
* calls
|
|
743
|
-
* `turn/end
|
|
744
|
-
*
|
|
745
|
-
* events.
|
|
739
|
+
* calls receive error results first, followed by an open `step/end` and a
|
|
740
|
+
* cause-specific `turn/end`; sequences continue the log and timestamps reuse the
|
|
741
|
+
* last real event. A balanced or empty log returns no events.
|
|
746
742
|
*
|
|
747
|
-
*
|
|
748
|
-
*
|
|
749
|
-
* `buildForkSeed` in `./fork.ts` (fork seeds) instead of selecting a cause.
|
|
750
|
-
*
|
|
751
|
-
* @param events - the log to scan: a valid committed prefix, possibly ending
|
|
752
|
-
* inside an open turn (a crash tail or a mid-turn fork cut).
|
|
753
|
-
* @param cause - why the turn is being closed; selects the `turn/end` reason
|
|
754
|
-
* and the model-visible wording of synthetic error tool results.
|
|
743
|
+
* @param events - the loaded durable log to scan (a valid committed prefix, possibly with a crash tail).
|
|
744
|
+
* @param cause - the owning close operation: selects result wording and the turn-ending reason.
|
|
755
745
|
* @returns the synthetic closer events to append after `events`, in order; empty when the log is already balanced.
|
|
756
746
|
*/
|
|
757
747
|
function openTurnClosers(events, cause) {
|
|
758
748
|
let openTurn = null;
|
|
759
749
|
let openStep = null;
|
|
760
|
-
const
|
|
761
|
-
for (const event of events)
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
break;
|
|
779
|
-
|
|
780
|
-
for (const block of event.data.message.content) if (block.type === "tool-call") pendingCalls.set(block.id, { step: event.data.step });
|
|
781
|
-
break;
|
|
782
|
-
case "tool/call":
|
|
783
|
-
{
|
|
784
|
-
const entry = pendingCalls.get(event.data.callId);
|
|
785
|
-
if (entry) entry.callSeq = event.seq;
|
|
786
|
-
}
|
|
787
|
-
break;
|
|
788
|
-
case "tool/result":
|
|
789
|
-
pendingCalls.delete(event.data.message.source.callId);
|
|
790
|
-
break;
|
|
791
|
-
default: break;
|
|
750
|
+
const recovery = new ToolCallRecovery(cause);
|
|
751
|
+
for (const event of events) {
|
|
752
|
+
recovery.observe(event);
|
|
753
|
+
switch (event.type) {
|
|
754
|
+
case "turn/start":
|
|
755
|
+
openTurn = event.data.turn;
|
|
756
|
+
openStep = null;
|
|
757
|
+
break;
|
|
758
|
+
case "turn/end":
|
|
759
|
+
openTurn = null;
|
|
760
|
+
openStep = null;
|
|
761
|
+
break;
|
|
762
|
+
case "step/start":
|
|
763
|
+
openStep = event.data.step;
|
|
764
|
+
break;
|
|
765
|
+
case "step/end":
|
|
766
|
+
openStep = null;
|
|
767
|
+
break;
|
|
768
|
+
default: break;
|
|
769
|
+
}
|
|
792
770
|
}
|
|
793
771
|
const last = events.at(-1);
|
|
794
772
|
if (openTurn === null || last === void 0) return [];
|
|
795
|
-
|
|
773
|
+
const closers = recovery.results();
|
|
774
|
+
let seq = last.seq + closers.length + 1;
|
|
796
775
|
const time = last.time;
|
|
797
|
-
const closers = [];
|
|
798
|
-
const text = CLOSER_TEXT[cause.kind];
|
|
799
|
-
for (const [callId, { step, callSeq }] of pendingCalls) {
|
|
800
|
-
const started = callSeq !== void 0;
|
|
801
|
-
const message = deepFreeze({
|
|
802
|
-
id: brandString(`${cause.kind}-tool-result-${callId}-${seq}`),
|
|
803
|
-
role: "tool",
|
|
804
|
-
toolCallId: callId,
|
|
805
|
-
isError: true,
|
|
806
|
-
source: {
|
|
807
|
-
kind: "tool",
|
|
808
|
-
callId
|
|
809
|
-
},
|
|
810
|
-
content: [{
|
|
811
|
-
type: "text",
|
|
812
|
-
text: started ? text.started : text.notStarted
|
|
813
|
-
}]
|
|
814
|
-
});
|
|
815
|
-
closers.push({
|
|
816
|
-
type: "tool/result",
|
|
817
|
-
seq: SessionSeq(seq++),
|
|
818
|
-
time,
|
|
819
|
-
data: {
|
|
820
|
-
turn: openTurn,
|
|
821
|
-
step,
|
|
822
|
-
message,
|
|
823
|
-
error: started ? {
|
|
824
|
-
name: "ToolOutcomeUnknownError",
|
|
825
|
-
code: TOOL_OUTCOME_UNKNOWN
|
|
826
|
-
} : {
|
|
827
|
-
name: "ToolNotStartedError",
|
|
828
|
-
code: TOOL_NOT_STARTED
|
|
829
|
-
}
|
|
830
|
-
},
|
|
831
|
-
surfaceOp: "append",
|
|
832
|
-
...started ? { sourceEventSeqs: [callSeq] } : {}
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
776
|
if (openStep !== null) closers.push({
|
|
836
777
|
type: "step/end",
|
|
837
778
|
seq: SessionSeq(seq++),
|
|
@@ -853,10 +794,109 @@ function openTurnClosers(events, cause) {
|
|
|
853
794
|
return closers;
|
|
854
795
|
}
|
|
855
796
|
/**
|
|
797
|
+
* Track unanswered assistant tool requests from one Session's committed events.
|
|
798
|
+
* Observe from the start of the owned step or replay prefix, and recover before
|
|
799
|
+
* its step closes. This state retains pending identities, not event history.
|
|
800
|
+
*/
|
|
801
|
+
var ToolCallRecovery = class {
|
|
802
|
+
cause;
|
|
803
|
+
pendingCalls = /* @__PURE__ */ new Map();
|
|
804
|
+
last;
|
|
805
|
+
/** @param cause - defaults to interrupted live/crash recovery; fork-seed construction supplies its own cause. */
|
|
806
|
+
constructor(cause = { kind: "interrupted" }) {
|
|
807
|
+
this.cause = cause;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Consume the next committed event; closed steps and turn boundaries discard pending requests.
|
|
811
|
+
* @param event - the next event from the same Session, in sequence order.
|
|
812
|
+
*/
|
|
813
|
+
observe(event) {
|
|
814
|
+
this.last = {
|
|
815
|
+
seq: event.seq,
|
|
816
|
+
time: event.time
|
|
817
|
+
};
|
|
818
|
+
switch (event.type) {
|
|
819
|
+
case "turn/start":
|
|
820
|
+
case "turn/end":
|
|
821
|
+
case "step/end":
|
|
822
|
+
this.pendingCalls.clear();
|
|
823
|
+
break;
|
|
824
|
+
case "assistant/message":
|
|
825
|
+
for (const block of event.data.message.content) if (block.type === "tool-call") this.pendingCalls.set(block.id, {
|
|
826
|
+
turn: event.data.turn,
|
|
827
|
+
step: event.data.step
|
|
828
|
+
});
|
|
829
|
+
break;
|
|
830
|
+
case "tool/call": {
|
|
831
|
+
const entry = this.pendingCalls.get(event.data.callId);
|
|
832
|
+
if (entry) entry.callSeq = event.seq;
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
case "tool/result": {
|
|
836
|
+
const callId = event.data.message.source.callId;
|
|
837
|
+
const entry = this.pendingCalls.get(callId);
|
|
838
|
+
if (event.surfaceOp === "append" && entry !== void 0 && entry.turn === event.data.turn && entry.step === event.data.step) this.pendingCalls.delete(callId);
|
|
839
|
+
break;
|
|
840
|
+
}
|
|
841
|
+
default: break;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Build conservative error results in assistant order without changing tracked state.
|
|
846
|
+
* Sequences follow the latest observed event and timestamps reuse its time.
|
|
847
|
+
* Callers commit the results and observe those commits before recovering again.
|
|
848
|
+
* @returns pending tool-result events, empty when no request remains unanswered.
|
|
849
|
+
*/
|
|
850
|
+
results() {
|
|
851
|
+
if (this.last === void 0) return [];
|
|
852
|
+
let seq = this.last.seq + 1;
|
|
853
|
+
const time = this.last.time;
|
|
854
|
+
const results = [];
|
|
855
|
+
const text = CLOSER_TEXT[this.cause.kind];
|
|
856
|
+
for (const [callId, { turn, step, callSeq }] of this.pendingCalls) {
|
|
857
|
+
const started = callSeq !== void 0;
|
|
858
|
+
const message = deepFreeze({
|
|
859
|
+
id: brandString(`${this.cause.kind}-tool-result-${callId}-${seq}`),
|
|
860
|
+
role: "tool",
|
|
861
|
+
toolCallId: callId,
|
|
862
|
+
isError: true,
|
|
863
|
+
source: {
|
|
864
|
+
kind: "tool",
|
|
865
|
+
callId
|
|
866
|
+
},
|
|
867
|
+
content: [{
|
|
868
|
+
type: "text",
|
|
869
|
+
text: started ? text.started : text.notStarted
|
|
870
|
+
}]
|
|
871
|
+
});
|
|
872
|
+
results.push({
|
|
873
|
+
type: "tool/result",
|
|
874
|
+
seq: SessionSeq(seq++),
|
|
875
|
+
time,
|
|
876
|
+
data: {
|
|
877
|
+
turn,
|
|
878
|
+
step,
|
|
879
|
+
message,
|
|
880
|
+
error: started ? {
|
|
881
|
+
name: "ToolOutcomeUnknownError",
|
|
882
|
+
code: TOOL_OUTCOME_UNKNOWN
|
|
883
|
+
} : {
|
|
884
|
+
name: "ToolNotStartedError",
|
|
885
|
+
code: TOOL_NOT_STARTED
|
|
886
|
+
}
|
|
887
|
+
},
|
|
888
|
+
surfaceOp: "append",
|
|
889
|
+
...started ? { sourceEventSeqs: [callSeq] } : {}
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
return results;
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
/**
|
|
856
896
|
* Crash-recovery entry point: synthetic closers that balance a persisted log
|
|
857
897
|
* whose tail turn was interrupted. Used by crash-recovery callers; fork
|
|
858
898
|
* seeds receive their `forked`-cause closers through `buildForkSeed` in
|
|
859
|
-
* `./fork.ts
|
|
899
|
+
* `./fork.ts`.
|
|
860
900
|
*
|
|
861
901
|
* @param events - the persisted log to scan, possibly ending inside an open turn.
|
|
862
902
|
* @returns the synthetic `interrupted` closer events to append after `events`; empty when the log is already balanced.
|
|
@@ -1890,4 +1930,4 @@ var SessionStore = class extends Service {
|
|
|
1890
1930
|
}
|
|
1891
1931
|
};
|
|
1892
1932
|
//#endregion
|
|
1893
|
-
export { KNOWN_SESSION_EVENT_TYPES, SESSION_FORMAT_VERSION, Session, SessionForkError, SessionId, SessionLogOffset, SessionPreparation, SessionSeq, SessionStore, SessionStore as default, TOOL_NOT_STARTED, TOOL_OUTCOME_UNKNOWN, adoptSessionEvent, buildForkSeed, canonicalHeader, decodeSeqRanges, deriveEventMessage, encodeSeqRanges, foldRequestHeader, foldSurface, headerEquals, interruptedTurnClosers, isAppendSurfaceEvent, isReplacementSurfaceEvent, isSurfaceEligibleType, isSurfaceEvent, snapshotSessionEvent };
|
|
1933
|
+
export { KNOWN_SESSION_EVENT_TYPES, SESSION_FORMAT_VERSION, Session, SessionForkError, SessionId, SessionLogOffset, SessionPreparation, SessionSeq, SessionStore, SessionStore as default, TOOL_NOT_STARTED, TOOL_OUTCOME_UNKNOWN, ToolCallRecovery, adoptSessionEvent, buildForkSeed, canonicalHeader, decodeSeqRanges, deriveEventMessage, encodeSeqRanges, foldRequestHeader, foldSurface, headerEquals, interruptedTurnClosers, isAppendSurfaceEvent, isReplacementSurfaceEvent, isSurfaceEligibleType, isSurfaceEvent, snapshotSessionEvent };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export * from './types.ts';
|
|
|
18
18
|
export { SessionPreparation } from './preparation.ts';
|
|
19
19
|
export type { SessionPreparationOptions } from './preparation.ts';
|
|
20
20
|
export type { AssistantMessage, DeveloperMessage, SystemMessage, ToolResultMessage, UserMessage } from '@deepseek-ai/dsh-llm';
|
|
21
|
-
export { interruptedTurnClosers, TOOL_NOT_STARTED, TOOL_OUTCOME_UNKNOWN } from './repair.ts';
|
|
21
|
+
export { interruptedTurnClosers, ToolCallRecovery, TOOL_NOT_STARTED, TOOL_OUTCOME_UNKNOWN } from './repair.ts';
|
|
22
22
|
export type { SessionSurface, SurfaceFoldReplacement, SurfaceFoldResult, SessionMessageProjection, SessionMessageProjectionContext } from './surface.ts';
|
|
23
23
|
export { deriveEventMessage, foldSurface, isAppendSurfaceEvent, isReplacementSurfaceEvent, isSurfaceEvent, isSurfaceEligibleType } from './surface.ts';
|
|
24
24
|
export { canonicalHeader, foldRequestHeader, headerEquals } from './request-header.ts';
|
package/lib/types/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { buildForkSeed } from "./fork.js";
|
|
|
18
18
|
export { buildForkSeed } from "./fork.js";
|
|
19
19
|
export * from "./types.js";
|
|
20
20
|
export { SessionPreparation } from "./preparation.js";
|
|
21
|
-
export { interruptedTurnClosers, TOOL_NOT_STARTED, TOOL_OUTCOME_UNKNOWN } from "./repair.js";
|
|
21
|
+
export { interruptedTurnClosers, ToolCallRecovery, TOOL_NOT_STARTED, TOOL_OUTCOME_UNKNOWN } from "./repair.js";
|
|
22
22
|
export { deriveEventMessage, foldSurface, isAppendSurfaceEvent, isReplacementSurfaceEvent, isSurfaceEvent, isSurfaceEligibleType } from "./surface.js";
|
|
23
23
|
export { canonicalHeader, foldRequestHeader, headerEquals } from "./request-header.js";
|
|
24
24
|
export { KNOWN_SESSION_EVENT_TYPES } from "./known-event-types.js";
|
package/lib/types/repair.d.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* inside the source's open turn. Both preserve every fully written event and
|
|
6
|
-
* close the unfinished step and turn. Calls in already closed steps remain
|
|
7
|
-
* unchanged, including any missing results.
|
|
2
|
+
* Pending tool-result recovery shared by failed live steps, interrupted logs,
|
|
3
|
+
* and fork seeds. Tail repair preserves closed steps and supplies only missing
|
|
4
|
+
* tool results and lifecycle boundaries, with cause-specific retry guidance.
|
|
8
5
|
* @module @deepseek-ai/dsh-session/repair
|
|
9
6
|
*/
|
|
10
7
|
import type { SessionEvent } from './types.ts';
|
|
@@ -28,27 +25,44 @@ export type OpenTurnCloseCause = {
|
|
|
28
25
|
};
|
|
29
26
|
/**
|
|
30
27
|
* Return deterministic synthetic events that close an open tail turn. Unmatched
|
|
31
|
-
* calls
|
|
32
|
-
* `turn/end
|
|
33
|
-
*
|
|
34
|
-
* events.
|
|
28
|
+
* calls receive error results first, followed by an open `step/end` and a
|
|
29
|
+
* cause-specific `turn/end`; sequences continue the log and timestamps reuse the
|
|
30
|
+
* last real event. A balanced or empty log returns no events.
|
|
35
31
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* `buildForkSeed` in `./fork.ts` (fork seeds) instead of selecting a cause.
|
|
39
|
-
*
|
|
40
|
-
* @param events - the log to scan: a valid committed prefix, possibly ending
|
|
41
|
-
* inside an open turn (a crash tail or a mid-turn fork cut).
|
|
42
|
-
* @param cause - why the turn is being closed; selects the `turn/end` reason
|
|
43
|
-
* and the model-visible wording of synthetic error tool results.
|
|
32
|
+
* @param events - the loaded durable log to scan (a valid committed prefix, possibly with a crash tail).
|
|
33
|
+
* @param cause - the owning close operation: selects result wording and the turn-ending reason.
|
|
44
34
|
* @returns the synthetic closer events to append after `events`, in order; empty when the log is already balanced.
|
|
45
35
|
*/
|
|
46
36
|
export declare function openTurnClosers(events: readonly SessionEvent[], cause: OpenTurnCloseCause): SessionEvent[];
|
|
37
|
+
/**
|
|
38
|
+
* Track unanswered assistant tool requests from one Session's committed events.
|
|
39
|
+
* Observe from the start of the owned step or replay prefix, and recover before
|
|
40
|
+
* its step closes. This state retains pending identities, not event history.
|
|
41
|
+
*/
|
|
42
|
+
export declare class ToolCallRecovery {
|
|
43
|
+
private readonly cause;
|
|
44
|
+
private readonly pendingCalls;
|
|
45
|
+
private last;
|
|
46
|
+
/** @param cause - defaults to interrupted live/crash recovery; fork-seed construction supplies its own cause. */
|
|
47
|
+
constructor(cause?: OpenTurnCloseCause);
|
|
48
|
+
/**
|
|
49
|
+
* Consume the next committed event; closed steps and turn boundaries discard pending requests.
|
|
50
|
+
* @param event - the next event from the same Session, in sequence order.
|
|
51
|
+
*/
|
|
52
|
+
observe(event: SessionEvent): void;
|
|
53
|
+
/**
|
|
54
|
+
* Build conservative error results in assistant order without changing tracked state.
|
|
55
|
+
* Sequences follow the latest observed event and timestamps reuse its time.
|
|
56
|
+
* Callers commit the results and observe those commits before recovering again.
|
|
57
|
+
* @returns pending tool-result events, empty when no request remains unanswered.
|
|
58
|
+
*/
|
|
59
|
+
results(): SessionEvent<'tool/result'>[];
|
|
60
|
+
}
|
|
47
61
|
/**
|
|
48
62
|
* Crash-recovery entry point: synthetic closers that balance a persisted log
|
|
49
63
|
* whose tail turn was interrupted. Used by crash-recovery callers; fork
|
|
50
64
|
* seeds receive their `forked`-cause closers through `buildForkSeed` in
|
|
51
|
-
* `./fork.ts
|
|
65
|
+
* `./fork.ts`.
|
|
52
66
|
*
|
|
53
67
|
* @param events - the persisted log to scan, possibly ending inside an open turn.
|
|
54
68
|
* @returns the synthetic `interrupted` closer events to append after `events`; empty when the log is already balanced.
|
package/lib/types/repair.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* inside the source's open turn. Both preserve every fully written event and
|
|
6
|
-
* close the unfinished step and turn. Calls in already closed steps remain
|
|
7
|
-
* unchanged, including any missing results.
|
|
2
|
+
* Pending tool-result recovery shared by failed live steps, interrupted logs,
|
|
3
|
+
* and fork seeds. Tail repair preserves closed steps and supplies only missing
|
|
4
|
+
* tool results and lifecycle boundaries, with cause-specific retry guidance.
|
|
8
5
|
* @module @deepseek-ai/dsh-session/repair
|
|
9
6
|
*/
|
|
10
7
|
import { brandString } from '@deepseek-ai/dsh-brand';
|
|
@@ -27,66 +24,35 @@ const CLOSER_TEXT = {
|
|
|
27
24
|
};
|
|
28
25
|
/**
|
|
29
26
|
* Return deterministic synthetic events that close an open tail turn. Unmatched
|
|
30
|
-
* calls
|
|
31
|
-
* `turn/end
|
|
32
|
-
*
|
|
33
|
-
* events.
|
|
27
|
+
* calls receive error results first, followed by an open `step/end` and a
|
|
28
|
+
* cause-specific `turn/end`; sequences continue the log and timestamps reuse the
|
|
29
|
+
* last real event. A balanced or empty log returns no events.
|
|
34
30
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* `buildForkSeed` in `./fork.ts` (fork seeds) instead of selecting a cause.
|
|
38
|
-
*
|
|
39
|
-
* @param events - the log to scan: a valid committed prefix, possibly ending
|
|
40
|
-
* inside an open turn (a crash tail or a mid-turn fork cut).
|
|
41
|
-
* @param cause - why the turn is being closed; selects the `turn/end` reason
|
|
42
|
-
* and the model-visible wording of synthetic error tool results.
|
|
31
|
+
* @param events - the loaded durable log to scan (a valid committed prefix, possibly with a crash tail).
|
|
32
|
+
* @param cause - the owning close operation: selects result wording and the turn-ending reason.
|
|
43
33
|
* @returns the synthetic closer events to append after `events`, in order; empty when the log is already balanced.
|
|
44
34
|
*/
|
|
45
35
|
export function openTurnClosers(events, cause) {
|
|
46
36
|
let openTurn = null;
|
|
47
37
|
let openStep = null;
|
|
48
|
-
|
|
49
|
-
// Assistant blocks register calls; later `tool/call` events add their seqs to `sourceEventSeqs`.
|
|
50
|
-
const pendingCalls = new Map();
|
|
38
|
+
const recovery = new ToolCallRecovery(cause);
|
|
51
39
|
for (const event of events) {
|
|
40
|
+
recovery.observe(event);
|
|
52
41
|
switch (event.type) {
|
|
53
42
|
case 'turn/start':
|
|
54
43
|
openTurn = event.data.turn;
|
|
55
44
|
openStep = null;
|
|
56
|
-
pendingCalls.clear();
|
|
57
45
|
break;
|
|
58
46
|
case 'turn/end':
|
|
59
47
|
openTurn = null;
|
|
60
48
|
openStep = null;
|
|
61
|
-
pendingCalls.clear();
|
|
62
49
|
break;
|
|
63
50
|
case 'step/start':
|
|
64
51
|
openStep = event.data.step;
|
|
65
52
|
break;
|
|
66
53
|
case 'step/end':
|
|
67
|
-
pendingCalls.clear();
|
|
68
54
|
openStep = null;
|
|
69
55
|
break;
|
|
70
|
-
case 'assistant/message':
|
|
71
|
-
// The assistant message carries the tool-call blocks; each is pending
|
|
72
|
-
// until a tool/result event with the same callId is logged.
|
|
73
|
-
for (const block of event.data.message.content) {
|
|
74
|
-
if (block.type === 'tool-call')
|
|
75
|
-
pendingCalls.set(block.id, { step: event.data.step });
|
|
76
|
-
}
|
|
77
|
-
break;
|
|
78
|
-
case 'tool/call':
|
|
79
|
-
// Cite the `tool/call` seq from the synthetic result.
|
|
80
|
-
{
|
|
81
|
-
const entry = pendingCalls.get(event.data.callId);
|
|
82
|
-
if (entry) {
|
|
83
|
-
entry.callSeq = event.seq;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
break;
|
|
87
|
-
case 'tool/result':
|
|
88
|
-
pendingCalls.delete(event.data.message.source.callId);
|
|
89
|
-
break;
|
|
90
56
|
// Other event types do not move the turn/step boundary cursor.
|
|
91
57
|
default:
|
|
92
58
|
break;
|
|
@@ -100,53 +66,120 @@ export function openTurnClosers(events, cause) {
|
|
|
100
66
|
// The last real event supplies the seq base and the timestamp for the
|
|
101
67
|
// synthetic closers (reusing the last timestamp keeps them deterministic and
|
|
102
68
|
// never invents a "future" time).
|
|
103
|
-
|
|
69
|
+
const closers = recovery.results();
|
|
70
|
+
let seq = last.seq + closers.length + 1;
|
|
104
71
|
const time = last.time;
|
|
105
|
-
|
|
106
|
-
// Close calls before their step; Map insertion order preserves transcript order.
|
|
107
|
-
const text = CLOSER_TEXT[cause.kind];
|
|
108
|
-
for (const [callId, { step, callSeq }] of pendingCalls) {
|
|
109
|
-
const started = callSeq !== undefined;
|
|
110
|
-
const message = deepFreeze({
|
|
111
|
-
id: brandString(`${cause.kind}-tool-result-${callId}-${seq}`),
|
|
112
|
-
role: 'tool',
|
|
113
|
-
toolCallId: callId,
|
|
114
|
-
isError: true,
|
|
115
|
-
source: { kind: 'tool', callId },
|
|
116
|
-
content: [{
|
|
117
|
-
type: 'text',
|
|
118
|
-
text: started ? text.started : text.notStarted,
|
|
119
|
-
}],
|
|
120
|
-
});
|
|
121
|
-
closers.push({
|
|
122
|
-
type: 'tool/result',
|
|
123
|
-
seq: SessionSeq(seq++),
|
|
124
|
-
time,
|
|
125
|
-
data: {
|
|
126
|
-
turn: openTurn,
|
|
127
|
-
step,
|
|
128
|
-
message,
|
|
129
|
-
error: started
|
|
130
|
-
? { name: 'ToolOutcomeUnknownError', code: TOOL_OUTCOME_UNKNOWN }
|
|
131
|
-
: { name: 'ToolNotStartedError', code: TOOL_NOT_STARTED },
|
|
132
|
-
},
|
|
133
|
-
surfaceOp: 'append',
|
|
134
|
-
...started ? { sourceEventSeqs: [callSeq] } : {},
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
// Close an open step next — a turn/end while a step is open is an invariant
|
|
138
|
-
// violation, so the step's boundary must be synthesized before the turn's.
|
|
72
|
+
// Close an open step before its turn.
|
|
139
73
|
if (openStep !== null) {
|
|
140
74
|
closers.push({ type: 'step/end', seq: SessionSeq(seq++), time, data: { turn: openTurn, step: openStep } });
|
|
141
75
|
}
|
|
142
76
|
closers.push({ type: 'turn/end', seq: SessionSeq(seq++), time, data: { turn: openTurn, reason: { kind: cause.kind } } });
|
|
143
77
|
return closers;
|
|
144
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Track unanswered assistant tool requests from one Session's committed events.
|
|
81
|
+
* Observe from the start of the owned step or replay prefix, and recover before
|
|
82
|
+
* its step closes. This state retains pending identities, not event history.
|
|
83
|
+
*/
|
|
84
|
+
export class ToolCallRecovery {
|
|
85
|
+
cause;
|
|
86
|
+
pendingCalls = new Map();
|
|
87
|
+
last;
|
|
88
|
+
/** @param cause - defaults to interrupted live/crash recovery; fork-seed construction supplies its own cause. */
|
|
89
|
+
constructor(cause = { kind: 'interrupted' }) {
|
|
90
|
+
this.cause = cause;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Consume the next committed event; closed steps and turn boundaries discard pending requests.
|
|
94
|
+
* @param event - the next event from the same Session, in sequence order.
|
|
95
|
+
*/
|
|
96
|
+
observe(event) {
|
|
97
|
+
this.last = { seq: event.seq, time: event.time };
|
|
98
|
+
switch (event.type) {
|
|
99
|
+
case 'turn/start':
|
|
100
|
+
case 'turn/end':
|
|
101
|
+
case 'step/end':
|
|
102
|
+
this.pendingCalls.clear();
|
|
103
|
+
break;
|
|
104
|
+
case 'assistant/message':
|
|
105
|
+
for (const block of event.data.message.content) {
|
|
106
|
+
if (block.type === 'tool-call') {
|
|
107
|
+
this.pendingCalls.set(block.id, { turn: event.data.turn, step: event.data.step });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
case 'tool/call': {
|
|
112
|
+
const entry = this.pendingCalls.get(event.data.callId);
|
|
113
|
+
if (entry)
|
|
114
|
+
entry.callSeq = event.seq;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
case 'tool/result': {
|
|
118
|
+
const callId = event.data.message.source.callId;
|
|
119
|
+
const entry = this.pendingCalls.get(callId);
|
|
120
|
+
if (event.surfaceOp === 'append' && entry !== undefined
|
|
121
|
+
&& entry.turn === event.data.turn && entry.step === event.data.step) {
|
|
122
|
+
this.pendingCalls.delete(callId);
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
// SessionEvent is merge-extensible; unrelated events retain pending requests.
|
|
127
|
+
default:
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Build conservative error results in assistant order without changing tracked state.
|
|
133
|
+
* Sequences follow the latest observed event and timestamps reuse its time.
|
|
134
|
+
* Callers commit the results and observe those commits before recovering again.
|
|
135
|
+
* @returns pending tool-result events, empty when no request remains unanswered.
|
|
136
|
+
*/
|
|
137
|
+
results() {
|
|
138
|
+
if (this.last === undefined)
|
|
139
|
+
return [];
|
|
140
|
+
let seq = this.last.seq + 1;
|
|
141
|
+
const time = this.last.time;
|
|
142
|
+
const results = [];
|
|
143
|
+
const text = CLOSER_TEXT[this.cause.kind];
|
|
144
|
+
// Close calls before their step: providers reject dangling assistant calls,
|
|
145
|
+
// and Map insertion order preserves their transcript order.
|
|
146
|
+
for (const [callId, { turn, step, callSeq }] of this.pendingCalls) {
|
|
147
|
+
const started = callSeq !== undefined;
|
|
148
|
+
const message = deepFreeze({
|
|
149
|
+
id: brandString(`${this.cause.kind}-tool-result-${callId}-${seq}`),
|
|
150
|
+
role: 'tool',
|
|
151
|
+
toolCallId: callId,
|
|
152
|
+
isError: true,
|
|
153
|
+
source: { kind: 'tool', callId },
|
|
154
|
+
content: [{
|
|
155
|
+
type: 'text',
|
|
156
|
+
text: started ? text.started : text.notStarted,
|
|
157
|
+
}],
|
|
158
|
+
});
|
|
159
|
+
results.push({
|
|
160
|
+
type: 'tool/result',
|
|
161
|
+
seq: SessionSeq(seq++),
|
|
162
|
+
time,
|
|
163
|
+
data: {
|
|
164
|
+
turn,
|
|
165
|
+
step,
|
|
166
|
+
message,
|
|
167
|
+
error: started
|
|
168
|
+
? { name: 'ToolOutcomeUnknownError', code: TOOL_OUTCOME_UNKNOWN }
|
|
169
|
+
: { name: 'ToolNotStartedError', code: TOOL_NOT_STARTED },
|
|
170
|
+
},
|
|
171
|
+
surfaceOp: 'append',
|
|
172
|
+
...started ? { sourceEventSeqs: [callSeq] } : {},
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return results;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
145
178
|
/**
|
|
146
179
|
* Crash-recovery entry point: synthetic closers that balance a persisted log
|
|
147
180
|
* whose tail turn was interrupted. Used by crash-recovery callers; fork
|
|
148
181
|
* seeds receive their `forked`-cause closers through `buildForkSeed` in
|
|
149
|
-
* `./fork.ts
|
|
182
|
+
* `./fork.ts`.
|
|
150
183
|
*
|
|
151
184
|
* @param events - the persisted log to scan, possibly ending inside an open turn.
|
|
152
185
|
* @returns the synthetic `interrupted` closer events to append after `events`; empty when the log is already balanced.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-session",
|
|
3
3
|
"description": "Event-sourced session store for the DeepSeek Harness",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0-rc.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -45,19 +45,19 @@
|
|
|
45
45
|
],
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@deepseek-ai/
|
|
49
|
-
"@deepseek-ai/
|
|
48
|
+
"@deepseek-ai/cordis": "~4.0.4",
|
|
49
|
+
"@deepseek-ai/dsh-scope": "0.2.0-rc.2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@deepseek-ai/dsh-invariants": "0.
|
|
53
|
-
"@deepseek-ai/dsh-typert-protocol": "0.
|
|
54
|
-
"@deepseek-ai/dsh-scope": "0.
|
|
55
|
-
"@deepseek-ai/
|
|
56
|
-
"@deepseek-ai/
|
|
52
|
+
"@deepseek-ai/dsh-invariants": "0.2.0-rc.2",
|
|
53
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.0-rc.2",
|
|
54
|
+
"@deepseek-ai/dsh-scope": "0.2.0-rc.2",
|
|
55
|
+
"@deepseek-ai/cordis": "~4.0.4",
|
|
56
|
+
"@deepseek-ai/dsh-typert-registry": "0.2.0-rc.2"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@deepseek-ai/dsh-llm": "0.
|
|
60
|
-
"@deepseek-ai/dsh-brand": "0.
|
|
61
|
-
"@deepseek-ai/dsh-util-values": "0.
|
|
59
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-brand": "0.2.0-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-util-values": "0.2.0-rc.2"
|
|
62
62
|
}
|
|
63
63
|
}
|