@clawos-dev/clawd 0.2.161 → 0.2.162
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/cli.cjs +77 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -4927,6 +4927,13 @@ var init_schemas = __esm({
|
|
|
4927
4927
|
toolUseId: external_exports.string(),
|
|
4928
4928
|
questions: external_exports.array(AskQuestionItemSchema)
|
|
4929
4929
|
}),
|
|
4930
|
+
// turn_end —— 一轮 AI 响应结束。消费者:reducer pushEventToBuffer 翻 turnOpen=false;
|
|
4931
|
+
// UI useChatPanelState 收 "Claude is working" spinner(lastEventKind===turn_end)。
|
|
4932
|
+
// 三个产生来源:
|
|
4933
|
+
// ① SDK 模式 stream-json `result` 帧(claude.ts)—— stdout 最后一帧,可靠
|
|
4934
|
+
// ② TUI 模式 observer 读 JSONL `system/turn_duration` 行(claude-tui.ts parseLine)
|
|
4935
|
+
// ⚠️ CC 写此行早于该轮尾段正文落盘,可能被尾随 text 覆盖 lastEventKind(③ 存在的原因)
|
|
4936
|
+
// ③ TUI 模式屏幕内容静止(observeScreenIdle → manager.dispatchTurnIdle inject)—— 兜 ② 的覆盖
|
|
4930
4937
|
external_exports.object({
|
|
4931
4938
|
...ParsedEventBase,
|
|
4932
4939
|
kind: external_exports.literal("turn_end")
|
|
@@ -35008,6 +35015,21 @@ var SessionManager = class {
|
|
|
35008
35015
|
if (!runner) return;
|
|
35009
35016
|
runner.input({ kind: "ready-detected" });
|
|
35010
35017
|
}
|
|
35018
|
+
/**
|
|
35019
|
+
* ClaudeTuiAdapter onTurnIdle callback:屏幕内容静止(turn 结束)时 inject 一个权威 turn_end。
|
|
35020
|
+
* 修 turn_duration 写盘早于尾段正文 → observer 尾随 text 覆盖 lastEventKind → spinner 不熄。
|
|
35021
|
+
* 静止触发(~1.2s)远晚于 observer poll(200ms),故此 turn_end 必排在尾随 text 之后 = buffer 最后一个。
|
|
35022
|
+
* 仅 tui 模式;runner 缺失 noop。turn_end 无 uuid 不参与 dedup(放行)。
|
|
35023
|
+
* 注:重复 inject(屏幕静止边缘多 fire)不产生错误状态——turnOpen 已 false、idle-kill 有
|
|
35024
|
+
* running-idle guard——但仍 append buffer + 刷 updatedAt + 广播 session:info(非真 no-op,churn 可接受)。
|
|
35025
|
+
*/
|
|
35026
|
+
dispatchTurnIdle(toolSessionId) {
|
|
35027
|
+
if (this.deps.mode !== "tui") return;
|
|
35028
|
+
const sid = this.sessionIdByToolSid(toolSessionId);
|
|
35029
|
+
const runner = sid ? this.runners.get(sid) : void 0;
|
|
35030
|
+
if (!runner) return;
|
|
35031
|
+
runner.input({ kind: "inject-events", events: [{ kind: "turn_end" }] });
|
|
35032
|
+
}
|
|
35011
35033
|
/** toolSessionId → sessionId 反查(遍历 runners);session 数典型 < 10,O(n) 可接受 */
|
|
35012
35034
|
sessionIdByToolSid(toolSessionId) {
|
|
35013
35035
|
for (const [sid, runner] of this.runners) {
|
|
@@ -37372,7 +37394,49 @@ function observeReady(surface, opts) {
|
|
|
37372
37394
|
}
|
|
37373
37395
|
};
|
|
37374
37396
|
}
|
|
37397
|
+
function observeScreenIdle(surface, opts) {
|
|
37398
|
+
const visibleRows = opts.visibleRows ?? 44;
|
|
37399
|
+
let lastSnap = null;
|
|
37400
|
+
let armed = false;
|
|
37401
|
+
let timer = null;
|
|
37402
|
+
let disposed = false;
|
|
37403
|
+
const snapOf = (lines) => lines.slice(-visibleRows).join("\n").replace(/[ \t]+$/gm, "");
|
|
37404
|
+
const clear = () => {
|
|
37405
|
+
if (timer) {
|
|
37406
|
+
clearTimeout(timer);
|
|
37407
|
+
timer = null;
|
|
37408
|
+
}
|
|
37409
|
+
};
|
|
37410
|
+
const fire = () => {
|
|
37411
|
+
timer = null;
|
|
37412
|
+
if (disposed) return;
|
|
37413
|
+
if (opts.getPopupVisible()) {
|
|
37414
|
+
timer = setTimeout(fire, opts.idleMs);
|
|
37415
|
+
return;
|
|
37416
|
+
}
|
|
37417
|
+
if (armed) return;
|
|
37418
|
+
armed = true;
|
|
37419
|
+
opts.onIdle();
|
|
37420
|
+
};
|
|
37421
|
+
const unsub = surface.onTick((lines) => {
|
|
37422
|
+
if (disposed) return;
|
|
37423
|
+
const snap = snapOf(lines);
|
|
37424
|
+
if (snap === lastSnap) return;
|
|
37425
|
+
lastSnap = snap;
|
|
37426
|
+
armed = false;
|
|
37427
|
+
clear();
|
|
37428
|
+
timer = setTimeout(fire, opts.idleMs);
|
|
37429
|
+
});
|
|
37430
|
+
return {
|
|
37431
|
+
dispose() {
|
|
37432
|
+
disposed = true;
|
|
37433
|
+
unsub();
|
|
37434
|
+
clear();
|
|
37435
|
+
}
|
|
37436
|
+
};
|
|
37437
|
+
}
|
|
37375
37438
|
var BYPASS_SETTLE_MS = 300;
|
|
37439
|
+
var SCREEN_IDLE_MS = 1200;
|
|
37376
37440
|
function createBootGate(pty, logger) {
|
|
37377
37441
|
const stripAnsi = (s) => s.replace(/\x1b\[[0-9;?]*C/g, " ").replace(/\x1b\[[0-9;?]*[a-zA-Z]/g, "").replace(/\x1b\][^\x07]*\x07/g, "").replace(/\x1b[NOPM=>78]/g, "").replace(/[\x00-\x1f\x7f]/g, " ");
|
|
37378
37442
|
const popups = {
|
|
@@ -37504,6 +37568,15 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
|
|
|
37504
37568
|
// popup_close 信号源:ready observer 扫到 ❯ + ─{20,} 输入框结构 → 输入框可见 → popup 已关
|
|
37505
37569
|
getInputFrameVisible: () => readyObserver.inputFrameVisible
|
|
37506
37570
|
});
|
|
37571
|
+
const screenIdleObserver = observeScreenIdle(surface, {
|
|
37572
|
+
idleMs: SCREEN_IDLE_MS,
|
|
37573
|
+
onIdle: () => {
|
|
37574
|
+
if (!ctx.toolSessionId || !this.tuiOpts.onTurnIdle) return;
|
|
37575
|
+
this.tuiLogger?.debug("screen-idle \u2192 turn_end", { toolSessionId: ctx.toolSessionId });
|
|
37576
|
+
this.tuiOpts.onTurnIdle(ctx.toolSessionId);
|
|
37577
|
+
},
|
|
37578
|
+
getPopupVisible: () => popupObserver.visibleKind !== null
|
|
37579
|
+
});
|
|
37507
37580
|
if (ctx.toolSessionId && this.tuiOpts.onSurfaceRegister) {
|
|
37508
37581
|
this.tuiOpts.onSurfaceRegister(ctx.toolSessionId, surface);
|
|
37509
37582
|
}
|
|
@@ -37551,6 +37624,7 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
|
|
|
37551
37624
|
bootGate.dispose();
|
|
37552
37625
|
readyObserver.dispose();
|
|
37553
37626
|
popupObserver.dispose();
|
|
37627
|
+
screenIdleObserver.dispose();
|
|
37554
37628
|
if (ctx.toolSessionId && this.tuiOpts.onSurfaceUnregister) {
|
|
37555
37629
|
this.tuiOpts.onSurfaceUnregister(ctx.toolSessionId);
|
|
37556
37630
|
}
|
|
@@ -46820,7 +46894,9 @@ async function startDaemon(config) {
|
|
|
46820
46894
|
onSurfaceRegister: (tsid, surface) => manager.registerSurface(tsid, surface),
|
|
46821
46895
|
onSurfaceUnregister: (tsid) => manager.unregisterSurface(tsid),
|
|
46822
46896
|
// ReadyGate v2:ReadyDetector emit ready 时投递 reducer 'ready-detected' input
|
|
46823
|
-
onReady: (tsid) => manager.dispatchReadyDetected(tsid)
|
|
46897
|
+
onReady: (tsid) => manager.dispatchReadyDetected(tsid),
|
|
46898
|
+
// 屏幕静止 → 补权威 turn_end(修 turn_duration 尾随 text 覆盖 lastEventKind)
|
|
46899
|
+
onTurnIdle: (tsid) => manager.dispatchTurnIdle(tsid)
|
|
46824
46900
|
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
46825
46901
|
registerAdapter("claude", claudeAdapter);
|
|
46826
46902
|
registerAdapter("codex", new CodexAdapter({ logger, historyReader: new CodexHistoryReader() }));
|