dsh-loop-engine 1.0.0-rc13 → 1.0.0-rc14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -6
- package/README.zh.md +13 -0
- package/lib/index.js +148 -80
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,13 +34,10 @@ matched — a mismatch fails loudly at boot or session resume:
|
|
|
34
34
|
|
|
35
35
|
| dsh-loop-engine | Requires harness |
|
|
36
36
|
|---|---|
|
|
37
|
-
| 1.0.0-
|
|
38
|
-
| 1.0.0-
|
|
39
|
-
| 1.0.0-rc11 | **0.1.2-rc.1** |
|
|
40
|
-
| 1.0.0-rc10 | **0.1.2-rc.1** |
|
|
41
|
-
| 1.0.0-rc7 | 0.1.1-rc.2 |
|
|
37
|
+
| 1.0.0-rc8 and later | **0.1.2-rc.1** |
|
|
38
|
+
| 1.0.0-rc7 and earlier | 0.1.1-rc.2 |
|
|
42
39
|
|
|
43
|
-
- **1.0.0-
|
|
40
|
+
- **1.0.0-rc8 and later is not compatible with harness 0.1.1-rc.2 or earlier.** It uses
|
|
44
41
|
the 0.1.2 persistence seam (`SessionPersistence.create` / `open` +
|
|
45
42
|
`SessionHandle`), the `installSection` settings API, `ToolCallId`, and
|
|
46
43
|
`Session.snapshotEvents()` — none of which exist in older harnesses.
|
package/README.zh.md
CHANGED
|
@@ -21,6 +21,19 @@ dsh plugin --profile web add dsh-loop-engine
|
|
|
21
21
|
- 使用 Pi 引擎时需要以 `pi` 要求的方式完成认证(其自身的 `~/.pi/agent/auth.json`,或提供方的 API-key 环境变量,如 `ANTHROPIC_API_KEY`)。
|
|
22
22
|
- 使用 Kimi Code 引擎时需要本机已安装并登录 `kimi` CLI(例如 `kimi login`),且在 `PATH` 上(或在组合条目里用 `kimiBin` 固定为绝对路径)。
|
|
23
23
|
|
|
24
|
+
## 版本兼容
|
|
25
|
+
|
|
26
|
+
`dsh-loop-engine` 与 harness **独立**版本(`1.0.0-rcN`),但通过 `peerDependencies` 绑定到特定 harness 版本;两者必须匹配——不匹配会在启动或会话恢复时响亮地失败:
|
|
27
|
+
|
|
28
|
+
| dsh-loop-engine | 需要 harness |
|
|
29
|
+
|---|---|
|
|
30
|
+
| 1.0.0-rc8 及以后 | **0.1.2-rc.1** |
|
|
31
|
+
| 1.0.0-rc7 及更早 | 0.1.1-rc.2 |
|
|
32
|
+
|
|
33
|
+
- **1.0.0-rc8 及以后不兼容 harness 0.1.1-rc.2 或更早版本。** 它使用 0.1.2 的持久化 seam(`SessionPersistence.create` / `open` + `SessionHandle`)、`installSection` settings API、`ToolCallId` 与 `Session.snapshotEvents()` —— 这些在更老的 harness 里都不存在。
|
|
34
|
+
- 要在更老的 harness 上使用本插件,请安装与之匹配的 loop-engine 版本(例如 harness 0.1.1-rc.2 用 `npm i dsh-loop-engine@1.0.0-rc7`)。
|
|
35
|
+
- 每个 tag 的 GitHub Release 正文会写明它针对的 harness 版本。
|
|
36
|
+
|
|
24
37
|
## 使用方法
|
|
25
38
|
|
|
26
39
|
1. 在 **Settings → Loop engine** 选择引擎——`in-process`(默认)、`claude-code`、`codex`、`pi` 或 `kimi`——然后重启 `dsh web`。
|
package/lib/index.js
CHANGED
|
@@ -1347,6 +1347,11 @@ var ClaudeCodeLoop = class extends Service {
|
|
|
1347
1347
|
const handle = await persistence.create(session.header, {
|
|
1348
1348
|
inheritedEventCount: session.inheritedEventCount,
|
|
1349
1349
|
...signal === void 0 ? {} : { signal }
|
|
1350
|
+
}).catch((error) => {
|
|
1351
|
+
if (error instanceof TypeError && error.message.includes("SessionLogOffset")) {
|
|
1352
|
+
return persistence.create(session.header, session.inheritedEventCount);
|
|
1353
|
+
}
|
|
1354
|
+
throw error;
|
|
1350
1355
|
});
|
|
1351
1356
|
return { handle, storedCount: 0 };
|
|
1352
1357
|
}
|
|
@@ -1395,26 +1400,38 @@ var ClaudeCodeLoop = class extends Service {
|
|
|
1395
1400
|
let preparation;
|
|
1396
1401
|
try {
|
|
1397
1402
|
try {
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1403
|
+
if (typeof persistence.open === "function") {
|
|
1404
|
+
handle = await raceAbortCall(
|
|
1405
|
+
() => persistence.open(id, "write", { signal: fused }),
|
|
1406
|
+
fused,
|
|
1407
|
+
id,
|
|
1408
|
+
(abandoned) => {
|
|
1409
|
+
void abandoned.close();
|
|
1410
|
+
}
|
|
1411
|
+
);
|
|
1412
|
+
const persisted = await handle.read(0, void 0, { signal: fused });
|
|
1413
|
+
fused.throwIfAborted();
|
|
1414
|
+
const closers = interruptedTurnClosers(persisted);
|
|
1415
|
+
if (closers.length > 0) await handle.append(closers);
|
|
1416
|
+
preparation = SessionPreparation.create(this.runtime.ctx.sessions.prepare(id, {
|
|
1417
|
+
seed: [...persisted, ...closers],
|
|
1418
|
+
meta: structuredClone(handle.header),
|
|
1419
|
+
inheritedEventCount: handle.inheritedEventCount,
|
|
1420
|
+
seedSource: "persistence"
|
|
1421
|
+
}));
|
|
1422
|
+
stored = { handle, storedCount: persisted.length + closers.length };
|
|
1423
|
+
await this.appendUnstoredSuffix(stored, preparation.session);
|
|
1424
|
+
} else {
|
|
1425
|
+
const publishedApi = persistence;
|
|
1426
|
+
preparation = await raceAbortCall(
|
|
1427
|
+
() => publishedApi.prepare(id, fused),
|
|
1428
|
+
fused,
|
|
1429
|
+
id,
|
|
1430
|
+
(abandoned) => {
|
|
1431
|
+
abandoned?.[Symbol.dispose]?.();
|
|
1432
|
+
}
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1418
1435
|
} finally {
|
|
1419
1436
|
await unfollowOwner();
|
|
1420
1437
|
}
|
|
@@ -2573,6 +2590,11 @@ var CodexLoop = class extends Service2 {
|
|
|
2573
2590
|
const handle = await persistence.create(session.header, {
|
|
2574
2591
|
inheritedEventCount: session.inheritedEventCount,
|
|
2575
2592
|
...signal === void 0 ? {} : { signal }
|
|
2593
|
+
}).catch((error) => {
|
|
2594
|
+
if (error instanceof TypeError && error.message.includes("SessionLogOffset")) {
|
|
2595
|
+
return persistence.create(session.header, session.inheritedEventCount);
|
|
2596
|
+
}
|
|
2597
|
+
throw error;
|
|
2576
2598
|
});
|
|
2577
2599
|
return { handle, storedCount: 0 };
|
|
2578
2600
|
}
|
|
@@ -2621,26 +2643,38 @@ var CodexLoop = class extends Service2 {
|
|
|
2621
2643
|
let preparation;
|
|
2622
2644
|
try {
|
|
2623
2645
|
try {
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2646
|
+
if (typeof persistence.open === "function") {
|
|
2647
|
+
handle = await raceAbortCall(
|
|
2648
|
+
() => persistence.open(id, "write", { signal: fused }),
|
|
2649
|
+
fused,
|
|
2650
|
+
id,
|
|
2651
|
+
(abandoned) => {
|
|
2652
|
+
void abandoned.close();
|
|
2653
|
+
}
|
|
2654
|
+
);
|
|
2655
|
+
const persisted = await handle.read(0, void 0, { signal: fused });
|
|
2656
|
+
fused.throwIfAborted();
|
|
2657
|
+
const closers = interruptedTurnClosers2(persisted);
|
|
2658
|
+
if (closers.length > 0) await handle.append(closers);
|
|
2659
|
+
preparation = SessionPreparation2.create(this.runtime.ctx.sessions.prepare(id, {
|
|
2660
|
+
seed: [...persisted, ...closers],
|
|
2661
|
+
meta: structuredClone(handle.header),
|
|
2662
|
+
inheritedEventCount: handle.inheritedEventCount,
|
|
2663
|
+
seedSource: "persistence"
|
|
2664
|
+
}));
|
|
2665
|
+
stored = { handle, storedCount: persisted.length + closers.length };
|
|
2666
|
+
await this.appendUnstoredSuffix(stored, preparation.session);
|
|
2667
|
+
} else {
|
|
2668
|
+
const publishedApi = persistence;
|
|
2669
|
+
preparation = await raceAbortCall(
|
|
2670
|
+
() => publishedApi.prepare(id, fused),
|
|
2671
|
+
fused,
|
|
2672
|
+
id,
|
|
2673
|
+
(abandoned) => {
|
|
2674
|
+
abandoned?.[Symbol.dispose]?.();
|
|
2675
|
+
}
|
|
2676
|
+
);
|
|
2677
|
+
}
|
|
2644
2678
|
} finally {
|
|
2645
2679
|
await unfollowOwner();
|
|
2646
2680
|
}
|
|
@@ -3906,6 +3940,11 @@ var PiLoop = class extends Service3 {
|
|
|
3906
3940
|
const handle = await persistence.create(session.header, {
|
|
3907
3941
|
inheritedEventCount: session.inheritedEventCount,
|
|
3908
3942
|
...signal === void 0 ? {} : { signal }
|
|
3943
|
+
}).catch((error) => {
|
|
3944
|
+
if (error instanceof TypeError && error.message.includes("SessionLogOffset")) {
|
|
3945
|
+
return persistence.create(session.header, session.inheritedEventCount);
|
|
3946
|
+
}
|
|
3947
|
+
throw error;
|
|
3909
3948
|
});
|
|
3910
3949
|
return { handle, storedCount: 0 };
|
|
3911
3950
|
}
|
|
@@ -3954,26 +3993,38 @@ var PiLoop = class extends Service3 {
|
|
|
3954
3993
|
let preparation;
|
|
3955
3994
|
try {
|
|
3956
3995
|
try {
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3996
|
+
if (typeof persistence.open === "function") {
|
|
3997
|
+
handle = await raceAbortCall(
|
|
3998
|
+
() => persistence.open(id, "write", { signal: fused }),
|
|
3999
|
+
fused,
|
|
4000
|
+
id,
|
|
4001
|
+
(abandoned) => {
|
|
4002
|
+
void abandoned.close();
|
|
4003
|
+
}
|
|
4004
|
+
);
|
|
4005
|
+
const persisted = await handle.read(0, void 0, { signal: fused });
|
|
4006
|
+
fused.throwIfAborted();
|
|
4007
|
+
const closers = interruptedTurnClosers3(persisted);
|
|
4008
|
+
if (closers.length > 0) await handle.append(closers);
|
|
4009
|
+
preparation = SessionPreparation3.create(this.runtime.ctx.sessions.prepare(id, {
|
|
4010
|
+
seed: [...persisted, ...closers],
|
|
4011
|
+
meta: structuredClone(handle.header),
|
|
4012
|
+
inheritedEventCount: handle.inheritedEventCount,
|
|
4013
|
+
seedSource: "persistence"
|
|
4014
|
+
}));
|
|
4015
|
+
stored = { handle, storedCount: persisted.length + closers.length };
|
|
4016
|
+
await this.appendUnstoredSuffix(stored, preparation.session);
|
|
4017
|
+
} else {
|
|
4018
|
+
const publishedApi = persistence;
|
|
4019
|
+
preparation = await raceAbortCall(
|
|
4020
|
+
() => publishedApi.prepare(id, fused),
|
|
4021
|
+
fused,
|
|
4022
|
+
id,
|
|
4023
|
+
(abandoned) => {
|
|
4024
|
+
abandoned?.[Symbol.dispose]?.();
|
|
4025
|
+
}
|
|
4026
|
+
);
|
|
4027
|
+
}
|
|
3977
4028
|
} finally {
|
|
3978
4029
|
await unfollowOwner();
|
|
3979
4030
|
}
|
|
@@ -5020,6 +5071,11 @@ var KimiLoop = class extends Service4 {
|
|
|
5020
5071
|
const handle = await persistence.create(session.header, {
|
|
5021
5072
|
inheritedEventCount: session.inheritedEventCount,
|
|
5022
5073
|
...signal === void 0 ? {} : { signal }
|
|
5074
|
+
}).catch((error) => {
|
|
5075
|
+
if (error instanceof TypeError && error.message.includes("SessionLogOffset")) {
|
|
5076
|
+
return persistence.create(session.header, session.inheritedEventCount);
|
|
5077
|
+
}
|
|
5078
|
+
throw error;
|
|
5023
5079
|
});
|
|
5024
5080
|
return { handle, storedCount: 0 };
|
|
5025
5081
|
}
|
|
@@ -5068,26 +5124,38 @@ var KimiLoop = class extends Service4 {
|
|
|
5068
5124
|
let preparation;
|
|
5069
5125
|
try {
|
|
5070
5126
|
try {
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5127
|
+
if (typeof persistence.open === "function") {
|
|
5128
|
+
handle = await raceAbortCall(
|
|
5129
|
+
() => persistence.open(id, "write", { signal: fused }),
|
|
5130
|
+
fused,
|
|
5131
|
+
id,
|
|
5132
|
+
(abandoned) => {
|
|
5133
|
+
void abandoned.close();
|
|
5134
|
+
}
|
|
5135
|
+
);
|
|
5136
|
+
const persisted = await handle.read(0, void 0, { signal: fused });
|
|
5137
|
+
fused.throwIfAborted();
|
|
5138
|
+
const closers = interruptedTurnClosers4(persisted);
|
|
5139
|
+
if (closers.length > 0) await handle.append(closers);
|
|
5140
|
+
preparation = SessionPreparation4.create(this.runtime.ctx.sessions.prepare(id, {
|
|
5141
|
+
seed: [...persisted, ...closers],
|
|
5142
|
+
meta: structuredClone(handle.header),
|
|
5143
|
+
inheritedEventCount: handle.inheritedEventCount,
|
|
5144
|
+
seedSource: "persistence"
|
|
5145
|
+
}));
|
|
5146
|
+
stored = { handle, storedCount: persisted.length + closers.length };
|
|
5147
|
+
await this.appendUnstoredSuffix(stored, preparation.session);
|
|
5148
|
+
} else {
|
|
5149
|
+
const publishedApi = persistence;
|
|
5150
|
+
preparation = await raceAbortCall(
|
|
5151
|
+
() => publishedApi.prepare(id, fused),
|
|
5152
|
+
fused,
|
|
5153
|
+
id,
|
|
5154
|
+
(abandoned) => {
|
|
5155
|
+
abandoned?.[Symbol.dispose]?.();
|
|
5156
|
+
}
|
|
5157
|
+
);
|
|
5158
|
+
}
|
|
5091
5159
|
} finally {
|
|
5092
5160
|
await unfollowOwner();
|
|
5093
5161
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-loop-engine",
|
|
3
3
|
"description": "Web-switchable agent loop engine selection for the DeepSeek Harness - out-of-tree plugin (Claude Code / Codex / Pi / Kimi Code drivers) maintained by @kuun993, zero main-repo changes",
|
|
4
|
-
"version": "1.0.0-
|
|
4
|
+
"version": "1.0.0-rc14",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|