@zhushanwen/zcode-subagent-cli 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-F6YT6OGA.js → chunk-NC4FSPIM.js} +89 -376
- package/dist/index.cjs +79 -373
- package/dist/index.d.cts +20 -39
- package/dist/index.d.ts +20 -39
- package/dist/index.js +1 -1
- package/dist/main.cjs +79 -373
- package/dist/main.js +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -61,16 +61,6 @@ var ZCODE_APPSERVER_STDERR_TAIL_CHARS = 400;
|
|
|
61
61
|
var ZCODE_APPSERVER_STDERR_TAIL_BUFFER_CHARS = 2048;
|
|
62
62
|
var ZCODE_APPSERVER_TURN_READ_TIMEOUT_MS = 5e3;
|
|
63
63
|
var ZCODE_APPSERVER_TURN_CLOSE_TIMEOUT_MS = 1500;
|
|
64
|
-
var ZCODE_TURN_IDLE_TIMEOUT_ENV = "TAIJI_ZCODE_TURN_IDLE_TIMEOUT_MS";
|
|
65
|
-
var ZCODE_TURN_MAX_TIMEOUT_ENV = "TAIJI_ZCODE_TURN_MAX_TIMEOUT_MS";
|
|
66
|
-
var ZCODE_TURN_IDLE_TIMEOUT_MS = 18e5;
|
|
67
|
-
var ZCODE_TURN_MAX_TIMEOUT_MS = 36e5;
|
|
68
|
-
function parseZcodeTurnTimeoutEnv(raw) {
|
|
69
|
-
if (raw === void 0 || raw === "") return { state: "unset" };
|
|
70
|
-
const parsed = Number(raw);
|
|
71
|
-
if (!Number.isFinite(parsed)) return { state: "invalid" };
|
|
72
|
-
return { state: "valid", ms: parsed };
|
|
73
|
-
}
|
|
74
64
|
var ZCODE_APPSERVER_STOP_TIMEOUT_MS = 3e3;
|
|
75
65
|
var ZCODE_APPSERVER_ABORT_GRACE_MS = 3e3;
|
|
76
66
|
var ZCODE_APPSERVER_STOP_TIMEOUT_ENV = "TAIJI_ZCODE_TEST_STOP_TIMEOUT_MS";
|
|
@@ -104,9 +94,9 @@ var import_subagent_engine_sdk11 = require("@zhushanwen/subagent-engine-sdk");
|
|
|
104
94
|
var import_subagent_engine_sdk = require("@zhushanwen/subagent-engine-sdk");
|
|
105
95
|
var import_subagent_engine_sdk2 = require("@zhushanwen/subagent-engine-sdk");
|
|
106
96
|
function replayJournalToSessionView(handle, engineId) {
|
|
107
|
-
const
|
|
108
|
-
if (
|
|
109
|
-
const events = (0, import_subagent_engine_sdk2.replayJournal)(
|
|
97
|
+
const eventsPath = handle.data.eventsPath;
|
|
98
|
+
if (eventsPath === void 0) return void 0;
|
|
99
|
+
const events = (0, import_subagent_engine_sdk2.replayJournal)(eventsPath);
|
|
110
100
|
if (events.length === 0) return void 0;
|
|
111
101
|
return (0, import_subagent_engine_sdk2.eventsToSessionView)(events, engineId, (0, import_subagent_engine_sdk2.sessionIdFromHandle)(handle.data));
|
|
112
102
|
}
|
|
@@ -1396,66 +1386,6 @@ function extractResumeTotalTokens(resumeResult) {
|
|
|
1396
1386
|
}
|
|
1397
1387
|
return acc.has ? acc.total : void 0;
|
|
1398
1388
|
}
|
|
1399
|
-
var TurnTimeoutError = class extends Error {
|
|
1400
|
-
kind;
|
|
1401
|
-
elapsed;
|
|
1402
|
-
lastEventAt;
|
|
1403
|
-
thresholdMs;
|
|
1404
|
-
constructor(kind, parts) {
|
|
1405
|
-
super(
|
|
1406
|
-
kind === "idle" ? `zcode turn idle \u5224\u6B7B\uFF1A\u8FDE\u7EED ${parts.thresholdMs}ms \u672A\u89C2\u5BDF\u5230\u672C turn \u4EFB\u4F55\u4E8B\u4EF6\uFF08session/event \u4E0E v4/telemetry/event \u5747\u9759\u9ED8\uFF09\uFF0C\u7EC8\u6001\u672A\u5230\u8FBE\u3002` + (parts.lastEventAt === void 0 ? "\u672C\u8F6E\u81EA send \u8D77\u672A\u89C2\u5BDF\u5230\u4EFB\u4F55\u4E8B\u4EF6\uFF08\u8FDB\u7A0B\u5047\u6B7B/\u534F\u8BAE\u9759\u9ED8\u5F62\u6001\uFF09\u3002" : `\u6700\u540E\u4E8B\u4EF6\u65F6\u523B ${new Date(parts.lastEventAt).toISOString()}\u3002`) + "\u6062\u590D\u6307\u5F15\uFF1A\u76F4\u63A5\u91CD\u8DD1\u672C\u4EFB\u52A1\uFF1B\u82E5\u6301\u7EED\u51FA\u73B0\uFF0C\u68C0\u67E5 ZCode \u684C\u9762\u7AEF\u6A21\u578B\u8FDE\u901A\u6027\u6216\u6539\u7528 engine: pi\u3002" : `zcode turn \u603B\u4E0A\u754C\u5224\u6B7B\uFF1A${parts.thresholdMs}ms \u5185\u672A\u89C2\u5BDF\u5230\u7EC8\u6001\uFF08turn.terminal \u4E0E\u6536\u5C3E\u5E27\u5747\u672A\u5230\u8FBE\uFF1Bidle \u5224\u5B9A\u672A\u89E6\u53D1\u2014\u2014\u4E8B\u4EF6\u6D41\u4ECD\u6D3B\u8DC3\uFF0Cchatty-wedge \u5F62\u6001\uFF09\u3002` + (parts.lastEventAt === void 0 ? "" : `\u6700\u540E\u4E8B\u4EF6\u65F6\u523B ${new Date(parts.lastEventAt).toISOString()}\u3002`) + `\u6062\u590D\u6307\u5F15\uFF1A\u76F4\u63A5\u91CD\u8DD1\u672C\u4EFB\u52A1\uFF1B\u82E5\u672C\u4EFB\u52A1\u5C5E\u5408\u6CD5\u8D85\u957F\u4EFB\u52A1\uFF08\u9884\u671F\u8D85\u8FC7 ${parts.thresholdMs}ms \u603B\u4E0A\u754C\uFF09\uFF0C\u91CD\u8DD1\u524D\u8BBE ${ZCODE_TURN_MAX_TIMEOUT_ENV} \u4E3A\u66F4\u5927\u6BEB\u79D2\u503C\uFF0C\u6216\u8BBE 0 \u5173\u95ED\u603B\u4E0A\u754C\uFF08\u5173\u95ED\u540E chatty \u5F62\u6001\u4E0D\u518D\u81EA\u52A8\u56DE\u6536\uFF0C\u9759\u9ED8 wedged \u4ECD\u7531 idle \u5C42\u515C\u5E95\u2014\u2014\u81EA\u884C\u6743\u8861\uFF09\u3002`
|
|
1407
|
-
);
|
|
1408
|
-
this.name = "TurnTimeoutError";
|
|
1409
|
-
this.kind = kind;
|
|
1410
|
-
this.elapsed = parts.elapsed;
|
|
1411
|
-
this.lastEventAt = parts.lastEventAt;
|
|
1412
|
-
this.thresholdMs = parts.thresholdMs;
|
|
1413
|
-
}
|
|
1414
|
-
};
|
|
1415
|
-
function clearTurnTimers(turn) {
|
|
1416
|
-
if (turn.idleTimer !== void 0) {
|
|
1417
|
-
clearTimeout(turn.idleTimer);
|
|
1418
|
-
turn.idleTimer = void 0;
|
|
1419
|
-
}
|
|
1420
|
-
if (turn.ceilingTimer !== void 0) {
|
|
1421
|
-
clearTimeout(turn.ceilingTimer);
|
|
1422
|
-
turn.ceilingTimer = void 0;
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
function armTurnTimer(onFire, ms) {
|
|
1426
|
-
const timer = setTimeout(onFire, ms);
|
|
1427
|
-
if (typeof timer.unref === "function") timer.unref();
|
|
1428
|
-
return timer;
|
|
1429
|
-
}
|
|
1430
|
-
function resolveTurnTimerMs(parts) {
|
|
1431
|
-
let value;
|
|
1432
|
-
let source;
|
|
1433
|
-
if (parts.explicit !== void 0) {
|
|
1434
|
-
value = parts.explicit;
|
|
1435
|
-
source = "\u663E\u5F0F\u4F20\u53C2";
|
|
1436
|
-
} else {
|
|
1437
|
-
const raw = process.env[parts.envName];
|
|
1438
|
-
const parsed = parseZcodeTurnTimeoutEnv(raw);
|
|
1439
|
-
if (parsed.state === "valid") {
|
|
1440
|
-
value = parsed.ms;
|
|
1441
|
-
source = `env ${parts.envName}=${raw}`;
|
|
1442
|
-
} else {
|
|
1443
|
-
if (parsed.state === "invalid") {
|
|
1444
|
-
logger2.warn(
|
|
1445
|
-
`[session-channel] ${parts.envName}="${raw}" \u975E\u6CD5\uFF08\u5E94\u4E3A\u6BEB\u79D2\u6570\u5B57\uFF09\u2014\u2014\u56DE\u843D\u9ED8\u8BA4 ${parts.fallbackMs}ms\uFF08${parts.label}\uFF09\u3002\u8BBE\u7F6E\u6B63\u6BEB\u79D2\u503C\u8986\u76D6\uFF0C\u6216 0 \u663E\u5F0F\u5173\u95ED`
|
|
1446
|
-
);
|
|
1447
|
-
}
|
|
1448
|
-
value = parts.fallbackMs;
|
|
1449
|
-
source = "\u9ED8\u8BA4\u503C";
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
if (value <= 0) {
|
|
1453
|
-
logger2.warn(
|
|
1454
|
-
`[session-channel] zcode turn ${parts.label}\u5DF2\u5173\u95ED\uFF08${source}\uFF09\u2014\u2014${parts.offConsequence}\u3002\u8BBE\u6B63\u6BEB\u79D2\u503C\uFF08env ${parts.envName} \u6216\u663E\u5F0F\u4F20\u53C2\uFF09\u6062\u590D\u56DE\u6536\u5C42`
|
|
1455
|
-
);
|
|
1456
|
-
}
|
|
1457
|
-
return value;
|
|
1458
|
-
}
|
|
1459
1389
|
var SessionChannel = class {
|
|
1460
1390
|
conn;
|
|
1461
1391
|
/** sessionId → 在途 turn(终态落定后仍保留到 runTurn 收尾——收尾帧数据吸收窗口)。 */
|
|
@@ -1481,23 +1411,23 @@ var SessionChannel = class {
|
|
|
1481
1411
|
),
|
|
1482
1412
|
// 连接崩溃收割:进程死亡(崩溃/我方杀链)立即 fail 全部在途 turn——
|
|
1483
1413
|
// onClose 契约保证触发时连接层在途 request 已全部 reject,此处补齐
|
|
1484
|
-
// 「无在途 request 的 turn
|
|
1414
|
+
// 「无在途 request 的 turn」的收割(否则在途 turn 失去全部终局来源)
|
|
1485
1415
|
conn.onClose((reason) => this.failAllTurns(`app-server ${reason}`))
|
|
1486
1416
|
];
|
|
1487
1417
|
}
|
|
1488
1418
|
/**
|
|
1489
1419
|
* [P0-1 U5/D7] dispose 前收割 + 退订:「退订 = 不会再有事件」在结构上蕴含「在途
|
|
1490
1420
|
* turn 不应再等」——close 缺失/被吞没形态(onClose 收割主路径未触发)下,在途
|
|
1491
|
-
* turn 于退订前经既有 failAllTurns
|
|
1492
|
-
*
|
|
1493
|
-
*
|
|
1494
|
-
*
|
|
1495
|
-
*
|
|
1421
|
+
* turn 于退订前经既有 failAllTurns 收敛为明确失败(设计 §3.4 退化路径闭合;
|
|
1422
|
+
* race 窗口在引擎 shutdownRuntimeAndDisposeChannel,量级与 awaitConnFinalized
|
|
1423
|
+
* 同源 ZCODE_APPSERVER_HARVEST_GRACE_MS)。幂等:与 onClose 收割先到者赢
|
|
1424
|
+
* (turn.fail 的 settled 守卫——已落定 turn 不改写),activeTurns 已空则 no-op。
|
|
1425
|
+
* 不影响连接自身生命周期(R4)。
|
|
1496
1426
|
*/
|
|
1497
1427
|
dispose() {
|
|
1498
1428
|
this.disposed = true;
|
|
1499
1429
|
this.failAllTurns(
|
|
1500
|
-
"zcode session channel \u5DF2 dispose\uFF1A\u8FDE\u63A5 close \u4E8B\u4EF6\u672A\u5728\u6536\u5272\u7A97\u53E3\u5185\u5230\u8FBE\uFF0C\u5728\u9014 turn \u4E8E\u9000\u8BA2\u524D\u6536\u5272\u4E3A\u660E\u786E\u5931\u8D25\
|
|
1430
|
+
"zcode session channel \u5DF2 dispose\uFF1A\u8FDE\u63A5 close \u4E8B\u4EF6\u672A\u5728\u6536\u5272\u7A97\u53E3\u5185\u5230\u8FBE\uFF0C\u5728\u9014 turn \u4E8E\u9000\u8BA2\u524D\u6536\u5272\u4E3A\u660E\u786E\u5931\u8D25\u3002\u6062\u590D\u6307\u5F15\uFF1A\u76F4\u63A5\u91CD\u8DD1\u672C\u4EFB\u52A1\u3002"
|
|
1501
1431
|
);
|
|
1502
1432
|
for (const off of this.offHandlers.splice(0)) off();
|
|
1503
1433
|
}
|
|
@@ -1627,7 +1557,6 @@ var SessionChannel = class {
|
|
|
1627
1557
|
...opened.turn.lastTerminalError !== void 0 ? { lastTerminalError: opened.turn.lastTerminalError } : {}
|
|
1628
1558
|
};
|
|
1629
1559
|
} finally {
|
|
1630
|
-
opened.stopTimers();
|
|
1631
1560
|
this.activeTurns.delete(sessionId);
|
|
1632
1561
|
await this.closeSession(sessionId);
|
|
1633
1562
|
}
|
|
@@ -1648,7 +1577,7 @@ var SessionChannel = class {
|
|
|
1648
1577
|
onTextDelta: opts.onTextDelta,
|
|
1649
1578
|
onThinkingDelta: opts.onThinkingDelta,
|
|
1650
1579
|
// [PR3] tool 执行期活性回调(SessionTurnCallbacks.onActivity 注释——宿主侧
|
|
1651
|
-
//
|
|
1580
|
+
// 的工具执行期刷新面)
|
|
1652
1581
|
onActivity: opts.onActivity
|
|
1653
1582
|
},
|
|
1654
1583
|
settled: false,
|
|
@@ -1658,83 +1587,25 @@ var SessionChannel = class {
|
|
|
1658
1587
|
terminal: void 0,
|
|
1659
1588
|
lastTerminalStatus: void 0,
|
|
1660
1589
|
lastTerminalError: void 0,
|
|
1661
|
-
|
|
1662
|
-
ceilingMs: 0,
|
|
1663
|
-
startedAt: Date.now(),
|
|
1664
|
-
lastEventAt: void 0,
|
|
1665
|
-
idleTimer: void 0,
|
|
1666
|
-
ceilingTimer: void 0,
|
|
1667
|
-
// 装配占位:下方 timer 创建后重绑(settle/fail 需要清理两 timer)
|
|
1590
|
+
// 装配占位:下方重绑(settle/fail 闭包引用 turn 本体)
|
|
1668
1591
|
settle: () => {
|
|
1669
1592
|
},
|
|
1670
1593
|
fail: () => {
|
|
1671
|
-
},
|
|
1672
|
-
fireTimeout: () => {
|
|
1673
1594
|
}
|
|
1674
1595
|
};
|
|
1675
|
-
turn.idleMs = resolveTurnTimerMs({
|
|
1676
|
-
explicit: opts.idleTimeoutMs,
|
|
1677
|
-
envName: ZCODE_TURN_IDLE_TIMEOUT_ENV,
|
|
1678
|
-
fallbackMs: ZCODE_TURN_IDLE_TIMEOUT_MS,
|
|
1679
|
-
label: "idle \u4E3B\u5224\u5B9A",
|
|
1680
|
-
offConsequence: "\u9759\u9ED8 wedged\uFF08\u65E0\u4E8B\u4EF6\uFF09\u5F62\u6001\u5C06\u65E0\u81EA\u52A8\u56DE\u6536\uFF0C\u4EFB\u52A1\u53EF\u80FD\u6302\u5230\u5BBF\u4E3B\u8FDB\u7A0B\u9000\u51FA"
|
|
1681
|
-
});
|
|
1682
|
-
turn.ceilingMs = resolveTurnTimerMs({
|
|
1683
|
-
explicit: opts.turnTimeoutMs,
|
|
1684
|
-
envName: ZCODE_TURN_MAX_TIMEOUT_ENV,
|
|
1685
|
-
fallbackMs: ZCODE_TURN_MAX_TIMEOUT_MS,
|
|
1686
|
-
label: "\u603B\u4E0A\u754C",
|
|
1687
|
-
offConsequence: "chatty-wedge\uFF08\u6709\u4E8B\u4EF6\u65E0\u7EC8\u6001\uFF09\u5F62\u6001\u5C06\u65E0\u81EA\u52A8\u56DE\u6536\uFF0C\u4EC5\u5269 idle \u9759\u9ED8\u5224\u5B9A\u515C\u5E95"
|
|
1688
|
-
});
|
|
1689
|
-
const fireTimeout = (kind) => {
|
|
1690
|
-
if (turn.settled) return;
|
|
1691
|
-
turn.settled = true;
|
|
1692
|
-
clearTurnTimers(turn);
|
|
1693
|
-
this.activeTurns.delete(sessionId);
|
|
1694
|
-
rejectDone(
|
|
1695
|
-
new TurnTimeoutError(kind, {
|
|
1696
|
-
thresholdMs: kind === "idle" ? turn.idleMs : turn.ceilingMs,
|
|
1697
|
-
elapsed: Date.now() - turn.startedAt,
|
|
1698
|
-
lastEventAt: turn.lastEventAt
|
|
1699
|
-
})
|
|
1700
|
-
);
|
|
1701
|
-
};
|
|
1702
|
-
turn.fireTimeout = fireTimeout;
|
|
1703
|
-
if (turn.idleMs > 0) {
|
|
1704
|
-
turn.idleTimer = armTurnTimer(() => turn.fireTimeout("idle"), turn.idleMs);
|
|
1705
|
-
}
|
|
1706
|
-
if (turn.ceilingMs > 0) {
|
|
1707
|
-
turn.ceilingTimer = armTurnTimer(
|
|
1708
|
-
() => turn.fireTimeout("ceiling"),
|
|
1709
|
-
turn.ceilingMs
|
|
1710
|
-
);
|
|
1711
|
-
}
|
|
1712
1596
|
turn.settle = (t) => {
|
|
1713
1597
|
if (turn.settled) return;
|
|
1714
1598
|
turn.settled = true;
|
|
1715
1599
|
turn.terminal = t;
|
|
1716
|
-
clearTurnTimers(turn);
|
|
1717
1600
|
resolveDone(t);
|
|
1718
1601
|
};
|
|
1719
1602
|
turn.fail = (err) => {
|
|
1720
1603
|
if (turn.settled) return;
|
|
1721
1604
|
turn.settled = true;
|
|
1722
|
-
clearTurnTimers(turn);
|
|
1723
1605
|
rejectDone(err);
|
|
1724
1606
|
};
|
|
1725
1607
|
this.activeTurns.set(sessionId, turn);
|
|
1726
|
-
return { turn, done
|
|
1727
|
-
}
|
|
1728
|
-
/**
|
|
1729
|
-
* idle 主判定的事件刷新(P0-1 D1):本 turn 任何事件到达即重置 idle 倒数——
|
|
1730
|
-
* 活跃事件流零误杀的结构保证。总上界不受影响(固定倒数)。已落定 turn 无
|
|
1731
|
-
* timer 可刷新(只剩 lastEventAt 记账)。
|
|
1732
|
-
*/
|
|
1733
|
-
refreshIdle(turn) {
|
|
1734
|
-
turn.lastEventAt = Date.now();
|
|
1735
|
-
if (turn.settled || turn.idleTimer === void 0) return;
|
|
1736
|
-
clearTimeout(turn.idleTimer);
|
|
1737
|
-
turn.idleTimer = armTurnTimer(() => turn.fireTimeout("idle"), turn.idleMs);
|
|
1608
|
+
return { turn, done };
|
|
1738
1609
|
}
|
|
1739
1610
|
lookupTurn(sessionId) {
|
|
1740
1611
|
if (sessionId !== void 0) return this.activeTurns.get(sessionId);
|
|
@@ -1764,7 +1635,6 @@ var SessionChannel = class {
|
|
|
1764
1635
|
if (turn === void 0) return;
|
|
1765
1636
|
const payload = isRecord3(params) && isRecord3(params.payload) ? params.payload : void 0;
|
|
1766
1637
|
if (payload === void 0) return;
|
|
1767
|
-
this.refreshIdle(turn);
|
|
1768
1638
|
if (this.applyFinalFrame(turn, payload)) return;
|
|
1769
1639
|
if (!this.applyStreamDelta(turn, payload) && !turn.settled) {
|
|
1770
1640
|
turn.callbacks.onActivity?.();
|
|
@@ -1881,7 +1751,6 @@ var SessionChannel = class {
|
|
|
1881
1751
|
applyStreamChunkTelemetry(params) {
|
|
1882
1752
|
const turn = this.lookupTurn(extractPushSessionId(params));
|
|
1883
1753
|
if (turn === void 0 || turn.settled) return;
|
|
1884
|
-
this.refreshIdle(turn);
|
|
1885
1754
|
for (const key of ["chunk", "text", "content"]) {
|
|
1886
1755
|
const v = params[key];
|
|
1887
1756
|
if (typeof v === "string" && v !== "") {
|
|
@@ -2237,30 +2106,19 @@ var ZcodeEngine = class {
|
|
|
2237
2106
|
* 只在最终轮终态后合成(不变量 2/5)。
|
|
2238
2107
|
*/
|
|
2239
2108
|
async runAppServerAttemptsWithRetry(task, ctx, modelRef, cwd, basePrompt, schema, usageAcc) {
|
|
2240
|
-
const attemptStartedAt = Date.now();
|
|
2241
2109
|
let final = await this.attemptAppServerTurn(task, ctx, modelRef, cwd, basePrompt);
|
|
2242
2110
|
accumulateUsage(usageAcc, final);
|
|
2243
2111
|
if (final.kind === "run-failed" && final.transient !== void 0 && ctx.signal?.aborted !== true && !this.disposed) {
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
// 预算继承传递点(D2 内部传参面):显式预算 → 剩余值;无显式预算 → 缺省
|
|
2255
|
-
// (channel 侧走同一 env/默认,与首轮行为一致)
|
|
2256
|
-
...budget.state === "inherit" ? { turnTimeoutMs: budget.remainingMs } : {},
|
|
2257
|
-
// 重试事实进文案:「已自动重试一次」句仅对真实发生的重试生效(未重试形态
|
|
2258
|
-
// 不含——与行为一致,§5.2 F-1/F-4)
|
|
2259
|
-
retried: true
|
|
2260
|
-
});
|
|
2261
|
-
accumulateUsage(usageAcc, retry);
|
|
2262
|
-
final = retry;
|
|
2263
|
-
}
|
|
2112
|
+
logger4.warn(
|
|
2113
|
+
`[zcode-engine] \u672B\u6B21 attempt \u77AC\u65F6\u5931\u8D25\uFF08${final.transient}\uFF09\u2014\u2014\u6B62\u635F\u94FE\u5DF2\u7EC8\u5C40\uFF0C\u65B0\u4F1A\u8BDD\u81EA\u52A8\u91CD\u8BD5\u4E00\u6B21`
|
|
2114
|
+
);
|
|
2115
|
+
const retry = await this.attemptAppServerTurn(task, ctx, modelRef, cwd, basePrompt, {
|
|
2116
|
+
// 重试事实进文案:「已自动重试一次」句仅对真实发生的重试生效(未重试形态
|
|
2117
|
+
// 不含——与行为一致,§5.2 F-1/F-4)
|
|
2118
|
+
retried: true
|
|
2119
|
+
});
|
|
2120
|
+
accumulateUsage(usageAcc, retry);
|
|
2121
|
+
final = retry;
|
|
2264
2122
|
}
|
|
2265
2123
|
if (final.kind === "parsed" && final.schemaResult !== void 0 && !final.schemaResult.ok && schema !== void 0) {
|
|
2266
2124
|
const retryPrompt = appendSchemaRetryDirective(basePrompt, final.schemaResult.error);
|
|
@@ -2292,9 +2150,7 @@ var ZcodeEngine = class {
|
|
|
2292
2150
|
* 单轮常驻执行:runTurn 组合面 + D3 abort 链 + 事件前移(text_delta 实时流出;
|
|
2293
2151
|
* 终态数据经 read 兜底收口后才 resolve——不变量 1/2)。
|
|
2294
2152
|
*
|
|
2295
|
-
* @param opts
|
|
2296
|
-
* 向重试轮传剩余值;缺省不传(channel 走 env→默认,首轮行为)。
|
|
2297
|
-
* retried:瞬时重试轮标记——失败文案补「已自动重试一次」句(F-1/F-4)。
|
|
2153
|
+
* @param opts retried:瞬时重试轮标记——失败文案补「已自动重试一次」句(F-1/F-4)。
|
|
2298
2154
|
*/
|
|
2299
2155
|
async attemptAppServerTurn(task, ctx, modelRef, cwd, prompt, opts = {}) {
|
|
2300
2156
|
const rt = this.ensureAppServerRuntime();
|
|
@@ -2324,12 +2180,10 @@ var ZcodeEngine = class {
|
|
|
2324
2180
|
ctx.onHandleReady?.({
|
|
2325
2181
|
sessionRef: { dbPath: zcodeSessionDbPath(this.deps.engineDataDir()), sessionId }
|
|
2326
2182
|
});
|
|
2327
|
-
}
|
|
2328
|
-
// 显式总上界传参(D2/U4:缺省缺席——channel 侧 resolveTurnTimerMs 走 env→默认)
|
|
2329
|
-
...opts.turnTimeoutMs !== void 0 ? { turnTimeoutMs: opts.turnTimeoutMs } : {}
|
|
2183
|
+
}
|
|
2330
2184
|
});
|
|
2331
2185
|
const onAbort = () => {
|
|
2332
|
-
void this.appServerAbortChain(rt, turn, () => currentSessionId, sessionCreated
|
|
2186
|
+
void this.appServerAbortChain(rt, turn, () => currentSessionId, sessionCreated);
|
|
2333
2187
|
};
|
|
2334
2188
|
if (ctx.signal !== void 0) {
|
|
2335
2189
|
if (ctx.signal.aborted) onAbort();
|
|
@@ -2355,32 +2209,16 @@ var ZcodeEngine = class {
|
|
|
2355
2209
|
/**
|
|
2356
2210
|
* [attemptAppServerTurn 拆分] 失败分流(catch 半边):
|
|
2357
2211
|
* - signal 已 aborted → 中止终态收口;
|
|
2358
|
-
* - [P0-1
|
|
2359
|
-
* 再挂在 turn 落定上(race 恒真,killChain 结构性不可达的 v1 击穿点),改以
|
|
2360
|
-
* stop 应答三态裁决。await 链终局(非 fire-and-forget):outcome 止损文案与
|
|
2361
|
-
* 重试时序(D6,u-z4)都依赖链终局信号——止损完成前不合成终态。timeout 类
|
|
2362
|
-
* (idle/ceiling 都算)是 D6 明文的可重试形态——结构化标记
|
|
2363
|
-
* (TurnTimeoutError 类型化判据,不经字符串匹配,D4 同精神);
|
|
2364
|
-
* - [P0-1 U4] 连接崩溃收割形态(failAllTurns 的错误,D6 第二可重试形态)判据:
|
|
2212
|
+
* - [P0-1 U4] 连接崩溃收割形态(failAllTurns 的错误,D6 可重试形态)判据:
|
|
2365
2213
|
* 非 RPC error(服务端无明确应答——有应答即精确错误归类,非瞬时崩溃面)且
|
|
2366
2214
|
* conn 不存活。时序可靠性:catch 时刻紧随 onClose 收割,连接重建仅由
|
|
2367
2215
|
* conn.request 惰性触发——本链路中 runTurn finally 的 closeSession 对死连接
|
|
2368
|
-
* 短路(channel 侧 !alive 守卫)、stop 只属 abort
|
|
2369
|
-
*
|
|
2216
|
+
* 短路(channel 侧 !alive 守卫)、stop 只属 abort 链(已被 signal.aborted
|
|
2217
|
+
* 短路)——此刻无 request 可重建,判据可靠;
|
|
2370
2218
|
* - 其余 → 精确错误终态。
|
|
2371
2219
|
*/
|
|
2372
2220
|
async classifyAppServerTurnFailure(err, ctx, args) {
|
|
2373
2221
|
if (ctx.signal?.aborted === true) return abortedAppServerAttempt(ctx);
|
|
2374
|
-
if (err instanceof TurnTimeoutError) {
|
|
2375
|
-
const stopPath = await this.appServerAbortChain(
|
|
2376
|
-
args.rt,
|
|
2377
|
-
args.turn,
|
|
2378
|
-
args.currentSessionId,
|
|
2379
|
-
args.sessionCreated,
|
|
2380
|
-
{ escalateOn: "stop-outcome" }
|
|
2381
|
-
);
|
|
2382
|
-
return timeoutAppServerAttempt(err, args.currentSessionId(), stopPath, { retried: args.retried });
|
|
2383
|
-
}
|
|
2384
2222
|
if (!isAppServerRpcError(err) && !args.rt.conn.alive) {
|
|
2385
2223
|
return failedAppServerAttempt(err, args.currentSessionId(), { retried: args.retried, transient: "conn-closed" });
|
|
2386
2224
|
}
|
|
@@ -2391,8 +2229,8 @@ var ZcodeEngine = class {
|
|
|
2391
2229
|
* shutdown resolve 于 `exit` 事件,而 finalize 挂 `close`(stdio 排空)——两者之间的
|
|
2392
2230
|
* 事件窗口内 conn.child 仍非 null,紧接的下一任务 request 会复用垂死进程(写入成功
|
|
2393
2231
|
* 但必败,走崩溃路径)而非触发重建。与 shutdownRuntimeAndDisposeChannel 的
|
|
2394
|
-
* HARVEST_GRACE 同款 race 形态(close
|
|
2395
|
-
*
|
|
2232
|
+
* HARVEST_GRACE 同款 race 形态(close 永不到达不挂死)。abort 链的 await 终局
|
|
2233
|
+
* 语义因此是「进程收割确认完成」而非「SIGTERM 已发出」。
|
|
2396
2234
|
*/
|
|
2397
2235
|
async awaitConnFinalized(rt) {
|
|
2398
2236
|
if (!rt.conn.alive) return;
|
|
@@ -2408,25 +2246,14 @@ var ZcodeEngine = class {
|
|
|
2408
2246
|
});
|
|
2409
2247
|
}
|
|
2410
2248
|
/**
|
|
2411
|
-
* D3 abort
|
|
2412
|
-
*
|
|
2413
|
-
*
|
|
2414
|
-
*
|
|
2415
|
-
*
|
|
2416
|
-
*
|
|
2417
|
-
* (带上限)再发 stop——否则 stop 永远发不出,直接连坐杀共享进程。
|
|
2418
|
-
* - **超时入口**(`escalateOn: "stop-outcome"`,channel 判死后由 catch await 链终局):
|
|
2419
|
-
* turn 已 reject,对它 race 恒真不可用(v1 击穿点)——升级判据改挂在 **stop 应答
|
|
2420
|
-
* 三态**:①成功应答 → 服务端接受停 turn,止损确认,链终止;②协议性 error 应答
|
|
2421
|
-
* (有 error 帧即控制面活的证据,多因 runTurn finally 的 closeSession 先行关会话,
|
|
2422
|
-
* 健康形态竞态)→ 链终止**不升级**(止损由 close 回收 + 服务端自治承担;把
|
|
2423
|
-
* 「stop 报错」一律升级会误杀健康共享进程并连坐并发任务);③超时/写入失败/进程
|
|
2424
|
-
* 死等连接级失败(控制面死)→ killChain 升级。判据实现依据:error 应答帧 reject
|
|
2425
|
-
* 携带 number code(isAppServerRpcError);连接级失败是无 code 的新 Error
|
|
2426
|
-
* (connection.request 三态 reject 形态)。返回值即止损路径(超时入口的 outcome
|
|
2427
|
-
* 文案素材——D3 强制可观测面)。
|
|
2249
|
+
* D3 abort 链执行体(用户取消入口,fire-and-forget——与 turn promise 并行推进):
|
|
2250
|
+
* stop 帧(超时 ZCODE_APPSERVER_STOP_TIMEOUT_MS)→ grace 窗口内 turn 落定即止
|
|
2251
|
+
* (不杀共享进程)→ 超窗 killChain(conn.shutdown 全序:SIGTERM→grace→SIGKILL)。
|
|
2252
|
+
* turn 的最终落定由 attempt 主路径 await 收口,本链不直接产出终态。abort 与 create
|
|
2253
|
+
* 竞态(signal 先到、session 未建立):等会话建立(带上限)再发 stop——否则 stop
|
|
2254
|
+
* 永远发不出,直接连坐杀共享进程。
|
|
2428
2255
|
*/
|
|
2429
|
-
async appServerAbortChain(rt, turn, getSessionId, sessionCreated
|
|
2256
|
+
async appServerAbortChain(rt, turn, getSessionId, sessionCreated) {
|
|
2430
2257
|
const graceRaceThenKill = async () => {
|
|
2431
2258
|
const settled = await Promise.race([
|
|
2432
2259
|
turn.then(
|
|
@@ -2435,49 +2262,31 @@ var ZcodeEngine = class {
|
|
|
2435
2262
|
),
|
|
2436
2263
|
delayResolved(abortGraceMs(), false)
|
|
2437
2264
|
]);
|
|
2438
|
-
if (settled) return
|
|
2265
|
+
if (settled) return;
|
|
2439
2266
|
logger4.warn(
|
|
2440
2267
|
`[zcode-engine] abort grace \u7A97\u53E3\u5185\u672A\u89C1\u7EC8\u6001\u2014\u2014killChain \u6536\u5272\u5171\u4EAB\u8FDB\u7A0B\uFF08\u63A5\u53D7\u8FDE\u5750\uFF0C\u5728\u9014\u4EFB\u52A1\u8D70\u5D29\u6E83\u8DEF\u5F84\uFF09`
|
|
2441
2268
|
);
|
|
2442
2269
|
await rt.conn.shutdown({ graceMs: ZCODE_KILL_GRACE_MS });
|
|
2443
2270
|
await this.awaitConnFinalized(rt);
|
|
2444
|
-
return "escalated-kill";
|
|
2445
2271
|
};
|
|
2446
2272
|
let sessionId = getSessionId();
|
|
2447
2273
|
if (sessionId === void 0) {
|
|
2448
2274
|
await Promise.race([sessionCreated, delayResolved(stopTimeoutMs(), void 0)]);
|
|
2449
2275
|
sessionId = getSessionId();
|
|
2450
2276
|
if (sessionId === void 0) {
|
|
2451
|
-
if (entry.escalateOn === "stop-outcome") return "no-session";
|
|
2452
2277
|
return graceRaceThenKill();
|
|
2453
2278
|
}
|
|
2454
2279
|
}
|
|
2455
2280
|
if (!rt.conn.alive) {
|
|
2456
|
-
if (entry.escalateOn === "stop-outcome") return "stop-unreachable-killed";
|
|
2457
2281
|
return graceRaceThenKill();
|
|
2458
2282
|
}
|
|
2459
2283
|
try {
|
|
2460
2284
|
await rt.conn.request("session/stop", { sessionId }, { timeoutMs: stopTimeoutMs() });
|
|
2461
2285
|
} catch (err) {
|
|
2462
|
-
if (entry.escalateOn === "stop-outcome") {
|
|
2463
|
-
if (isAppServerRpcError(err)) {
|
|
2464
|
-
logger4.debug(
|
|
2465
|
-
`[zcode-engine] session/stop \u62A5\u534F\u8BAE\u6027 error\uFF08${errMessage3(err)}\uFF09\u2014\u2014\u4F1A\u8BDD\u5DF2\u56DE\u6536\uFF0C\u63A7\u5236\u9762\u5B58\u6D3B\uFF0C\u4E0D\u5347\u7EA7\u6740\u94FE`
|
|
2466
|
-
);
|
|
2467
|
-
return "stop-rejected";
|
|
2468
|
-
}
|
|
2469
|
-
logger4.warn(
|
|
2470
|
-
`[zcode-engine] session/stop \u65E0\u5E94\u7B54\uFF08${errMessage3(err)}\uFF09\u2014\u2014\u5347\u7EA7 killChain \u6536\u5272\u5171\u4EAB\u8FDB\u7A0B\uFF08\u8D85\u65F6\u5165\u53E3\uFF0C\u63A5\u53D7\u8FDE\u5750\uFF09`
|
|
2471
|
-
);
|
|
2472
|
-
await rt.conn.shutdown({ graceMs: ZCODE_KILL_GRACE_MS });
|
|
2473
|
-
await this.awaitConnFinalized(rt);
|
|
2474
|
-
return "stop-unreachable-killed";
|
|
2475
|
-
}
|
|
2476
2286
|
logger4.debug(
|
|
2477
2287
|
`[zcode-engine] session/stop \u5931\u8D25\uFF08${errMessage3(err)}\uFF09\u2014\u2014grace \u540E\u8D70 killChain \u515C\u5E95`
|
|
2478
2288
|
);
|
|
2479
2289
|
}
|
|
2480
|
-
if (entry.escalateOn === "stop-outcome") return "stop-acked";
|
|
2481
2290
|
return graceRaceThenKill();
|
|
2482
2291
|
}
|
|
2483
2292
|
// ── 常驻运行时管理(D1/D6)──────────────────────
|
|
@@ -2531,15 +2340,15 @@ var ZcodeEngine = class {
|
|
|
2531
2340
|
* [R5 修复 R4 既有竞态] shutdown → 等崩溃收割实际发生 → channel 退订。killChain 在
|
|
2532
2341
|
* `exit` 事件 resolve,而连接 finalize(onClose → channel 的 failAllTurns)挂
|
|
2533
2342
|
* `close` 事件——两者之间有一个事件循环窗口:shutdown resolve 后立即退订,在途
|
|
2534
|
-
* turn
|
|
2343
|
+
* turn 会错过收割而失去终局来源。退订前等 onClose 触发(本方法先于
|
|
2535
2344
|
* shutdown 订阅;channel 的订阅在构造期更早——其 failAllTurns 先于本 promise
|
|
2536
2345
|
* resolve 执行);ZCODE_APPSERVER_HARVEST_GRACE_MS 兜底防 `close` 永不到达时挂死。
|
|
2537
2346
|
* [P0-1 U5/D7] grace race 输掉(close 迟到/永不到达——stdio 被孙进程持有排空不
|
|
2538
2347
|
* 尽等病态形态)时,channel.dispose() 内置的 dispose 收割(failAllTurns 先于退订,
|
|
2539
|
-
* SessionChannel.dispose)兜底在途 turn
|
|
2540
|
-
*
|
|
2541
|
-
*
|
|
2542
|
-
*
|
|
2348
|
+
* SessionChannel.dispose)兜底在途 turn——在途 turn 收敛为「grace 窗口内明确失败」
|
|
2349
|
+
* (设计 §3.4 退化路径闭合);race 窗口与 awaitConnFinalized 同源同量级
|
|
2350
|
+
* (ZCODE_APPSERVER_HARVEST_GRACE_MS)。正常 close 先到时 onClose 收割先行,
|
|
2351
|
+
* dispose 收割幂等 no-op(零回归)。
|
|
2543
2352
|
*/
|
|
2544
2353
|
async shutdownRuntimeAndDisposeChannel(rt) {
|
|
2545
2354
|
const harvested = new Promise((resolve2) => {
|
|
@@ -2578,10 +2387,7 @@ var ZcodeEngine = class {
|
|
|
2578
2387
|
engineId: ZCODE_ENGINE_ID,
|
|
2579
2388
|
content: "",
|
|
2580
2389
|
durationMs: Date.now() - startedAt,
|
|
2581
|
-
...typeof task.worktree === "object" && task.worktree !== null ? { worktreePath: task.worktree.path } : {}
|
|
2582
|
-
// D9① fallback 留痕:路由层经 RunContext 投影(zcode 无 record 通路,outcome 是
|
|
2583
|
-
// 唯一留痕面;pi 引擎另有 record 投影)
|
|
2584
|
-
...ctx.engineFallback !== void 0 ? { engineFallback: ctx.engineFallback } : {}
|
|
2390
|
+
...typeof task.worktree === "object" && task.worktree !== null ? { worktreePath: task.worktree.path } : {}
|
|
2585
2391
|
};
|
|
2586
2392
|
const emit = (event) => {
|
|
2587
2393
|
ctx.onEvent?.(event);
|
|
@@ -2676,7 +2482,7 @@ var ZcodeEngine = class {
|
|
|
2676
2482
|
* D6 read 三级降级:①sqlite 原生读取 → ②宿主 event journal 重放(对齐点①接线:
|
|
2677
2483
|
* replayJournalToSessionView 复用 live reducer,重放等价性见 §3.3.6)→ ③outcome-only。
|
|
2678
2484
|
* sessionId 缺失(解析失败的 run 无法定位 session)跳过①级;②级依赖
|
|
2679
|
-
* handle.
|
|
2485
|
+
* handle.eventsPath(宿主 run 后回填)。dbPath:新 handle 恒为隔离库绝对路径
|
|
2680
2486
|
* (zcodeSessionDbPath(engineDataDir),tier1 白名单集合见方法体——宿主路径仅
|
|
2681
2487
|
* 「共享 HOME 时代」存量兼容);旧 records(池时代)的相对路径仍按池目录锚定
|
|
2682
2488
|
* 解析(read 兼容旧数据,池目录不存在时自然落②级 journal 降级)。[池抽象降级
|
|
@@ -2847,16 +2653,6 @@ ${omissionNote}${kept.join("\n")}
|
|
|
2847
2653
|
function buildResumeUnavailableNoticeSegment() {
|
|
2848
2654
|
return "[\u4F1A\u8BDD\u5EF6\u7EED\u63D0\u793A] \u672C\u6D88\u606F\u662F\u540C\u4E00\u4EFB\u52A1\u7684\u5EF6\u7EED\u4F1A\u8BDD\uFF0C\u4F46\u4E0A\u4E00\u4F1A\u8BDD\u7684\u5386\u53F2\u8BB0\u5F55\u4E0D\u53EF\u6062\u590D\uFF08\u539F\u59CB\u4F1A\u8BDD\u5DF2\u5931\u6548\uFF09\u3002\n\u6CA1\u6709\u66F4\u65E9\u7684\u5BF9\u8BDD\u4E0A\u4E0B\u6587\u53EF\u5F15\u7528\u2014\u2014\u8BF7\u57FA\u4E8E\u4E0B\u65B9\u6700\u65B0\u6D88\u606F\u72EC\u7ACB\u5224\u65AD\u5E76\u7EE7\u7EED\u63A8\u8FDB\u4EFB\u52A1\u3002\n\n";
|
|
2849
2655
|
}
|
|
2850
|
-
var ZCODE_TURN_RETRY_MIN_BUDGET_MS = 3e5;
|
|
2851
|
-
function resolveTransientRetryBudget(totalBudgetMs, consumedMs) {
|
|
2852
|
-
if (totalBudgetMs === void 0) return { state: "unbounded" };
|
|
2853
|
-
const remainingMs = totalBudgetMs - consumedMs;
|
|
2854
|
-
return remainingMs >= ZCODE_TURN_RETRY_MIN_BUDGET_MS ? { state: "inherit", remainingMs } : { state: "depleted" };
|
|
2855
|
-
}
|
|
2856
|
-
function explicitTurnBudgetMs() {
|
|
2857
|
-
const parsed = parseZcodeTurnTimeoutEnv(process.env[ZCODE_TURN_MAX_TIMEOUT_ENV]);
|
|
2858
|
-
return parsed.state === "valid" && parsed.ms > 0 ? parsed.ms : void 0;
|
|
2859
|
-
}
|
|
2860
2656
|
function isPlainObject(v) {
|
|
2861
2657
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2862
2658
|
}
|
|
@@ -3002,8 +2798,7 @@ function failedAppServerAttempt(err, currentSessionId, opts = {}) {
|
|
|
3002
2798
|
kind: "run-failed",
|
|
3003
2799
|
output: syntheticAppServerOutput(null),
|
|
3004
2800
|
message: buildAppServerRunFailedMessage(err, currentSessionId, opts.retried === true),
|
|
3005
|
-
// [P0-1 U4/D6]
|
|
3006
|
-
// timeoutAppServerAttempt,此处只承载 conn-closed)
|
|
2801
|
+
// [P0-1 U4/D6] 瞬时失败形态标记(重试判定判据,conn-closed 连接崩溃形态)
|
|
3007
2802
|
...opts.transient !== void 0 ? { transient: opts.transient } : {},
|
|
3008
2803
|
// 错误规格表 -32004 行「按任务失败上报(含会话 id)」:create 成功后运行中失败
|
|
3009
2804
|
// (-32004/-32010 等)时留痕会话 id——经 applyRunFailedOutcome 落 outcome.sessionId
|
|
@@ -3011,38 +2806,6 @@ function failedAppServerAttempt(err, currentSessionId, opts = {}) {
|
|
|
3011
2806
|
...currentSessionId !== void 0 ? { sessionId: currentSessionId } : {}
|
|
3012
2807
|
};
|
|
3013
2808
|
}
|
|
3014
|
-
function timeoutAppServerAttempt(err, currentSessionId, stopPath, opts = {}) {
|
|
3015
|
-
return {
|
|
3016
|
-
kind: "run-failed",
|
|
3017
|
-
output: syntheticAppServerOutput(null),
|
|
3018
|
-
message: buildAppServerTimeoutMessage(err, currentSessionId, stopPath, opts.retried === true),
|
|
3019
|
-
transient: "timeout",
|
|
3020
|
-
...currentSessionId !== void 0 ? { sessionId: currentSessionId } : {}
|
|
3021
|
-
};
|
|
3022
|
-
}
|
|
3023
|
-
function stopPathText(stopPath) {
|
|
3024
|
-
switch (stopPath) {
|
|
3025
|
-
case "stop-acked":
|
|
3026
|
-
return "session/stop \u5DF2\u9001\u8FBE\uFF08\u670D\u52A1\u7AEF\u63A5\u53D7\u505C turn\uFF09";
|
|
3027
|
-
case "stop-rejected":
|
|
3028
|
-
return "session/stop \u62A5\u534F\u8BAE\u6027 error\uFF08\u4F1A\u8BDD\u5DF2\u88AB\u56DE\u6536\uFF0C\u63A7\u5236\u9762\u5B58\u6D3B\u2014\u2014\u6B62\u635F\u7531\u4F1A\u8BDD\u56DE\u6536\u627F\u62C5\uFF0C\u4E0D\u5347\u7EA7\u6740\u94FE\uFF09";
|
|
3029
|
-
case "stop-unreachable-killed":
|
|
3030
|
-
return `session/stop \u65E0\u5E94\u7B54\u5DF2\u5347\u7EA7\u6740\u94FE\uFF08SIGTERM\u2192${ZCODE_KILL_GRACE_MS}ms\u2192SIGKILL \u6536\u5272\u5171\u4EAB\u8FDB\u7A0B\uFF09`;
|
|
3031
|
-
case "no-session":
|
|
3032
|
-
return "\u4F1A\u8BDD\u672A\u5EFA\u7ACB\uFF08\u4EFB\u52A1\u672A\u5F00\u59CB\u6267\u884C\uFF0C\u65E0\u5728\u9014\u6D88\u8017\uFF09";
|
|
3033
|
-
default:
|
|
3034
|
-
return "grace \u7A97\u53E3\u5185\u7EC8\u6001\u843D\u5B9A\u6216\u5DF2\u8D70\u6740\u94FE";
|
|
3035
|
-
}
|
|
3036
|
-
}
|
|
3037
|
-
function buildAppServerTimeoutMessage(err, sessionId, stopPath, retried = false) {
|
|
3038
|
-
const sid = sessionId !== void 0 ? `\uFF08\u4F1A\u8BDD ${sessionId}\uFF09` : "";
|
|
3039
|
-
const lastEventText = err.lastEventAt !== void 0 ? `\uFF0C\u6700\u540E\u4E8B\u4EF6 ${new Date(err.lastEventAt).toISOString()}` : "\uFF0C\u6574\u8F6E\u672A\u89C2\u5BDF\u5230\u4EFB\u4F55\u4E8B\u4EF6\uFF08\u8FDB\u7A0B\u5047\u6B7B/\u534F\u8BAE\u9759\u9ED8\u5F62\u6001\uFF09";
|
|
3040
|
-
const head = err.kind === "idle" ? `engine_timeout: zcode turn \u8FDE\u7EED\u9759\u9ED8 ${err.thresholdMs}ms\uFF08idle \u5224\u5B9A${lastEventText}\uFF0C\u603B\u8017\u65F6 ${err.elapsed}ms\uFF09${sid}\u3002` : `engine_timeout: zcode turn \u603B\u4E0A\u754C ${err.thresholdMs}ms \u5185\u672A\u89C2\u5BDF\u5230\u7EC8\u6001\uFF08chatty-wedge \u5224\u5B9A\u2014\u2014\u4E8B\u4EF6\u6D41\u4ECD\u6D3B\u8DC3\u800C\u7EC8\u6001\u672A\u5230\u8FBE\uFF0C\u603B\u8017\u65F6 ${err.elapsed}ms\uFF09${sid}\u3002`;
|
|
3041
|
-
const selfHelp = err.kind === "ceiling" ? `\u82E5\u672C\u4EFB\u52A1\u5C5E\u5408\u6CD5\u8D85\u957F\u4EFB\u52A1\uFF08\u9884\u671F\u8D85\u8FC7 ${err.thresholdMs}ms\uFF09\uFF0C\u91CD\u8DD1\u524D\u8BBE ${ZCODE_TURN_MAX_TIMEOUT_ENV} \u4E3A\u66F4\u5927\u6BEB\u79D2\u503C\u6216 0 \u5173\u95ED\u603B\u4E0A\u754C\uFF08\u5173\u95ED\u540E chatty \u5F62\u6001\u4E0D\u518D\u81EA\u52A8\u56DE\u6536\uFF0C\u9759\u9ED8 wedged \u4ECD\u7531 idle \u5C42\u515C\u5E95\u2014\u2014\u81EA\u884C\u6743\u8861\uFF09\u3002` : "";
|
|
3042
|
-
const rerunGuide = retried ? `\u{1F449} \u6062\u590D\u6307\u5F15\uFF1A\u76F4\u63A5\u91CD\u8DD1\u672C\u4EFB\u52A1\uFF08\u77AC\u65F6\u6545\u969C\u5DF2\u81EA\u52A8\u91CD\u8BD5\u4E00\u6B21\u4ECD\u8D85\u65F6\uFF1B\u91CD\u8BD5\u5728\u6B62\u635F\u94FE\u7EC8\u5C40\u540E\u542F\u52A8\uFF0C\u65E0\u65B0\u65E7\u4EFB\u52A1\u53CC\u8DD1\u7A97\uFF09\uFF1B` : `\u{1F449} \u6062\u590D\u6307\u5F15\uFF1A\u76F4\u63A5\u91CD\u8DD1\u672C\u4EFB\u52A1\uFF1B`;
|
|
3043
|
-
return `${head}\u6B62\u635F\u8DEF\u5F84\uFF1A${stopPathText(stopPath)}\u3002
|
|
3044
|
-
${rerunGuide}${selfHelp}\u82E5\u6301\u7EED\u51FA\u73B0\uFF0C\u68C0\u67E5 ZCode \u684C\u9762\u7AEF\u6A21\u578B\u8FDE\u901A\u6027\u6216\u6539\u7528 engine: pi\u3002`;
|
|
3045
|
-
}
|
|
3046
2809
|
function isHostTimeoutAbort(ctx) {
|
|
3047
2810
|
return ctx.signal?.aborted === true && ctx.signal.reason === import_subagent_engine_sdk11.HOST_TIMEOUT_ABORT_REASON;
|
|
3048
2811
|
}
|
|
@@ -3095,13 +2858,14 @@ function createDefaultZcodeEngine() {
|
|
|
3095
2858
|
var import_subagent_engine_sdk13 = require("@zhushanwen/subagent-engine-sdk");
|
|
3096
2859
|
|
|
3097
2860
|
// src/server.ts
|
|
2861
|
+
var import_server = require("@zhushanwen/subagent-engine-sdk/server");
|
|
3098
2862
|
var logger5 = (0, import_subagent_engine_sdk14.getLogger)("subagents");
|
|
3099
|
-
var REVERSE_TIMEOUT_DEFAULT_MS = 6e4;
|
|
3100
2863
|
var EngineProtocolServer = class {
|
|
3101
2864
|
write;
|
|
3102
2865
|
engine;
|
|
3103
2866
|
reverseClock;
|
|
3104
2867
|
reverseTimeoutMs;
|
|
2868
|
+
frameLoop;
|
|
3105
2869
|
activeRuns = /* @__PURE__ */ new Map();
|
|
3106
2870
|
reversePending = /* @__PURE__ */ new Map();
|
|
3107
2871
|
revSeq = 0;
|
|
@@ -3110,46 +2874,22 @@ var EngineProtocolServer = class {
|
|
|
3110
2874
|
this.write = opts.write;
|
|
3111
2875
|
this.engine = opts.engine ?? createDefaultZcodeEngine();
|
|
3112
2876
|
this.reverseClock = opts.reverseClock;
|
|
3113
|
-
this.reverseTimeoutMs = opts.reverseTimeoutMs ?? REVERSE_TIMEOUT_DEFAULT_MS;
|
|
2877
|
+
this.reverseTimeoutMs = opts.reverseTimeoutMs ?? import_server.REVERSE_TIMEOUT_DEFAULT_MS;
|
|
2878
|
+
this.frameLoop = {
|
|
2879
|
+
write: this.write,
|
|
2880
|
+
settleReverse: (id, frame) => this.settleReverse(id, frame),
|
|
2881
|
+
dispatch: (id, method, params) => this.dispatch(id, method, params),
|
|
2882
|
+
toError: (err) => toProtocolError(err)
|
|
2883
|
+
};
|
|
3114
2884
|
}
|
|
3115
2885
|
/** 入站帧消费(请求帧 + 反向请求应答帧;main.ts 的行解析器拆行后喂入)。 */
|
|
3116
2886
|
handleFrame(frame) {
|
|
3117
|
-
|
|
3118
|
-
this.settleReverse(frame.id, frame);
|
|
3119
|
-
return;
|
|
3120
|
-
}
|
|
3121
|
-
if ((0, import_subagent_engine_sdk14.isReverseRequestFrame)(frame)) {
|
|
3122
|
-
this.write({
|
|
3123
|
-
id: 0,
|
|
3124
|
-
error: {
|
|
3125
|
-
code: "engine_protocol_bad_frame",
|
|
3126
|
-
message: `unexpected reverse request frame from host: ${String(frame.method)}`,
|
|
3127
|
-
recovery: "The engine protocol v1 only carries host/* requests engine\u2192host."
|
|
3128
|
-
}
|
|
3129
|
-
});
|
|
3130
|
-
return;
|
|
3131
|
-
}
|
|
3132
|
-
if (typeof frame === "object" && frame !== null && "id" in frame && "method" in frame && typeof frame.method === "string") {
|
|
3133
|
-
const { id, method, params } = frame;
|
|
3134
|
-
if (typeof id === "number") {
|
|
3135
|
-
void this.dispatch(id, method, params).then(
|
|
3136
|
-
(result) => this.write({ id, result }),
|
|
3137
|
-
(err) => this.write({ id, error: toProtocolError(err) })
|
|
3138
|
-
);
|
|
3139
|
-
return;
|
|
3140
|
-
}
|
|
3141
|
-
}
|
|
2887
|
+
(0, import_server.handleInboundFrame)(frame, this.frameLoop);
|
|
3142
2888
|
}
|
|
3143
2889
|
/** 9 正向方法分发(表驱动:method → 处理器;未知方法 → engine_protocol_unknown_method)。 */
|
|
3144
2890
|
async dispatch(id, method, params) {
|
|
3145
2891
|
const handler = this.methodHandlers[method];
|
|
3146
|
-
if (handler === void 0)
|
|
3147
|
-
throw new import_subagent_engine_sdk14.EngineSdkError(
|
|
3148
|
-
"engine_protocol_unknown_method",
|
|
3149
|
-
`unknown protocol method: ${method} (request id ${id})`,
|
|
3150
|
-
"The engine speaks protocol v1; check the installed engine package version vs the host."
|
|
3151
|
-
);
|
|
3152
|
-
}
|
|
2892
|
+
if (handler === void 0) throw (0, import_server.unknownMethodError)(id, method);
|
|
3153
2893
|
return handler(params);
|
|
3154
2894
|
}
|
|
3155
2895
|
/**
|
|
@@ -3172,42 +2912,23 @@ var EngineProtocolServer = class {
|
|
|
3172
2912
|
};
|
|
3173
2913
|
// ── initialize:版本协商(越界 → engine_protocol_mismatch)+ 能力应答 ──
|
|
3174
2914
|
initialize(params) {
|
|
3175
|
-
|
|
3176
|
-
throw new import_subagent_engine_sdk14.EngineSdkError(
|
|
3177
|
-
"engine_protocol_mismatch",
|
|
3178
|
-
`host protocol version ${String(params?.protocolVersion)} is not compatible with engine protocol v${import_subagent_engine_sdk14.ENGINE_PROTOCOL_VERSION}`,
|
|
3179
|
-
`Upgrade the engine package or the host so both speak protocol v${import_subagent_engine_sdk14.ENGINE_PROTOCOL_VERSION}.`
|
|
3180
|
-
);
|
|
3181
|
-
}
|
|
3182
|
-
this.initialized = true;
|
|
3183
|
-
const models = this.engine.listModels?.() ?? null;
|
|
3184
|
-
return {
|
|
3185
|
-
protocolVersion: import_subagent_engine_sdk14.ENGINE_PROTOCOL_VERSION,
|
|
2915
|
+
const result = (0, import_server.initializeEngine)(params, {
|
|
3186
2916
|
engineId: this.engine.id,
|
|
3187
|
-
engineVersion: ZCODE_ADAPTER_VERSION,
|
|
3188
2917
|
adapterVersion: ZCODE_ADAPTER_VERSION,
|
|
3189
2918
|
capabilities: this.engine.capabilities(),
|
|
3190
|
-
|
|
3191
|
-
};
|
|
2919
|
+
listModels: () => this.engine.listModels?.() ?? null
|
|
2920
|
+
});
|
|
2921
|
+
this.initialized = true;
|
|
2922
|
+
return result;
|
|
3192
2923
|
}
|
|
3193
2924
|
// ── run:协议载荷 → 本地 AgentCallOpts/RunContext;事件 → 通知/host 通道 ──
|
|
3194
2925
|
async run(params) {
|
|
3195
|
-
if (!this.initialized)
|
|
3196
|
-
throw new import_subagent_engine_sdk14.EngineSdkError(
|
|
3197
|
-
"engine_protocol_not_initialized",
|
|
3198
|
-
"run before initialize is a protocol violation",
|
|
3199
|
-
"The host must complete the initialize handshake before dispatching runs."
|
|
3200
|
-
);
|
|
3201
|
-
}
|
|
2926
|
+
if (!this.initialized) throw (0, import_server.notInitializedError)();
|
|
3202
2927
|
const { runId, task, ctx } = params;
|
|
3203
2928
|
const controller = new AbortController();
|
|
3204
2929
|
const active = { controller, seq: 0 };
|
|
3205
2930
|
this.activeRuns.set(runId, active);
|
|
3206
|
-
const fullTask =
|
|
3207
|
-
...task,
|
|
3208
|
-
...ctx.model !== void 0 ? { model: ctx.model } : {},
|
|
3209
|
-
...ctx.cwd !== void 0 ? { cwd: ctx.cwd } : {}
|
|
3210
|
-
};
|
|
2931
|
+
const fullTask = (0, import_server.assembleFullTask)(task, ctx);
|
|
3211
2932
|
const ctxModel = (0, import_subagent_engine_sdk13.parseCtxModel)(ctx.ctxModel);
|
|
3212
2933
|
const stream = ctx.streamMode === "stream" ? {
|
|
3213
2934
|
onDelta: (delta) => {
|
|
@@ -3220,7 +2941,6 @@ var EngineProtocolServer = class {
|
|
|
3220
2941
|
onEvent: (event) => this.emitEvent(runId, event),
|
|
3221
2942
|
...ctxModel !== void 0 ? { ctxModel } : {},
|
|
3222
2943
|
...stream !== void 0 ? { stream } : {},
|
|
3223
|
-
...ctx.engineFallback !== void 0 ? { engineFallback: ctx.engineFallback } : {},
|
|
3224
2944
|
// [U6 / §3.2.6 要点 3] resume 锚点透传(宿主 → 引擎的续聊通道:zcode 锚
|
|
3225
2945
|
// sessionRef {sessionId, dbPath},引擎侧 resume 读 + 新 session 注入消费)。
|
|
3226
2946
|
...params.resume !== void 0 ? { resume: params.resume } : {},
|
|
@@ -3255,9 +2975,7 @@ var EngineProtocolServer = class {
|
|
|
3255
2975
|
}
|
|
3256
2976
|
// ── 出站:事件通知 + 反向请求客户端 ──
|
|
3257
2977
|
emitEvent(runId, event) {
|
|
3258
|
-
|
|
3259
|
-
const seq = active !== void 0 ? ++active.seq : 0;
|
|
3260
|
-
this.write({ method: "event", params: { runId, seq, event } });
|
|
2978
|
+
(0, import_server.writeRunEvent)(this.write, this.activeRuns, runId, event);
|
|
3261
2979
|
}
|
|
3262
2980
|
/**
|
|
3263
2981
|
* 发反向请求并等应答(帧④必须应答)。计时面登记:发出 → clock.started;收到
|
|
@@ -3283,25 +3001,17 @@ var EngineProtocolServer = class {
|
|
|
3283
3001
|
return this.reverseRequestInternal(method, params);
|
|
3284
3002
|
}
|
|
3285
3003
|
reverseRequestInternal(method, params) {
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
this.reversePending
|
|
3290
|
-
this.
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
this.write({ id, method, params });
|
|
3298
|
-
} catch (err) {
|
|
3299
|
-
this.reversePending.delete(id);
|
|
3300
|
-
clearTimeout(timer);
|
|
3301
|
-
this.reverseClock?.settled(id);
|
|
3302
|
-
reject(new Error(`reverse request ${method} (${id}) could not be written: ${(0, import_subagent_engine_sdk4.toErrorMessage)(err)}`));
|
|
3303
|
-
}
|
|
3304
|
-
});
|
|
3004
|
+
return (0, import_server.sendReverseRequest)(
|
|
3005
|
+
{
|
|
3006
|
+
write: this.write,
|
|
3007
|
+
pending: this.reversePending,
|
|
3008
|
+
timeoutMs: this.reverseTimeoutMs,
|
|
3009
|
+
...this.reverseClock !== void 0 ? { clock: this.reverseClock } : {},
|
|
3010
|
+
nextId: () => `rev-${++this.revSeq}`
|
|
3011
|
+
},
|
|
3012
|
+
method,
|
|
3013
|
+
params
|
|
3014
|
+
);
|
|
3305
3015
|
}
|
|
3306
3016
|
/** 反向请求应答落位(ack 两阶段:{ack:true}/{unsupported:true}/{ok:true} 均先 ack 计时面)。 */
|
|
3307
3017
|
settleReverse(id, frame) {
|
|
@@ -3318,13 +3028,9 @@ var EngineProtocolServer = class {
|
|
|
3318
3028
|
function probeParamsOf(params) {
|
|
3319
3029
|
return typeof params === "object" && params !== null ? params : void 0;
|
|
3320
3030
|
}
|
|
3031
|
+
var RUN_FAILURE_RECOVERY = "Check the engine process logs (engineDataDir/logs/) and rerun; if persistent, reinstall or upgrade the engine package.";
|
|
3321
3032
|
function toProtocolError(err) {
|
|
3322
|
-
|
|
3323
|
-
return {
|
|
3324
|
-
code: "engine_run_failed",
|
|
3325
|
-
message: (0, import_subagent_engine_sdk4.toErrorMessage)(err),
|
|
3326
|
-
recovery: "Check the engine process logs (engineDataDir/logs/) and rerun; if persistent, reinstall or upgrade the engine package."
|
|
3327
|
-
};
|
|
3033
|
+
return (0, import_server.toProtocolError)(err, RUN_FAILURE_RECOVERY);
|
|
3328
3034
|
}
|
|
3329
3035
|
|
|
3330
3036
|
// src/golden-sample.ts
|