@zhushanwen/zcode-subagent-cli 0.1.2 → 0.2.1
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-IIAABOER.js → chunk-WQ7NVGKB.js} +72 -29
- package/dist/index.cjs +72 -29
- package/dist/index.d.cts +14 -9
- package/dist/index.d.ts +14 -9
- package/dist/index.js +1 -1
- package/dist/main.cjs +72 -29
- package/dist/main.js +1 -1
- package/package.json +2 -2
|
@@ -28,6 +28,9 @@ var ZCODE_APPSERVER_ABORT_GRACE_MS = 3e3;
|
|
|
28
28
|
var ZCODE_APPSERVER_ERR_MODEL_CONFIG_MISSING = -32603;
|
|
29
29
|
var ZCODE_APPSERVER_ERR_BUSY_SESSION = -32010;
|
|
30
30
|
var ZCODE_APPSERVER_HARVEST_GRACE_MS = 1e3;
|
|
31
|
+
function isFailedTerminalStatus(status) {
|
|
32
|
+
return status === "failed" || status === "error";
|
|
33
|
+
}
|
|
31
34
|
|
|
32
35
|
// src/db-path.ts
|
|
33
36
|
import * as os from "os";
|
|
@@ -680,6 +683,11 @@ var AppServerConnection = class {
|
|
|
680
683
|
reqSeq = 0;
|
|
681
684
|
/** stderr 滚动缓冲(代级:崩溃诊断用)。 */
|
|
682
685
|
stderrTail = "";
|
|
686
|
+
/**
|
|
687
|
+
* stderr tee 落盘流(D6-⑦;merge 裁决:旋转走 logs/stderr-rotation 的路径式
|
|
688
|
+
* rotateStderrLogIfNeeded——W5 边界禁 import subagent-core 的 SizeRotatedAppendStream,
|
|
689
|
+
* 常驻流改裸 WriteStream + 按次轮转检查,帽语义等价)。
|
|
690
|
+
*/
|
|
683
691
|
stderrStream = null;
|
|
684
692
|
stderrStreamFailed = false;
|
|
685
693
|
/**
|
|
@@ -1366,7 +1374,13 @@ var SessionChannel = class {
|
|
|
1366
1374
|
});
|
|
1367
1375
|
const turn = {
|
|
1368
1376
|
sessionId,
|
|
1369
|
-
callbacks: {
|
|
1377
|
+
callbacks: {
|
|
1378
|
+
onTextDelta: opts.onTextDelta,
|
|
1379
|
+
onThinkingDelta: opts.onThinkingDelta,
|
|
1380
|
+
// [PR3] tool 执行期活性回调(SessionTurnCallbacks.onActivity 注释——宿主侧
|
|
1381
|
+
// 无进展守护的工具执行期刷新面)
|
|
1382
|
+
onActivity: opts.onActivity
|
|
1383
|
+
},
|
|
1370
1384
|
settled: false,
|
|
1371
1385
|
deltas: [],
|
|
1372
1386
|
finalText: void 0,
|
|
@@ -1482,7 +1496,9 @@ var SessionChannel = class {
|
|
|
1482
1496
|
if (payload === void 0) return;
|
|
1483
1497
|
this.refreshIdle(turn);
|
|
1484
1498
|
if (this.applyFinalFrame(turn, payload)) return;
|
|
1485
|
-
this.applyStreamDelta(turn, payload)
|
|
1499
|
+
if (!this.applyStreamDelta(turn, payload) && !turn.settled) {
|
|
1500
|
+
turn.callbacks.onActivity?.();
|
|
1501
|
+
}
|
|
1486
1502
|
}
|
|
1487
1503
|
/**
|
|
1488
1504
|
* 收尾帧判定与吸收(A.2 ⑤ 两种形态:payload.response / stopReason+content 变体)。
|
|
@@ -1506,9 +1522,12 @@ var SessionChannel = class {
|
|
|
1506
1522
|
/** 增量 delta 分发:非空 delta 入账 + 回调;终态后迟到丢弃(不变量 2)。
|
|
1507
1523
|
* kind 区分两通道(F2):reasoning_delta 只走 thinking 回调(不入 deltas 账本
|
|
1508
1524
|
* ——deltas 是 response 兜底聚合,推理文本不是答案正文);text_delta / kind
|
|
1509
|
-
* 缺席走 text 路径。
|
|
1525
|
+
* 缺席走 text 路径。
|
|
1526
|
+
* 返回值([PR3]):帧被 delta 路径消费(thinking 或 text,回调若注册则已触发)
|
|
1527
|
+
* → true;无 delta / 空 delta / 终态后迟到丢弃 → false(handleSessionEvent 据
|
|
1528
|
+
* 此分流 onActivity——delta 帧已是宿主可见进展,不双发活性信号)。 */
|
|
1510
1529
|
applyStreamDelta(turn, payload) {
|
|
1511
|
-
if (typeof payload.delta !== "string" || payload.delta === "") return;
|
|
1530
|
+
if (typeof payload.delta !== "string" || payload.delta === "") return false;
|
|
1512
1531
|
if (turn.settled) {
|
|
1513
1532
|
logger2.warn(
|
|
1514
1533
|
`\u7EC8\u6001\u540E\u8FDF\u5230\u7684 delta \u4E22\u5F03\uFF08\u4F1A\u8BDD ${turn.sessionId}\uFF0C\u4E0D\u53D8\u91CF 2\uFF1Aresolve \u540E\u4E0D\u518D\u53D1\u4E8B\u4EF6\uFF09: ${payload.delta.slice(
|
|
@@ -1516,14 +1535,15 @@ var SessionChannel = class {
|
|
|
1516
1535
|
DELTA_LOG_CHARS
|
|
1517
1536
|
)}`
|
|
1518
1537
|
);
|
|
1519
|
-
return;
|
|
1538
|
+
return false;
|
|
1520
1539
|
}
|
|
1521
1540
|
if (payload.kind === "reasoning_delta") {
|
|
1522
1541
|
turn.callbacks.onThinkingDelta?.(payload.delta);
|
|
1523
|
-
return;
|
|
1542
|
+
return true;
|
|
1524
1543
|
}
|
|
1525
1544
|
turn.deltas.push(payload.delta);
|
|
1526
1545
|
turn.callbacks.onTextDelta?.(payload.delta);
|
|
1546
|
+
return true;
|
|
1527
1547
|
}
|
|
1528
1548
|
handleTelemetry(params) {
|
|
1529
1549
|
if (!isRecord3(params)) return;
|
|
@@ -1543,13 +1563,38 @@ var SessionChannel = class {
|
|
|
1543
1563
|
turn.lastTerminalStatus = status;
|
|
1544
1564
|
this.recordTerminalError(turn, params);
|
|
1545
1565
|
if (turn.settled) {
|
|
1546
|
-
|
|
1547
|
-
`\u6743\u5A01\u7EC8\u6001\u665A\u4E8E\u843D\u5B9A\u7ED3\u679C\u5230\u8FBE\uFF08\u4F1A\u8BDD ${turn.sessionId}\uFF0C\u5DF2\u843D\u5B9A source=${turn.terminal?.source}\uFF09\uFF1Aturn.terminal status="${status}" \u4EC5\u8BB0\u5F55\u4E0D\u6539\u5199\uFF08P0-1 D5\u2460\uFF09`
|
|
1548
|
-
);
|
|
1566
|
+
this.logLateTerminal(turn, status);
|
|
1549
1567
|
return;
|
|
1550
1568
|
}
|
|
1551
1569
|
turn.settle({ status, source: "turn.terminal" });
|
|
1552
1570
|
}
|
|
1571
|
+
/**
|
|
1572
|
+
* 已落定 turn 的迟到权威终态分级日志(P-Z2 后续:常态迟到降噪)。真机实证该
|
|
1573
|
+
* 形态的唯一可达路径是 success 终态常态迟到(final-frame 先落定 + 权威
|
|
1574
|
+
* turn.terminal 迟到)——即每个成功任务必经;原无条件 warn 经 SDK cli-entry
|
|
1575
|
+
* 的 stderr 兜底 → runtime [rpc:stderr] 全量 console.error 链路,每个成功任务
|
|
1576
|
+
* 产一条零异常区分度的 ERROR 级日志。按权威 status 分级(落定语义不动——
|
|
1577
|
+
* lastTerminalStatus/lastTerminalError 的入账在上游无条件路径完成):
|
|
1578
|
+
* - "success":常态迟到,零日志;
|
|
1579
|
+
* - "interrupted":用户中断形态,debug(stderr 兜底对 debug no-op——对齐
|
|
1580
|
+
* SDK logger CONSOLE_SINK 语义,host/log 反向请求侧仍可观测);
|
|
1581
|
+
* - 失败类(isFailedTerminalStatus,与引擎失败分流同口径)与 unknown/未识别
|
|
1582
|
+
* status:保守 warn(原样 status 已写入文案)——假成功识破的防御面,理论
|
|
1583
|
+
* 不可达但保留,宁可误报不静默。
|
|
1584
|
+
*/
|
|
1585
|
+
logLateTerminal(turn, status) {
|
|
1586
|
+
if (status === "success") return;
|
|
1587
|
+
const message = `\u6743\u5A01\u7EC8\u6001\u665A\u4E8E\u843D\u5B9A\u7ED3\u679C\u5230\u8FBE\uFF08\u4F1A\u8BDD ${turn.sessionId}\uFF0C\u5DF2\u843D\u5B9A source=${turn.terminal?.source}\uFF09\uFF1Aturn.terminal status="${status}" \u4EC5\u8BB0\u5F55\u4E0D\u6539\u5199\uFF08P0-1 D5\u2460\uFF09`;
|
|
1588
|
+
if (isFailedTerminalStatus(status)) {
|
|
1589
|
+
logger2.warn(message);
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
if (status === "interrupted") {
|
|
1593
|
+
logger2.debug(message);
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
logger2.warn(message);
|
|
1597
|
+
}
|
|
1553
1598
|
/** terminal 帧专属错误信息入账(⛔P-Z2 实证:真实 failed 终态的 errorCode/errorMessage
|
|
1554
1599
|
* 只在 terminal 帧携带,read/delta 拿不到——先到/迟到都记录,消费层合成失败
|
|
1555
1600
|
* 文案时优先采信)。二者均缺失时不挂 lastTerminalError 字段。 */
|
|
@@ -1835,6 +1880,11 @@ var ZcodeEngine = class {
|
|
|
1835
1880
|
// 不变量 3a 的拼接比对不含 reasoning)
|
|
1836
1881
|
onTextDelta: (delta) => ctx.onEvent?.({ type: "text_delta", delta }),
|
|
1837
1882
|
onThinkingDelta: (delta) => ctx.onEvent?.({ type: "thinking_delta", delta }),
|
|
1883
|
+
// [PR3] 工具执行期活性:非终态非增量的 session/event 帧(tool.updated progress
|
|
1884
|
+
// 等,真机探针实证每 ~1s 一帧)→ activity 事件(零载荷纯活性信号——宿主无进展
|
|
1885
|
+
// 守护对任何事件类型刷新;reducer no-op、不落 journal)。zcode 引擎
|
|
1886
|
+
// conversation:"unsupported",run 域是唯一发射面(无 chat 域接线)。
|
|
1887
|
+
onActivity: () => ctx.onEvent?.({ type: "activity" }),
|
|
1838
1888
|
onSessionCreated: (sessionId) => {
|
|
1839
1889
|
currentSessionId = sessionId;
|
|
1840
1890
|
rt.activeSessions.add(sessionId);
|
|
@@ -2061,6 +2111,17 @@ var ZcodeEngine = class {
|
|
|
2061
2111
|
}
|
|
2062
2112
|
await this.shutdownRuntimeAndDisposeChannel(rt);
|
|
2063
2113
|
}
|
|
2114
|
+
/**
|
|
2115
|
+
* [u7a D5] 引擎在途只读快照:activeSessions 非空才算在途——poolKey 'shared' 的
|
|
2116
|
+
* app-server **空闲常驻进程恒活,禁止按进程存在判定**(进程在 ≠ 在途,否则推迟
|
|
2117
|
+
* 判定恒真、30min 上限从兜底变常态路径,设计 §3.3 D5 显式排除)。计数权威 =
|
|
2118
|
+
* activeSessions(attempt 入 create 应答后 add / finally settle 后 delete,与
|
|
2119
|
+
* dispose 的 close 帧目标集同一状态源,无双记账)。运行时未初始化(从未 run /
|
|
2120
|
+
* 已 dispose)→ 恒 0。
|
|
2121
|
+
*/
|
|
2122
|
+
inFlightSnapshot() {
|
|
2123
|
+
return { inFlight: this.appserverRuntime?.activeSessions.size ?? 0 };
|
|
2124
|
+
}
|
|
2064
2125
|
/** 终态合成(extension-conventions 函数 80 行上限,从 run 提取):aborted / run-failed / parsed 三分支。 */
|
|
2065
2126
|
finalizeOutcome(task, ctx, final, usageAcc, startedAt) {
|
|
2066
2127
|
const outcome = {
|
|
@@ -2129,17 +2190,6 @@ var ZcodeEngine = class {
|
|
|
2129
2190
|
}
|
|
2130
2191
|
for (const ev of synthesizeCoarseEvents(payload.response, payload.usage)) emit(ev);
|
|
2131
2192
|
}
|
|
2132
|
-
/**
|
|
2133
|
-
* D1 可选面:zcode 首期不支持 conversation(capabilities 声明)——同步拒绝、
|
|
2134
|
-
* 不创建进程,文案给可操作建议(A11)。
|
|
2135
|
-
*/
|
|
2136
|
-
async interact(_handle, _action) {
|
|
2137
|
-
return {
|
|
2138
|
-
ok: false,
|
|
2139
|
-
code: "engine_capability_unsupported",
|
|
2140
|
-
message: "zcode \u5F15\u64CE\u4E0D\u652F\u6301 conversation \u4EA4\u4E92\u63A7\u5236\u9762\uFF08capabilities.conversation = 'unsupported'\uFF0C\u6BCF\u4EFB\u52A1\u81EA\u5305\u542B\u4F1A\u8BDD\uFF0C\u65E0\u540C\u8FDB\u7A0B idle \u590D\u7528\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u6539\u7528\u5355\u6B21 subagent \u8C03\u7528\u91CD\u65B0\u6D3E\u53D1\u4EFB\u52A1\uFF0C\u6216\u4F7F\u7528 engine: 'pi'\uFF08chatMode idle \u590D\u7528\uFF0C\u652F\u6301 message/close/cancel\uFF09\u3002"
|
|
2141
|
-
};
|
|
2142
|
-
}
|
|
2143
2193
|
/** [U7] 模型可发现性:v2 桌面登录态聚合(带凭据 provider × models),失败安全返回清单本身可能为空。 */
|
|
2144
2194
|
listModels() {
|
|
2145
2195
|
return listZcodeModels(this.deps.sources);
|
|
@@ -2339,9 +2389,6 @@ function authoritativeTerminalStatus(r) {
|
|
|
2339
2389
|
if (r.lastTerminalStatus !== void 0) return r.lastTerminalStatus;
|
|
2340
2390
|
return r.terminal.source === "turn.terminal" ? r.terminal.status : void 0;
|
|
2341
2391
|
}
|
|
2342
|
-
function isFailedTerminalStatus(status) {
|
|
2343
|
-
return status === "failed" || status === "error";
|
|
2344
|
-
}
|
|
2345
2392
|
function parsedAppServerAttempt(task, r) {
|
|
2346
2393
|
if (isFailedTerminalStatus(authoritativeTerminalStatus(r))) {
|
|
2347
2394
|
return failedTerminalAppServerAttempt(r);
|
|
@@ -2526,7 +2573,7 @@ var EngineProtocolServer = class {
|
|
|
2526
2573
|
}
|
|
2527
2574
|
}
|
|
2528
2575
|
}
|
|
2529
|
-
/**
|
|
2576
|
+
/** 9 正向方法分发(表驱动:method → 处理器;未知方法 → engine_protocol_unknown_method)。 */
|
|
2530
2577
|
async dispatch(id, method, params) {
|
|
2531
2578
|
const handler = this.methodHandlers[method];
|
|
2532
2579
|
if (handler === void 0) {
|
|
@@ -2539,7 +2586,7 @@ var EngineProtocolServer = class {
|
|
|
2539
2586
|
return handler(params);
|
|
2540
2587
|
}
|
|
2541
2588
|
/**
|
|
2542
|
-
*
|
|
2589
|
+
* 9 正向方法 → 处理器映射(每个处理器消费原始 params 并自行收敛类型——
|
|
2543
2590
|
* 与原 switch case 表达式一一对应)。
|
|
2544
2591
|
*/
|
|
2545
2592
|
methodHandlers = {
|
|
@@ -2547,7 +2594,6 @@ var EngineProtocolServer = class {
|
|
|
2547
2594
|
probe: (p) => this.engine.probe(probeParamsOf(p)),
|
|
2548
2595
|
run: (p) => this.run(p),
|
|
2549
2596
|
cancel: (p) => this.cancel(p),
|
|
2550
|
-
interact: (p) => this.interact(p),
|
|
2551
2597
|
read: (p) => this.read(p),
|
|
2552
2598
|
listModels: () => ({ models: this.engine.listModels?.() ?? null }),
|
|
2553
2599
|
validateModel: (p) => this.validateModel(p),
|
|
@@ -2623,9 +2669,6 @@ var EngineProtocolServer = class {
|
|
|
2623
2669
|
if (active !== void 0) active.controller.abort(new Error(`cancelled by host: ${params.reason}`));
|
|
2624
2670
|
return { ok: true };
|
|
2625
2671
|
}
|
|
2626
|
-
async interact(params) {
|
|
2627
|
-
return this.engine.interact({ data: params.handle }, params.action);
|
|
2628
|
-
}
|
|
2629
2672
|
read(params) {
|
|
2630
2673
|
return this.engine.read({ data: params.handle });
|
|
2631
2674
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -78,6 +78,9 @@ var ZCODE_APPSERVER_ABORT_GRACE_MS = 3e3;
|
|
|
78
78
|
var ZCODE_APPSERVER_ERR_MODEL_CONFIG_MISSING = -32603;
|
|
79
79
|
var ZCODE_APPSERVER_ERR_BUSY_SESSION = -32010;
|
|
80
80
|
var ZCODE_APPSERVER_HARVEST_GRACE_MS = 1e3;
|
|
81
|
+
function isFailedTerminalStatus(status) {
|
|
82
|
+
return status === "failed" || status === "error";
|
|
83
|
+
}
|
|
81
84
|
|
|
82
85
|
// src/registration.ts
|
|
83
86
|
var import_subagent_engine_sdk10 = require("@zhushanwen/subagent-engine-sdk");
|
|
@@ -702,6 +705,11 @@ var AppServerConnection = class {
|
|
|
702
705
|
reqSeq = 0;
|
|
703
706
|
/** stderr 滚动缓冲(代级:崩溃诊断用)。 */
|
|
704
707
|
stderrTail = "";
|
|
708
|
+
/**
|
|
709
|
+
* stderr tee 落盘流(D6-⑦;merge 裁决:旋转走 logs/stderr-rotation 的路径式
|
|
710
|
+
* rotateStderrLogIfNeeded——W5 边界禁 import subagent-core 的 SizeRotatedAppendStream,
|
|
711
|
+
* 常驻流改裸 WriteStream + 按次轮转检查,帽语义等价)。
|
|
712
|
+
*/
|
|
705
713
|
stderrStream = null;
|
|
706
714
|
stderrStreamFailed = false;
|
|
707
715
|
/**
|
|
@@ -1388,7 +1396,13 @@ var SessionChannel = class {
|
|
|
1388
1396
|
});
|
|
1389
1397
|
const turn = {
|
|
1390
1398
|
sessionId,
|
|
1391
|
-
callbacks: {
|
|
1399
|
+
callbacks: {
|
|
1400
|
+
onTextDelta: opts.onTextDelta,
|
|
1401
|
+
onThinkingDelta: opts.onThinkingDelta,
|
|
1402
|
+
// [PR3] tool 执行期活性回调(SessionTurnCallbacks.onActivity 注释——宿主侧
|
|
1403
|
+
// 无进展守护的工具执行期刷新面)
|
|
1404
|
+
onActivity: opts.onActivity
|
|
1405
|
+
},
|
|
1392
1406
|
settled: false,
|
|
1393
1407
|
deltas: [],
|
|
1394
1408
|
finalText: void 0,
|
|
@@ -1504,7 +1518,9 @@ var SessionChannel = class {
|
|
|
1504
1518
|
if (payload === void 0) return;
|
|
1505
1519
|
this.refreshIdle(turn);
|
|
1506
1520
|
if (this.applyFinalFrame(turn, payload)) return;
|
|
1507
|
-
this.applyStreamDelta(turn, payload)
|
|
1521
|
+
if (!this.applyStreamDelta(turn, payload) && !turn.settled) {
|
|
1522
|
+
turn.callbacks.onActivity?.();
|
|
1523
|
+
}
|
|
1508
1524
|
}
|
|
1509
1525
|
/**
|
|
1510
1526
|
* 收尾帧判定与吸收(A.2 ⑤ 两种形态:payload.response / stopReason+content 变体)。
|
|
@@ -1528,9 +1544,12 @@ var SessionChannel = class {
|
|
|
1528
1544
|
/** 增量 delta 分发:非空 delta 入账 + 回调;终态后迟到丢弃(不变量 2)。
|
|
1529
1545
|
* kind 区分两通道(F2):reasoning_delta 只走 thinking 回调(不入 deltas 账本
|
|
1530
1546
|
* ——deltas 是 response 兜底聚合,推理文本不是答案正文);text_delta / kind
|
|
1531
|
-
* 缺席走 text 路径。
|
|
1547
|
+
* 缺席走 text 路径。
|
|
1548
|
+
* 返回值([PR3]):帧被 delta 路径消费(thinking 或 text,回调若注册则已触发)
|
|
1549
|
+
* → true;无 delta / 空 delta / 终态后迟到丢弃 → false(handleSessionEvent 据
|
|
1550
|
+
* 此分流 onActivity——delta 帧已是宿主可见进展,不双发活性信号)。 */
|
|
1532
1551
|
applyStreamDelta(turn, payload) {
|
|
1533
|
-
if (typeof payload.delta !== "string" || payload.delta === "") return;
|
|
1552
|
+
if (typeof payload.delta !== "string" || payload.delta === "") return false;
|
|
1534
1553
|
if (turn.settled) {
|
|
1535
1554
|
logger2.warn(
|
|
1536
1555
|
`\u7EC8\u6001\u540E\u8FDF\u5230\u7684 delta \u4E22\u5F03\uFF08\u4F1A\u8BDD ${turn.sessionId}\uFF0C\u4E0D\u53D8\u91CF 2\uFF1Aresolve \u540E\u4E0D\u518D\u53D1\u4E8B\u4EF6\uFF09: ${payload.delta.slice(
|
|
@@ -1538,14 +1557,15 @@ var SessionChannel = class {
|
|
|
1538
1557
|
DELTA_LOG_CHARS
|
|
1539
1558
|
)}`
|
|
1540
1559
|
);
|
|
1541
|
-
return;
|
|
1560
|
+
return false;
|
|
1542
1561
|
}
|
|
1543
1562
|
if (payload.kind === "reasoning_delta") {
|
|
1544
1563
|
turn.callbacks.onThinkingDelta?.(payload.delta);
|
|
1545
|
-
return;
|
|
1564
|
+
return true;
|
|
1546
1565
|
}
|
|
1547
1566
|
turn.deltas.push(payload.delta);
|
|
1548
1567
|
turn.callbacks.onTextDelta?.(payload.delta);
|
|
1568
|
+
return true;
|
|
1549
1569
|
}
|
|
1550
1570
|
handleTelemetry(params) {
|
|
1551
1571
|
if (!isRecord3(params)) return;
|
|
@@ -1565,13 +1585,38 @@ var SessionChannel = class {
|
|
|
1565
1585
|
turn.lastTerminalStatus = status;
|
|
1566
1586
|
this.recordTerminalError(turn, params);
|
|
1567
1587
|
if (turn.settled) {
|
|
1568
|
-
|
|
1569
|
-
`\u6743\u5A01\u7EC8\u6001\u665A\u4E8E\u843D\u5B9A\u7ED3\u679C\u5230\u8FBE\uFF08\u4F1A\u8BDD ${turn.sessionId}\uFF0C\u5DF2\u843D\u5B9A source=${turn.terminal?.source}\uFF09\uFF1Aturn.terminal status="${status}" \u4EC5\u8BB0\u5F55\u4E0D\u6539\u5199\uFF08P0-1 D5\u2460\uFF09`
|
|
1570
|
-
);
|
|
1588
|
+
this.logLateTerminal(turn, status);
|
|
1571
1589
|
return;
|
|
1572
1590
|
}
|
|
1573
1591
|
turn.settle({ status, source: "turn.terminal" });
|
|
1574
1592
|
}
|
|
1593
|
+
/**
|
|
1594
|
+
* 已落定 turn 的迟到权威终态分级日志(P-Z2 后续:常态迟到降噪)。真机实证该
|
|
1595
|
+
* 形态的唯一可达路径是 success 终态常态迟到(final-frame 先落定 + 权威
|
|
1596
|
+
* turn.terminal 迟到)——即每个成功任务必经;原无条件 warn 经 SDK cli-entry
|
|
1597
|
+
* 的 stderr 兜底 → runtime [rpc:stderr] 全量 console.error 链路,每个成功任务
|
|
1598
|
+
* 产一条零异常区分度的 ERROR 级日志。按权威 status 分级(落定语义不动——
|
|
1599
|
+
* lastTerminalStatus/lastTerminalError 的入账在上游无条件路径完成):
|
|
1600
|
+
* - "success":常态迟到,零日志;
|
|
1601
|
+
* - "interrupted":用户中断形态,debug(stderr 兜底对 debug no-op——对齐
|
|
1602
|
+
* SDK logger CONSOLE_SINK 语义,host/log 反向请求侧仍可观测);
|
|
1603
|
+
* - 失败类(isFailedTerminalStatus,与引擎失败分流同口径)与 unknown/未识别
|
|
1604
|
+
* status:保守 warn(原样 status 已写入文案)——假成功识破的防御面,理论
|
|
1605
|
+
* 不可达但保留,宁可误报不静默。
|
|
1606
|
+
*/
|
|
1607
|
+
logLateTerminal(turn, status) {
|
|
1608
|
+
if (status === "success") return;
|
|
1609
|
+
const message = `\u6743\u5A01\u7EC8\u6001\u665A\u4E8E\u843D\u5B9A\u7ED3\u679C\u5230\u8FBE\uFF08\u4F1A\u8BDD ${turn.sessionId}\uFF0C\u5DF2\u843D\u5B9A source=${turn.terminal?.source}\uFF09\uFF1Aturn.terminal status="${status}" \u4EC5\u8BB0\u5F55\u4E0D\u6539\u5199\uFF08P0-1 D5\u2460\uFF09`;
|
|
1610
|
+
if (isFailedTerminalStatus(status)) {
|
|
1611
|
+
logger2.warn(message);
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
if (status === "interrupted") {
|
|
1615
|
+
logger2.debug(message);
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
logger2.warn(message);
|
|
1619
|
+
}
|
|
1575
1620
|
/** terminal 帧专属错误信息入账(⛔P-Z2 实证:真实 failed 终态的 errorCode/errorMessage
|
|
1576
1621
|
* 只在 terminal 帧携带,read/delta 拿不到——先到/迟到都记录,消费层合成失败
|
|
1577
1622
|
* 文案时优先采信)。二者均缺失时不挂 lastTerminalError 字段。 */
|
|
@@ -1857,6 +1902,11 @@ var ZcodeEngine = class {
|
|
|
1857
1902
|
// 不变量 3a 的拼接比对不含 reasoning)
|
|
1858
1903
|
onTextDelta: (delta) => ctx.onEvent?.({ type: "text_delta", delta }),
|
|
1859
1904
|
onThinkingDelta: (delta) => ctx.onEvent?.({ type: "thinking_delta", delta }),
|
|
1905
|
+
// [PR3] 工具执行期活性:非终态非增量的 session/event 帧(tool.updated progress
|
|
1906
|
+
// 等,真机探针实证每 ~1s 一帧)→ activity 事件(零载荷纯活性信号——宿主无进展
|
|
1907
|
+
// 守护对任何事件类型刷新;reducer no-op、不落 journal)。zcode 引擎
|
|
1908
|
+
// conversation:"unsupported",run 域是唯一发射面(无 chat 域接线)。
|
|
1909
|
+
onActivity: () => ctx.onEvent?.({ type: "activity" }),
|
|
1860
1910
|
onSessionCreated: (sessionId) => {
|
|
1861
1911
|
currentSessionId = sessionId;
|
|
1862
1912
|
rt.activeSessions.add(sessionId);
|
|
@@ -2083,6 +2133,17 @@ var ZcodeEngine = class {
|
|
|
2083
2133
|
}
|
|
2084
2134
|
await this.shutdownRuntimeAndDisposeChannel(rt);
|
|
2085
2135
|
}
|
|
2136
|
+
/**
|
|
2137
|
+
* [u7a D5] 引擎在途只读快照:activeSessions 非空才算在途——poolKey 'shared' 的
|
|
2138
|
+
* app-server **空闲常驻进程恒活,禁止按进程存在判定**(进程在 ≠ 在途,否则推迟
|
|
2139
|
+
* 判定恒真、30min 上限从兜底变常态路径,设计 §3.3 D5 显式排除)。计数权威 =
|
|
2140
|
+
* activeSessions(attempt 入 create 应答后 add / finally settle 后 delete,与
|
|
2141
|
+
* dispose 的 close 帧目标集同一状态源,无双记账)。运行时未初始化(从未 run /
|
|
2142
|
+
* 已 dispose)→ 恒 0。
|
|
2143
|
+
*/
|
|
2144
|
+
inFlightSnapshot() {
|
|
2145
|
+
return { inFlight: this.appserverRuntime?.activeSessions.size ?? 0 };
|
|
2146
|
+
}
|
|
2086
2147
|
/** 终态合成(extension-conventions 函数 80 行上限,从 run 提取):aborted / run-failed / parsed 三分支。 */
|
|
2087
2148
|
finalizeOutcome(task, ctx, final, usageAcc, startedAt) {
|
|
2088
2149
|
const outcome = {
|
|
@@ -2151,17 +2212,6 @@ var ZcodeEngine = class {
|
|
|
2151
2212
|
}
|
|
2152
2213
|
for (const ev of synthesizeCoarseEvents(payload.response, payload.usage)) emit(ev);
|
|
2153
2214
|
}
|
|
2154
|
-
/**
|
|
2155
|
-
* D1 可选面:zcode 首期不支持 conversation(capabilities 声明)——同步拒绝、
|
|
2156
|
-
* 不创建进程,文案给可操作建议(A11)。
|
|
2157
|
-
*/
|
|
2158
|
-
async interact(_handle, _action) {
|
|
2159
|
-
return {
|
|
2160
|
-
ok: false,
|
|
2161
|
-
code: "engine_capability_unsupported",
|
|
2162
|
-
message: "zcode \u5F15\u64CE\u4E0D\u652F\u6301 conversation \u4EA4\u4E92\u63A7\u5236\u9762\uFF08capabilities.conversation = 'unsupported'\uFF0C\u6BCF\u4EFB\u52A1\u81EA\u5305\u542B\u4F1A\u8BDD\uFF0C\u65E0\u540C\u8FDB\u7A0B idle \u590D\u7528\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u6539\u7528\u5355\u6B21 subagent \u8C03\u7528\u91CD\u65B0\u6D3E\u53D1\u4EFB\u52A1\uFF0C\u6216\u4F7F\u7528 engine: 'pi'\uFF08chatMode idle \u590D\u7528\uFF0C\u652F\u6301 message/close/cancel\uFF09\u3002"
|
|
2163
|
-
};
|
|
2164
|
-
}
|
|
2165
2215
|
/** [U7] 模型可发现性:v2 桌面登录态聚合(带凭据 provider × models),失败安全返回清单本身可能为空。 */
|
|
2166
2216
|
listModels() {
|
|
2167
2217
|
return listZcodeModels(this.deps.sources);
|
|
@@ -2361,9 +2411,6 @@ function authoritativeTerminalStatus(r) {
|
|
|
2361
2411
|
if (r.lastTerminalStatus !== void 0) return r.lastTerminalStatus;
|
|
2362
2412
|
return r.terminal.source === "turn.terminal" ? r.terminal.status : void 0;
|
|
2363
2413
|
}
|
|
2364
|
-
function isFailedTerminalStatus(status) {
|
|
2365
|
-
return status === "failed" || status === "error";
|
|
2366
|
-
}
|
|
2367
2414
|
function parsedAppServerAttempt(task, r) {
|
|
2368
2415
|
if (isFailedTerminalStatus(authoritativeTerminalStatus(r))) {
|
|
2369
2416
|
return failedTerminalAppServerAttempt(r);
|
|
@@ -2539,7 +2586,7 @@ var EngineProtocolServer = class {
|
|
|
2539
2586
|
}
|
|
2540
2587
|
}
|
|
2541
2588
|
}
|
|
2542
|
-
/**
|
|
2589
|
+
/** 9 正向方法分发(表驱动:method → 处理器;未知方法 → engine_protocol_unknown_method)。 */
|
|
2543
2590
|
async dispatch(id, method, params) {
|
|
2544
2591
|
const handler = this.methodHandlers[method];
|
|
2545
2592
|
if (handler === void 0) {
|
|
@@ -2552,7 +2599,7 @@ var EngineProtocolServer = class {
|
|
|
2552
2599
|
return handler(params);
|
|
2553
2600
|
}
|
|
2554
2601
|
/**
|
|
2555
|
-
*
|
|
2602
|
+
* 9 正向方法 → 处理器映射(每个处理器消费原始 params 并自行收敛类型——
|
|
2556
2603
|
* 与原 switch case 表达式一一对应)。
|
|
2557
2604
|
*/
|
|
2558
2605
|
methodHandlers = {
|
|
@@ -2560,7 +2607,6 @@ var EngineProtocolServer = class {
|
|
|
2560
2607
|
probe: (p) => this.engine.probe(probeParamsOf(p)),
|
|
2561
2608
|
run: (p) => this.run(p),
|
|
2562
2609
|
cancel: (p) => this.cancel(p),
|
|
2563
|
-
interact: (p) => this.interact(p),
|
|
2564
2610
|
read: (p) => this.read(p),
|
|
2565
2611
|
listModels: () => ({ models: this.engine.listModels?.() ?? null }),
|
|
2566
2612
|
validateModel: (p) => this.validateModel(p),
|
|
@@ -2636,9 +2682,6 @@ var EngineProtocolServer = class {
|
|
|
2636
2682
|
if (active !== void 0) active.controller.abort(new Error(`cancelled by host: ${params.reason}`));
|
|
2637
2683
|
return { ok: true };
|
|
2638
2684
|
}
|
|
2639
|
-
async interact(params) {
|
|
2640
|
-
return this.engine.interact({ data: params.handle }, params.action);
|
|
2641
|
-
}
|
|
2642
2685
|
read(params) {
|
|
2643
2686
|
return this.engine.read({ data: params.handle });
|
|
2644
2687
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EnginePort, ReverseRequestClock, EngineCapabilities, ProbeReport, EngineAgentCallOpts, RunContext, EngineRunResult, EngineHandle,
|
|
1
|
+
import { EnginePort, ReverseRequestClock, EngineCapabilities, ProbeReport, EngineAgentCallOpts, RunContext, EngineRunResult, EngineHandle, SessionView } from '@zhushanwen/subagent-engine-sdk';
|
|
2
2
|
|
|
3
3
|
/** 出站帧写入面(main.ts 注入 process.stdout;测试注入内存缓冲)。 */
|
|
4
4
|
type FrameWriter = (frame: unknown) => void;
|
|
@@ -30,17 +30,16 @@ declare class EngineProtocolServer {
|
|
|
30
30
|
constructor(opts: EngineProtocolServerOptions);
|
|
31
31
|
/** 入站帧消费(请求帧 + 反向请求应答帧;main.ts 的行解析器拆行后喂入)。 */
|
|
32
32
|
handleFrame(frame: unknown): void;
|
|
33
|
-
/**
|
|
33
|
+
/** 9 正向方法分发(表驱动:method → 处理器;未知方法 → engine_protocol_unknown_method)。 */
|
|
34
34
|
private dispatch;
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* 9 正向方法 → 处理器映射(每个处理器消费原始 params 并自行收敛类型——
|
|
37
37
|
* 与原 switch case 表达式一一对应)。
|
|
38
38
|
*/
|
|
39
39
|
private readonly methodHandlers;
|
|
40
40
|
private initialize;
|
|
41
41
|
private run;
|
|
42
42
|
private cancel;
|
|
43
|
-
private interact;
|
|
44
43
|
private read;
|
|
45
44
|
private validateModel;
|
|
46
45
|
private emitEvent;
|
|
@@ -214,6 +213,17 @@ declare class ZcodeEngine implements EnginePort {
|
|
|
214
213
|
* ensureAppServerRuntime 自动重建(与崩溃重建同一代码路径,不变量 4)。
|
|
215
214
|
*/
|
|
216
215
|
dispose(): Promise<void>;
|
|
216
|
+
/**
|
|
217
|
+
* [u7a D5] 引擎在途只读快照:activeSessions 非空才算在途——poolKey 'shared' 的
|
|
218
|
+
* app-server **空闲常驻进程恒活,禁止按进程存在判定**(进程在 ≠ 在途,否则推迟
|
|
219
|
+
* 判定恒真、30min 上限从兜底变常态路径,设计 §3.3 D5 显式排除)。计数权威 =
|
|
220
|
+
* activeSessions(attempt 入 create 应答后 add / finally settle 后 delete,与
|
|
221
|
+
* dispose 的 close 帧目标集同一状态源,无双记账)。运行时未初始化(从未 run /
|
|
222
|
+
* 已 dispose)→ 恒 0。
|
|
223
|
+
*/
|
|
224
|
+
inFlightSnapshot(): {
|
|
225
|
+
inFlight: number;
|
|
226
|
+
};
|
|
217
227
|
/** 终态合成(extension-conventions 函数 80 行上限,从 run 提取):aborted / run-failed / parsed 三分支。 */
|
|
218
228
|
private finalizeOutcome;
|
|
219
229
|
/** abort 合成终态:exitCode=null(record 正常收尾,不留僵尸)。 */
|
|
@@ -226,11 +236,6 @@ declare class ZcodeEngine implements EnginePort {
|
|
|
226
236
|
private applyRunFailedOutcome;
|
|
227
237
|
/** parsed 合成终态:content/sessionId/usage 落位 + schema 校验分流 + coarse 事件。 */
|
|
228
238
|
private applyParsedOutcome;
|
|
229
|
-
/**
|
|
230
|
-
* D1 可选面:zcode 首期不支持 conversation(capabilities 声明)——同步拒绝、
|
|
231
|
-
* 不创建进程,文案给可操作建议(A11)。
|
|
232
|
-
*/
|
|
233
|
-
interact(_handle: EngineHandle, _action: InteractAction): Promise<InteractResult>;
|
|
234
239
|
/** [U7] 模型可发现性:v2 桌面登录态聚合(带凭据 provider × models),失败安全返回清单本身可能为空。 */
|
|
235
240
|
listModels(): Array<{
|
|
236
241
|
id: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EnginePort, ReverseRequestClock, EngineCapabilities, ProbeReport, EngineAgentCallOpts, RunContext, EngineRunResult, EngineHandle,
|
|
1
|
+
import { EnginePort, ReverseRequestClock, EngineCapabilities, ProbeReport, EngineAgentCallOpts, RunContext, EngineRunResult, EngineHandle, SessionView } from '@zhushanwen/subagent-engine-sdk';
|
|
2
2
|
|
|
3
3
|
/** 出站帧写入面(main.ts 注入 process.stdout;测试注入内存缓冲)。 */
|
|
4
4
|
type FrameWriter = (frame: unknown) => void;
|
|
@@ -30,17 +30,16 @@ declare class EngineProtocolServer {
|
|
|
30
30
|
constructor(opts: EngineProtocolServerOptions);
|
|
31
31
|
/** 入站帧消费(请求帧 + 反向请求应答帧;main.ts 的行解析器拆行后喂入)。 */
|
|
32
32
|
handleFrame(frame: unknown): void;
|
|
33
|
-
/**
|
|
33
|
+
/** 9 正向方法分发(表驱动:method → 处理器;未知方法 → engine_protocol_unknown_method)。 */
|
|
34
34
|
private dispatch;
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* 9 正向方法 → 处理器映射(每个处理器消费原始 params 并自行收敛类型——
|
|
37
37
|
* 与原 switch case 表达式一一对应)。
|
|
38
38
|
*/
|
|
39
39
|
private readonly methodHandlers;
|
|
40
40
|
private initialize;
|
|
41
41
|
private run;
|
|
42
42
|
private cancel;
|
|
43
|
-
private interact;
|
|
44
43
|
private read;
|
|
45
44
|
private validateModel;
|
|
46
45
|
private emitEvent;
|
|
@@ -214,6 +213,17 @@ declare class ZcodeEngine implements EnginePort {
|
|
|
214
213
|
* ensureAppServerRuntime 自动重建(与崩溃重建同一代码路径,不变量 4)。
|
|
215
214
|
*/
|
|
216
215
|
dispose(): Promise<void>;
|
|
216
|
+
/**
|
|
217
|
+
* [u7a D5] 引擎在途只读快照:activeSessions 非空才算在途——poolKey 'shared' 的
|
|
218
|
+
* app-server **空闲常驻进程恒活,禁止按进程存在判定**(进程在 ≠ 在途,否则推迟
|
|
219
|
+
* 判定恒真、30min 上限从兜底变常态路径,设计 §3.3 D5 显式排除)。计数权威 =
|
|
220
|
+
* activeSessions(attempt 入 create 应答后 add / finally settle 后 delete,与
|
|
221
|
+
* dispose 的 close 帧目标集同一状态源,无双记账)。运行时未初始化(从未 run /
|
|
222
|
+
* 已 dispose)→ 恒 0。
|
|
223
|
+
*/
|
|
224
|
+
inFlightSnapshot(): {
|
|
225
|
+
inFlight: number;
|
|
226
|
+
};
|
|
217
227
|
/** 终态合成(extension-conventions 函数 80 行上限,从 run 提取):aborted / run-failed / parsed 三分支。 */
|
|
218
228
|
private finalizeOutcome;
|
|
219
229
|
/** abort 合成终态:exitCode=null(record 正常收尾,不留僵尸)。 */
|
|
@@ -226,11 +236,6 @@ declare class ZcodeEngine implements EnginePort {
|
|
|
226
236
|
private applyRunFailedOutcome;
|
|
227
237
|
/** parsed 合成终态:content/sessionId/usage 落位 + schema 校验分流 + coarse 事件。 */
|
|
228
238
|
private applyParsedOutcome;
|
|
229
|
-
/**
|
|
230
|
-
* D1 可选面:zcode 首期不支持 conversation(capabilities 声明)——同步拒绝、
|
|
231
|
-
* 不创建进程,文案给可操作建议(A11)。
|
|
232
|
-
*/
|
|
233
|
-
interact(_handle: EngineHandle, _action: InteractAction): Promise<InteractResult>;
|
|
234
239
|
/** [U7] 模型可发现性:v2 桌面登录态聚合(带凭据 provider × models),失败安全返回清单本身可能为空。 */
|
|
235
240
|
listModels(): Array<{
|
|
236
241
|
id: string;
|
package/dist/index.js
CHANGED
package/dist/main.cjs
CHANGED
|
@@ -58,6 +58,9 @@ var ZCODE_APPSERVER_ABORT_GRACE_MS = 3e3;
|
|
|
58
58
|
var ZCODE_APPSERVER_ERR_MODEL_CONFIG_MISSING = -32603;
|
|
59
59
|
var ZCODE_APPSERVER_ERR_BUSY_SESSION = -32010;
|
|
60
60
|
var ZCODE_APPSERVER_HARVEST_GRACE_MS = 1e3;
|
|
61
|
+
function isFailedTerminalStatus(status) {
|
|
62
|
+
return status === "failed" || status === "error";
|
|
63
|
+
}
|
|
61
64
|
|
|
62
65
|
// src/registration.ts
|
|
63
66
|
var import_subagent_engine_sdk10 = require("@zhushanwen/subagent-engine-sdk");
|
|
@@ -682,6 +685,11 @@ var AppServerConnection = class {
|
|
|
682
685
|
reqSeq = 0;
|
|
683
686
|
/** stderr 滚动缓冲(代级:崩溃诊断用)。 */
|
|
684
687
|
stderrTail = "";
|
|
688
|
+
/**
|
|
689
|
+
* stderr tee 落盘流(D6-⑦;merge 裁决:旋转走 logs/stderr-rotation 的路径式
|
|
690
|
+
* rotateStderrLogIfNeeded——W5 边界禁 import subagent-core 的 SizeRotatedAppendStream,
|
|
691
|
+
* 常驻流改裸 WriteStream + 按次轮转检查,帽语义等价)。
|
|
692
|
+
*/
|
|
685
693
|
stderrStream = null;
|
|
686
694
|
stderrStreamFailed = false;
|
|
687
695
|
/**
|
|
@@ -1368,7 +1376,13 @@ var SessionChannel = class {
|
|
|
1368
1376
|
});
|
|
1369
1377
|
const turn = {
|
|
1370
1378
|
sessionId,
|
|
1371
|
-
callbacks: {
|
|
1379
|
+
callbacks: {
|
|
1380
|
+
onTextDelta: opts.onTextDelta,
|
|
1381
|
+
onThinkingDelta: opts.onThinkingDelta,
|
|
1382
|
+
// [PR3] tool 执行期活性回调(SessionTurnCallbacks.onActivity 注释——宿主侧
|
|
1383
|
+
// 无进展守护的工具执行期刷新面)
|
|
1384
|
+
onActivity: opts.onActivity
|
|
1385
|
+
},
|
|
1372
1386
|
settled: false,
|
|
1373
1387
|
deltas: [],
|
|
1374
1388
|
finalText: void 0,
|
|
@@ -1484,7 +1498,9 @@ var SessionChannel = class {
|
|
|
1484
1498
|
if (payload === void 0) return;
|
|
1485
1499
|
this.refreshIdle(turn);
|
|
1486
1500
|
if (this.applyFinalFrame(turn, payload)) return;
|
|
1487
|
-
this.applyStreamDelta(turn, payload)
|
|
1501
|
+
if (!this.applyStreamDelta(turn, payload) && !turn.settled) {
|
|
1502
|
+
turn.callbacks.onActivity?.();
|
|
1503
|
+
}
|
|
1488
1504
|
}
|
|
1489
1505
|
/**
|
|
1490
1506
|
* 收尾帧判定与吸收(A.2 ⑤ 两种形态:payload.response / stopReason+content 变体)。
|
|
@@ -1508,9 +1524,12 @@ var SessionChannel = class {
|
|
|
1508
1524
|
/** 增量 delta 分发:非空 delta 入账 + 回调;终态后迟到丢弃(不变量 2)。
|
|
1509
1525
|
* kind 区分两通道(F2):reasoning_delta 只走 thinking 回调(不入 deltas 账本
|
|
1510
1526
|
* ——deltas 是 response 兜底聚合,推理文本不是答案正文);text_delta / kind
|
|
1511
|
-
* 缺席走 text 路径。
|
|
1527
|
+
* 缺席走 text 路径。
|
|
1528
|
+
* 返回值([PR3]):帧被 delta 路径消费(thinking 或 text,回调若注册则已触发)
|
|
1529
|
+
* → true;无 delta / 空 delta / 终态后迟到丢弃 → false(handleSessionEvent 据
|
|
1530
|
+
* 此分流 onActivity——delta 帧已是宿主可见进展,不双发活性信号)。 */
|
|
1512
1531
|
applyStreamDelta(turn, payload) {
|
|
1513
|
-
if (typeof payload.delta !== "string" || payload.delta === "") return;
|
|
1532
|
+
if (typeof payload.delta !== "string" || payload.delta === "") return false;
|
|
1514
1533
|
if (turn.settled) {
|
|
1515
1534
|
logger2.warn(
|
|
1516
1535
|
`\u7EC8\u6001\u540E\u8FDF\u5230\u7684 delta \u4E22\u5F03\uFF08\u4F1A\u8BDD ${turn.sessionId}\uFF0C\u4E0D\u53D8\u91CF 2\uFF1Aresolve \u540E\u4E0D\u518D\u53D1\u4E8B\u4EF6\uFF09: ${payload.delta.slice(
|
|
@@ -1518,14 +1537,15 @@ var SessionChannel = class {
|
|
|
1518
1537
|
DELTA_LOG_CHARS
|
|
1519
1538
|
)}`
|
|
1520
1539
|
);
|
|
1521
|
-
return;
|
|
1540
|
+
return false;
|
|
1522
1541
|
}
|
|
1523
1542
|
if (payload.kind === "reasoning_delta") {
|
|
1524
1543
|
turn.callbacks.onThinkingDelta?.(payload.delta);
|
|
1525
|
-
return;
|
|
1544
|
+
return true;
|
|
1526
1545
|
}
|
|
1527
1546
|
turn.deltas.push(payload.delta);
|
|
1528
1547
|
turn.callbacks.onTextDelta?.(payload.delta);
|
|
1548
|
+
return true;
|
|
1529
1549
|
}
|
|
1530
1550
|
handleTelemetry(params) {
|
|
1531
1551
|
if (!isRecord3(params)) return;
|
|
@@ -1545,13 +1565,38 @@ var SessionChannel = class {
|
|
|
1545
1565
|
turn.lastTerminalStatus = status;
|
|
1546
1566
|
this.recordTerminalError(turn, params);
|
|
1547
1567
|
if (turn.settled) {
|
|
1548
|
-
|
|
1549
|
-
`\u6743\u5A01\u7EC8\u6001\u665A\u4E8E\u843D\u5B9A\u7ED3\u679C\u5230\u8FBE\uFF08\u4F1A\u8BDD ${turn.sessionId}\uFF0C\u5DF2\u843D\u5B9A source=${turn.terminal?.source}\uFF09\uFF1Aturn.terminal status="${status}" \u4EC5\u8BB0\u5F55\u4E0D\u6539\u5199\uFF08P0-1 D5\u2460\uFF09`
|
|
1550
|
-
);
|
|
1568
|
+
this.logLateTerminal(turn, status);
|
|
1551
1569
|
return;
|
|
1552
1570
|
}
|
|
1553
1571
|
turn.settle({ status, source: "turn.terminal" });
|
|
1554
1572
|
}
|
|
1573
|
+
/**
|
|
1574
|
+
* 已落定 turn 的迟到权威终态分级日志(P-Z2 后续:常态迟到降噪)。真机实证该
|
|
1575
|
+
* 形态的唯一可达路径是 success 终态常态迟到(final-frame 先落定 + 权威
|
|
1576
|
+
* turn.terminal 迟到)——即每个成功任务必经;原无条件 warn 经 SDK cli-entry
|
|
1577
|
+
* 的 stderr 兜底 → runtime [rpc:stderr] 全量 console.error 链路,每个成功任务
|
|
1578
|
+
* 产一条零异常区分度的 ERROR 级日志。按权威 status 分级(落定语义不动——
|
|
1579
|
+
* lastTerminalStatus/lastTerminalError 的入账在上游无条件路径完成):
|
|
1580
|
+
* - "success":常态迟到,零日志;
|
|
1581
|
+
* - "interrupted":用户中断形态,debug(stderr 兜底对 debug no-op——对齐
|
|
1582
|
+
* SDK logger CONSOLE_SINK 语义,host/log 反向请求侧仍可观测);
|
|
1583
|
+
* - 失败类(isFailedTerminalStatus,与引擎失败分流同口径)与 unknown/未识别
|
|
1584
|
+
* status:保守 warn(原样 status 已写入文案)——假成功识破的防御面,理论
|
|
1585
|
+
* 不可达但保留,宁可误报不静默。
|
|
1586
|
+
*/
|
|
1587
|
+
logLateTerminal(turn, status) {
|
|
1588
|
+
if (status === "success") return;
|
|
1589
|
+
const message = `\u6743\u5A01\u7EC8\u6001\u665A\u4E8E\u843D\u5B9A\u7ED3\u679C\u5230\u8FBE\uFF08\u4F1A\u8BDD ${turn.sessionId}\uFF0C\u5DF2\u843D\u5B9A source=${turn.terminal?.source}\uFF09\uFF1Aturn.terminal status="${status}" \u4EC5\u8BB0\u5F55\u4E0D\u6539\u5199\uFF08P0-1 D5\u2460\uFF09`;
|
|
1590
|
+
if (isFailedTerminalStatus(status)) {
|
|
1591
|
+
logger2.warn(message);
|
|
1592
|
+
return;
|
|
1593
|
+
}
|
|
1594
|
+
if (status === "interrupted") {
|
|
1595
|
+
logger2.debug(message);
|
|
1596
|
+
return;
|
|
1597
|
+
}
|
|
1598
|
+
logger2.warn(message);
|
|
1599
|
+
}
|
|
1555
1600
|
/** terminal 帧专属错误信息入账(⛔P-Z2 实证:真实 failed 终态的 errorCode/errorMessage
|
|
1556
1601
|
* 只在 terminal 帧携带,read/delta 拿不到——先到/迟到都记录,消费层合成失败
|
|
1557
1602
|
* 文案时优先采信)。二者均缺失时不挂 lastTerminalError 字段。 */
|
|
@@ -1837,6 +1882,11 @@ var ZcodeEngine = class {
|
|
|
1837
1882
|
// 不变量 3a 的拼接比对不含 reasoning)
|
|
1838
1883
|
onTextDelta: (delta) => ctx.onEvent?.({ type: "text_delta", delta }),
|
|
1839
1884
|
onThinkingDelta: (delta) => ctx.onEvent?.({ type: "thinking_delta", delta }),
|
|
1885
|
+
// [PR3] 工具执行期活性:非终态非增量的 session/event 帧(tool.updated progress
|
|
1886
|
+
// 等,真机探针实证每 ~1s 一帧)→ activity 事件(零载荷纯活性信号——宿主无进展
|
|
1887
|
+
// 守护对任何事件类型刷新;reducer no-op、不落 journal)。zcode 引擎
|
|
1888
|
+
// conversation:"unsupported",run 域是唯一发射面(无 chat 域接线)。
|
|
1889
|
+
onActivity: () => ctx.onEvent?.({ type: "activity" }),
|
|
1840
1890
|
onSessionCreated: (sessionId) => {
|
|
1841
1891
|
currentSessionId = sessionId;
|
|
1842
1892
|
rt.activeSessions.add(sessionId);
|
|
@@ -2063,6 +2113,17 @@ var ZcodeEngine = class {
|
|
|
2063
2113
|
}
|
|
2064
2114
|
await this.shutdownRuntimeAndDisposeChannel(rt);
|
|
2065
2115
|
}
|
|
2116
|
+
/**
|
|
2117
|
+
* [u7a D5] 引擎在途只读快照:activeSessions 非空才算在途——poolKey 'shared' 的
|
|
2118
|
+
* app-server **空闲常驻进程恒活,禁止按进程存在判定**(进程在 ≠ 在途,否则推迟
|
|
2119
|
+
* 判定恒真、30min 上限从兜底变常态路径,设计 §3.3 D5 显式排除)。计数权威 =
|
|
2120
|
+
* activeSessions(attempt 入 create 应答后 add / finally settle 后 delete,与
|
|
2121
|
+
* dispose 的 close 帧目标集同一状态源,无双记账)。运行时未初始化(从未 run /
|
|
2122
|
+
* 已 dispose)→ 恒 0。
|
|
2123
|
+
*/
|
|
2124
|
+
inFlightSnapshot() {
|
|
2125
|
+
return { inFlight: this.appserverRuntime?.activeSessions.size ?? 0 };
|
|
2126
|
+
}
|
|
2066
2127
|
/** 终态合成(extension-conventions 函数 80 行上限,从 run 提取):aborted / run-failed / parsed 三分支。 */
|
|
2067
2128
|
finalizeOutcome(task, ctx, final, usageAcc, startedAt) {
|
|
2068
2129
|
const outcome = {
|
|
@@ -2131,17 +2192,6 @@ var ZcodeEngine = class {
|
|
|
2131
2192
|
}
|
|
2132
2193
|
for (const ev of synthesizeCoarseEvents(payload.response, payload.usage)) emit(ev);
|
|
2133
2194
|
}
|
|
2134
|
-
/**
|
|
2135
|
-
* D1 可选面:zcode 首期不支持 conversation(capabilities 声明)——同步拒绝、
|
|
2136
|
-
* 不创建进程,文案给可操作建议(A11)。
|
|
2137
|
-
*/
|
|
2138
|
-
async interact(_handle, _action) {
|
|
2139
|
-
return {
|
|
2140
|
-
ok: false,
|
|
2141
|
-
code: "engine_capability_unsupported",
|
|
2142
|
-
message: "zcode \u5F15\u64CE\u4E0D\u652F\u6301 conversation \u4EA4\u4E92\u63A7\u5236\u9762\uFF08capabilities.conversation = 'unsupported'\uFF0C\u6BCF\u4EFB\u52A1\u81EA\u5305\u542B\u4F1A\u8BDD\uFF0C\u65E0\u540C\u8FDB\u7A0B idle \u590D\u7528\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u6539\u7528\u5355\u6B21 subagent \u8C03\u7528\u91CD\u65B0\u6D3E\u53D1\u4EFB\u52A1\uFF0C\u6216\u4F7F\u7528 engine: 'pi'\uFF08chatMode idle \u590D\u7528\uFF0C\u652F\u6301 message/close/cancel\uFF09\u3002"
|
|
2143
|
-
};
|
|
2144
|
-
}
|
|
2145
2195
|
/** [U7] 模型可发现性:v2 桌面登录态聚合(带凭据 provider × models),失败安全返回清单本身可能为空。 */
|
|
2146
2196
|
listModels() {
|
|
2147
2197
|
return listZcodeModels(this.deps.sources);
|
|
@@ -2341,9 +2391,6 @@ function authoritativeTerminalStatus(r) {
|
|
|
2341
2391
|
if (r.lastTerminalStatus !== void 0) return r.lastTerminalStatus;
|
|
2342
2392
|
return r.terminal.source === "turn.terminal" ? r.terminal.status : void 0;
|
|
2343
2393
|
}
|
|
2344
|
-
function isFailedTerminalStatus(status) {
|
|
2345
|
-
return status === "failed" || status === "error";
|
|
2346
|
-
}
|
|
2347
2394
|
function parsedAppServerAttempt(task, r) {
|
|
2348
2395
|
if (isFailedTerminalStatus(authoritativeTerminalStatus(r))) {
|
|
2349
2396
|
return failedTerminalAppServerAttempt(r);
|
|
@@ -2519,7 +2566,7 @@ var EngineProtocolServer = class {
|
|
|
2519
2566
|
}
|
|
2520
2567
|
}
|
|
2521
2568
|
}
|
|
2522
|
-
/**
|
|
2569
|
+
/** 9 正向方法分发(表驱动:method → 处理器;未知方法 → engine_protocol_unknown_method)。 */
|
|
2523
2570
|
async dispatch(id, method, params) {
|
|
2524
2571
|
const handler = this.methodHandlers[method];
|
|
2525
2572
|
if (handler === void 0) {
|
|
@@ -2532,7 +2579,7 @@ var EngineProtocolServer = class {
|
|
|
2532
2579
|
return handler(params);
|
|
2533
2580
|
}
|
|
2534
2581
|
/**
|
|
2535
|
-
*
|
|
2582
|
+
* 9 正向方法 → 处理器映射(每个处理器消费原始 params 并自行收敛类型——
|
|
2536
2583
|
* 与原 switch case 表达式一一对应)。
|
|
2537
2584
|
*/
|
|
2538
2585
|
methodHandlers = {
|
|
@@ -2540,7 +2587,6 @@ var EngineProtocolServer = class {
|
|
|
2540
2587
|
probe: (p) => this.engine.probe(probeParamsOf(p)),
|
|
2541
2588
|
run: (p) => this.run(p),
|
|
2542
2589
|
cancel: (p) => this.cancel(p),
|
|
2543
|
-
interact: (p) => this.interact(p),
|
|
2544
2590
|
read: (p) => this.read(p),
|
|
2545
2591
|
listModels: () => ({ models: this.engine.listModels?.() ?? null }),
|
|
2546
2592
|
validateModel: (p) => this.validateModel(p),
|
|
@@ -2616,9 +2662,6 @@ var EngineProtocolServer = class {
|
|
|
2616
2662
|
if (active !== void 0) active.controller.abort(new Error(`cancelled by host: ${params.reason}`));
|
|
2617
2663
|
return { ok: true };
|
|
2618
2664
|
}
|
|
2619
|
-
async interact(params) {
|
|
2620
|
-
return this.engine.interact({ data: params.handle }, params.action);
|
|
2621
|
-
}
|
|
2622
2665
|
read(params) {
|
|
2623
2666
|
return this.engine.read({ data: params.handle });
|
|
2624
2667
|
}
|
package/dist/main.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/zcode-subagent-cli",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "zcode subagent engine as an independent CLI package (W5 of subagent-engine-protocolization): speaks engine-protocol v1 over NDJSON stdio, depends only on @zhushanwen/subagent-engine-sdk (never subagent-core)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"dist/"
|
|
62
62
|
],
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@zhushanwen/subagent-engine-sdk": "0.
|
|
64
|
+
"@zhushanwen/subagent-engine-sdk": "0.3.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/node": "^24.0.0",
|