@clawos-dev/clawd 0.2.93-beta.175.b162fd0 → 0.2.94-beta.176.8dff088
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 +133 -154
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -222,11 +222,7 @@ var init_errors = __esm({
|
|
|
222
222
|
PERMISSION_REQUEST_STALE: "PERMISSION_REQUEST_STALE",
|
|
223
223
|
FILE_TOO_LARGE: "FILE_TOO_LARGE",
|
|
224
224
|
INTERNAL: "INTERNAL",
|
|
225
|
-
UNAUTHORIZED: "UNAUTHORIZED"
|
|
226
|
-
// Ready gate:用户在 pendingSend 已存在时再次 send,daemon 拒绝(不覆盖暂存)。
|
|
227
|
-
// UI ChatInput 应在 popup 态 disable,daemon 兜底;error 帧 broadcast 通知所有 tab。
|
|
228
|
-
// Spec: clawd/superpowers/specs/2026-05-22-cc-ready-gate-design.md §错误处理
|
|
229
|
-
SEND_PENDING: "SEND_PENDING"
|
|
225
|
+
UNAUTHORIZED: "UNAUTHORIZED"
|
|
230
226
|
};
|
|
231
227
|
ClawdError = class extends Error {
|
|
232
228
|
constructor(code, message) {
|
|
@@ -10559,6 +10555,20 @@ function withCommonFields(msg, o) {
|
|
|
10559
10555
|
if (typeof o.uuid === "string" && o.uuid.length > 0) msg.uuid = o.uuid;
|
|
10560
10556
|
return msg;
|
|
10561
10557
|
}
|
|
10558
|
+
function isRejectSentinelLine(obj) {
|
|
10559
|
+
if (!obj || typeof obj !== "object") return false;
|
|
10560
|
+
return typeof obj.toolUseResult === "string";
|
|
10561
|
+
}
|
|
10562
|
+
function isUserPlainTextLine(obj) {
|
|
10563
|
+
if (!obj || typeof obj !== "object") return false;
|
|
10564
|
+
const o = obj;
|
|
10565
|
+
if (o.type !== "user") return false;
|
|
10566
|
+
const message = o.message;
|
|
10567
|
+
const content = message?.content;
|
|
10568
|
+
if (!Array.isArray(content) || content.length !== 1) return false;
|
|
10569
|
+
const part = content[0];
|
|
10570
|
+
return part?.type === "text";
|
|
10571
|
+
}
|
|
10562
10572
|
function messageFromJsonl(obj) {
|
|
10563
10573
|
if (!obj || typeof obj !== "object") return null;
|
|
10564
10574
|
const o = obj;
|
|
@@ -10566,6 +10576,7 @@ function messageFromJsonl(obj) {
|
|
|
10566
10576
|
const ts = o.timestamp ?? o.ts;
|
|
10567
10577
|
if (type === "user" || type === "assistant") {
|
|
10568
10578
|
const message = o.message;
|
|
10579
|
+
if (type === "assistant" && message?.model === "<synthetic>") return null;
|
|
10569
10580
|
const content = message?.content;
|
|
10570
10581
|
const toolResultExtra = type === "user" ? extractToolResultExtraFromRaw(o.toolUseResult) : void 0;
|
|
10571
10582
|
const sourceToolAssistantUUID = type === "user" && typeof o.sourceToolAssistantUUID === "string" ? o.sourceToolAssistantUUID : void 0;
|
|
@@ -10879,7 +10890,11 @@ var init_claude_history = __esm({
|
|
|
10879
10890
|
);
|
|
10880
10891
|
const lines = readJsonlLines(file);
|
|
10881
10892
|
const messages = [];
|
|
10893
|
+
let prevIsRejectSentinel = false;
|
|
10882
10894
|
for (const line of lines) {
|
|
10895
|
+
const skipInterruptedMarker = prevIsRejectSentinel && isUserPlainTextLine(line);
|
|
10896
|
+
prevIsRejectSentinel = isRejectSentinelLine(line);
|
|
10897
|
+
if (skipInterruptedMarker) continue;
|
|
10883
10898
|
const msg = messageFromJsonl(line);
|
|
10884
10899
|
if (msg) messages.push(msg);
|
|
10885
10900
|
}
|
|
@@ -11305,6 +11320,7 @@ function parseClaudeObjectInner(obj) {
|
|
|
11305
11320
|
}
|
|
11306
11321
|
if (type === "assistant") {
|
|
11307
11322
|
const message = obj.message;
|
|
11323
|
+
if (message?.model === "<synthetic>") return events;
|
|
11308
11324
|
if (message) {
|
|
11309
11325
|
const mModel = message.model;
|
|
11310
11326
|
if (typeof mModel === "string" && mModel.length > 0) {
|
|
@@ -21273,9 +21289,7 @@ function cloneState(s) {
|
|
|
21273
21289
|
freshSpawn: s.freshSpawn,
|
|
21274
21290
|
procAlive: s.procAlive,
|
|
21275
21291
|
seenUuids: s.seenUuids,
|
|
21276
|
-
subSessionMeta: s.subSessionMeta
|
|
21277
|
-
readyForSend: s.readyForSend,
|
|
21278
|
-
pendingSend: s.pendingSend
|
|
21292
|
+
subSessionMeta: s.subSessionMeta
|
|
21279
21293
|
};
|
|
21280
21294
|
}
|
|
21281
21295
|
var IDLE_KILL_DELAY_MS = 6e4;
|
|
@@ -21510,23 +21524,6 @@ function applyCommand(state, command, deps) {
|
|
|
21510
21524
|
effects.push({ kind: "cancel-idle-kill", sessionId });
|
|
21511
21525
|
next.status = next.procAlive ? "running" : "idle";
|
|
21512
21526
|
}
|
|
21513
|
-
if (next.pendingSend) {
|
|
21514
|
-
return {
|
|
21515
|
-
state: next,
|
|
21516
|
-
effects: [
|
|
21517
|
-
...effects,
|
|
21518
|
-
{
|
|
21519
|
-
kind: "emit-frame",
|
|
21520
|
-
frame: {
|
|
21521
|
-
type: "error",
|
|
21522
|
-
sessionId,
|
|
21523
|
-
code: ERROR_CODES.SEND_PENDING,
|
|
21524
|
-
message: "a previous message is still pending; cc not yet ready"
|
|
21525
|
-
}
|
|
21526
|
-
}
|
|
21527
|
-
]
|
|
21528
|
-
};
|
|
21529
|
-
}
|
|
21530
21527
|
if (!next.procAlive) {
|
|
21531
21528
|
next.procAlive = true;
|
|
21532
21529
|
next.freshSpawn = true;
|
|
@@ -21535,9 +21532,6 @@ function applyCommand(state, command, deps) {
|
|
|
21535
21532
|
next.nextSeq = 0;
|
|
21536
21533
|
next.turnOpen = false;
|
|
21537
21534
|
next.status = "running";
|
|
21538
|
-
if (deps.mode === "tui") {
|
|
21539
|
-
next.readyForSend = false;
|
|
21540
|
-
}
|
|
21541
21535
|
effects.push({ kind: "spawn", ctx: buildSpawnContext(next, deps) });
|
|
21542
21536
|
effects.push({
|
|
21543
21537
|
kind: "emit-frame",
|
|
@@ -21554,15 +21548,10 @@ function applyCommand(state, command, deps) {
|
|
|
21554
21548
|
uuid: deps.genUuid?.()
|
|
21555
21549
|
};
|
|
21556
21550
|
const pushed = pushEventToBuffer(next, userEvent, deps);
|
|
21557
|
-
let nextState = pushed.state;
|
|
21558
21551
|
effects.push(...pushed.effects);
|
|
21559
|
-
|
|
21560
|
-
|
|
21561
|
-
|
|
21562
|
-
} else {
|
|
21563
|
-
nextState = { ...nextState, pendingSend: { text: command.text } };
|
|
21564
|
-
}
|
|
21565
|
-
return { state: nextState, effects };
|
|
21552
|
+
const payload = deps.encodeStdin(command.text, { sessionId });
|
|
21553
|
+
effects.push({ kind: "write-stdin", payload });
|
|
21554
|
+
return { state: pushed.state, effects };
|
|
21566
21555
|
}
|
|
21567
21556
|
case "stop": {
|
|
21568
21557
|
for (const toolUseId of Object.keys(state.pendingQuestions ?? {})) {
|
|
@@ -21577,7 +21566,6 @@ function applyCommand(state, command, deps) {
|
|
|
21577
21566
|
}
|
|
21578
21567
|
next.pendingPermissions = {};
|
|
21579
21568
|
next.pendingQuestions = {};
|
|
21580
|
-
next.pendingSend = void 0;
|
|
21581
21569
|
if (next.procAlive) {
|
|
21582
21570
|
next.status = "stopping";
|
|
21583
21571
|
effects.push({ kind: "kill", signal: "SIGKILL" });
|
|
@@ -21615,8 +21603,6 @@ function applyCommand(state, command, deps) {
|
|
|
21615
21603
|
}
|
|
21616
21604
|
next.pendingPermissions = {};
|
|
21617
21605
|
next.pendingQuestions = {};
|
|
21618
|
-
next.pendingSend = void 0;
|
|
21619
|
-
next.readyForSend = false;
|
|
21620
21606
|
if (next.procAlive) {
|
|
21621
21607
|
effects.push({ kind: "kill", signal: "SIGKILL" });
|
|
21622
21608
|
}
|
|
@@ -21660,7 +21646,6 @@ function applyCommand(state, command, deps) {
|
|
|
21660
21646
|
next.pendingPermissions = {};
|
|
21661
21647
|
next.freshSpawn = false;
|
|
21662
21648
|
next.seenUuids = [];
|
|
21663
|
-
next.pendingSend = void 0;
|
|
21664
21649
|
effects.push({
|
|
21665
21650
|
kind: "emit-frame",
|
|
21666
21651
|
frame: { type: "session:cleared", sessionId }
|
|
@@ -21698,7 +21683,6 @@ function applyCommand(state, command, deps) {
|
|
|
21698
21683
|
next.pendingPermissions = {};
|
|
21699
21684
|
next.freshSpawn = false;
|
|
21700
21685
|
next.seenUuids = [];
|
|
21701
|
-
next.pendingSend = void 0;
|
|
21702
21686
|
effects.push({ kind: "persist-file", file: nextFile });
|
|
21703
21687
|
effects.push(sessionInfoFrame(nextFile));
|
|
21704
21688
|
effects.push({
|
|
@@ -21733,8 +21717,6 @@ function reduceSession(state, input, deps) {
|
|
|
21733
21717
|
const next = cloneState(state);
|
|
21734
21718
|
next.procAlive = false;
|
|
21735
21719
|
next.status = "stopped";
|
|
21736
|
-
next.pendingSend = void 0;
|
|
21737
|
-
next.readyForSend = false;
|
|
21738
21720
|
const sessionId = next.file.sessionId;
|
|
21739
21721
|
const clearedEffects = Object.keys(state.pendingQuestions ?? {}).map(
|
|
21740
21722
|
(toolUseId) => ({
|
|
@@ -21766,8 +21748,6 @@ function reduceSession(state, input, deps) {
|
|
|
21766
21748
|
case "proc-error": {
|
|
21767
21749
|
const next = cloneState(state);
|
|
21768
21750
|
next.status = "error";
|
|
21769
|
-
next.pendingSend = void 0;
|
|
21770
|
-
next.readyForSend = false;
|
|
21771
21751
|
return {
|
|
21772
21752
|
state: next,
|
|
21773
21753
|
effects: [
|
|
@@ -21894,30 +21874,6 @@ function reduceSession(state, input, deps) {
|
|
|
21894
21874
|
effects: [{ kind: "kill", signal: "SIGKILL" }]
|
|
21895
21875
|
};
|
|
21896
21876
|
}
|
|
21897
|
-
case "ready-detected": {
|
|
21898
|
-
if (!state.procAlive) {
|
|
21899
|
-
return { state, effects: [] };
|
|
21900
|
-
}
|
|
21901
|
-
const next = cloneState(state);
|
|
21902
|
-
next.readyForSend = true;
|
|
21903
|
-
const flushEffects = [];
|
|
21904
|
-
if (state.pendingSend) {
|
|
21905
|
-
const payload = deps.encodeStdin(state.pendingSend.text, {
|
|
21906
|
-
sessionId: next.file.sessionId
|
|
21907
|
-
});
|
|
21908
|
-
flushEffects.push({ kind: "write-stdin", payload });
|
|
21909
|
-
next.pendingSend = void 0;
|
|
21910
|
-
}
|
|
21911
|
-
return { state: next, effects: flushEffects };
|
|
21912
|
-
}
|
|
21913
|
-
case "popup-detected": {
|
|
21914
|
-
if (!state.procAlive) {
|
|
21915
|
-
return { state, effects: [] };
|
|
21916
|
-
}
|
|
21917
|
-
const next = cloneState(state);
|
|
21918
|
-
next.readyForSend = false;
|
|
21919
|
-
return { state: next, effects: [] };
|
|
21920
|
-
}
|
|
21921
21877
|
case "inject-owner-text": {
|
|
21922
21878
|
const ownerEvent = {
|
|
21923
21879
|
kind: "meta-text",
|
|
@@ -22106,8 +22062,7 @@ var SessionRunner = class {
|
|
|
22106
22062
|
resolveContextWindow: this.hooks.resolveContextWindow,
|
|
22107
22063
|
genUuid: this.hooks.genUuid ?? v4_default,
|
|
22108
22064
|
ownerDisplayName: this.hooks.ownerDisplayName,
|
|
22109
|
-
personaRoot: this.hooks.personaRoot
|
|
22110
|
-
mode: this.hooks.mode ?? "sdk"
|
|
22065
|
+
personaRoot: this.hooks.personaRoot
|
|
22111
22066
|
};
|
|
22112
22067
|
const { state, effects } = reduceSession(this.state, inputMsg, deps);
|
|
22113
22068
|
this.state = state;
|
|
@@ -22537,14 +22492,7 @@ function makeInitialState(file, subSessionMeta) {
|
|
|
22537
22492
|
freshSpawn: false,
|
|
22538
22493
|
procAlive: false,
|
|
22539
22494
|
seenUuids: [],
|
|
22540
|
-
subSessionMeta
|
|
22541
|
-
// Ready gate:保守起手 true,让 SDK 模式与 TUI 接线未完成时 send 仍走旧的"立即写 stdin"
|
|
22542
|
-
// 路径不破坏 SDK 用户体验。TUI 模式 manager 集成(Task 6)会在 spawn 时显式 dispatch
|
|
22543
|
-
// 'popup-detected' 把 flag 翻 false → 等 ReadyGate emit ready 再 dispatch 'ready-detected'
|
|
22544
|
-
// 翻回 true 并 flush pendingSend。
|
|
22545
|
-
// daemon-only 字段,不上 wire / 不写 SessionFile(compressFrameForWire 只处理
|
|
22546
|
-
// session:status,SessionState 不直接序列化)。
|
|
22547
|
-
readyForSend: true
|
|
22495
|
+
subSessionMeta
|
|
22548
22496
|
};
|
|
22549
22497
|
}
|
|
22550
22498
|
var SessionManager = class {
|
|
@@ -22787,9 +22735,6 @@ var SessionManager = class {
|
|
|
22787
22735
|
// Phase 2 capability platform (plan §3): 透传 personaRoot, buildSpawnArgs 据
|
|
22788
22736
|
// cwd 是否在 personaRoot 下自动决定是否注入 --settings sandbox-settings.json.
|
|
22789
22737
|
personaRoot: this.deps.personaRoot,
|
|
22790
|
-
// 透传给 ReducerDeps.mode:reducer send !procAlive spawn 路径据此判断要不要把
|
|
22791
|
-
// readyForSend 翻 false(TUI 翻 false 让 user_text 走 pendingSend 暂存;SDK 不动保持直写)
|
|
22792
|
-
mode: this.deps.mode,
|
|
22793
22738
|
// file-sharing (spec §6 PR 3):闭包 scope + sessionId,runner 只暴露 tool/relPath/cwd
|
|
22794
22739
|
onFileEdit: attachmentGroup ? (input) => attachmentGroup.onFileEdit({
|
|
22795
22740
|
scope,
|
|
@@ -23925,9 +23870,6 @@ var SessionManager = class {
|
|
|
23925
23870
|
},
|
|
23926
23871
|
"broadcast"
|
|
23927
23872
|
);
|
|
23928
|
-
const runner = this.runners.get(sid);
|
|
23929
|
-
if (!runner) return;
|
|
23930
|
-
runner.input({ kind: visible ? "popup-detected" : "ready-detected" });
|
|
23931
23873
|
}
|
|
23932
23874
|
/** toolSessionId → sessionId 反查(遍历 runners);session 数典型 < 10,O(n) 可接受 */
|
|
23933
23875
|
sessionIdByToolSid(toolSessionId) {
|
|
@@ -25212,29 +25154,6 @@ var POPUP_FOOTER_PATTERNS = [
|
|
|
25212
25154
|
{ kind: "permission", regex: /Tab to amend|Do you want to proceed/i },
|
|
25213
25155
|
{ kind: "question", regex: /Enter to select|↑\/↓ to navigate/i }
|
|
25214
25156
|
];
|
|
25215
|
-
function matchPopupFooterKind(bufferText) {
|
|
25216
|
-
for (const p2 of POPUP_FOOTER_PATTERNS) {
|
|
25217
|
-
if (p2.regex.test(bufferText)) return p2.kind;
|
|
25218
|
-
}
|
|
25219
|
-
return null;
|
|
25220
|
-
}
|
|
25221
|
-
function hasInputFrame(bufferText) {
|
|
25222
|
-
const lines = bufferText.split("\n");
|
|
25223
|
-
for (let i = 1; i < lines.length; i++) {
|
|
25224
|
-
const cur = lines[i];
|
|
25225
|
-
if (!/^\s*❯\s/.test(cur)) continue;
|
|
25226
|
-
const prev = lines[i - 1];
|
|
25227
|
-
if (/─{20,}/.test(prev)) return true;
|
|
25228
|
-
}
|
|
25229
|
-
return false;
|
|
25230
|
-
}
|
|
25231
|
-
var READY_SIGNATURE_PATTERNS = [
|
|
25232
|
-
{ name: "input-frame", match: hasInputFrame }
|
|
25233
|
-
];
|
|
25234
|
-
function isReadySignature(bufferText) {
|
|
25235
|
-
if (matchPopupFooterKind(bufferText) !== null) return false;
|
|
25236
|
-
return READY_SIGNATURE_PATTERNS.some((p2) => p2.match(bufferText));
|
|
25237
|
-
}
|
|
25238
25157
|
function createPopupDetector(opts) {
|
|
25239
25158
|
const term = new Terminal({
|
|
25240
25159
|
cols: opts.cols ?? 120,
|
|
@@ -25246,52 +25165,43 @@ function createPopupDetector(opts) {
|
|
|
25246
25165
|
term.loadAddon(serializeAddon);
|
|
25247
25166
|
let visible = null;
|
|
25248
25167
|
let pendingClear = null;
|
|
25249
|
-
let quietTimer = null;
|
|
25250
|
-
const QUIET_MS = opts.quietMs ?? 300;
|
|
25251
25168
|
let parseSeq = 0;
|
|
25252
25169
|
let pendingParse = 0;
|
|
25253
25170
|
let drainWaiters = [];
|
|
25254
25171
|
let disposed = false;
|
|
25255
|
-
const
|
|
25172
|
+
const scanFooter = () => {
|
|
25256
25173
|
const buf = term.buffer.active;
|
|
25257
|
-
const lines = [];
|
|
25258
25174
|
for (let i = 0; i < buf.length; i++) {
|
|
25259
25175
|
const line = buf.getLine(i);
|
|
25260
25176
|
if (!line) continue;
|
|
25261
|
-
|
|
25177
|
+
const text = line.translateToString(true);
|
|
25178
|
+
if (!text) continue;
|
|
25179
|
+
for (const p2 of POPUP_FOOTER_PATTERNS) {
|
|
25180
|
+
if (p2.regex.test(text)) return p2.kind;
|
|
25181
|
+
}
|
|
25262
25182
|
}
|
|
25263
|
-
|
|
25264
|
-
return { ready: isReadySignature(text), footerKind: matchPopupFooterKind(text) };
|
|
25183
|
+
return null;
|
|
25265
25184
|
};
|
|
25266
25185
|
const tick = () => {
|
|
25267
|
-
|
|
25268
|
-
|
|
25269
|
-
|
|
25270
|
-
|
|
25271
|
-
|
|
25272
|
-
if (
|
|
25273
|
-
|
|
25274
|
-
|
|
25275
|
-
}
|
|
25276
|
-
|
|
25277
|
-
|
|
25278
|
-
|
|
25279
|
-
|
|
25280
|
-
|
|
25281
|
-
|
|
25282
|
-
|
|
25283
|
-
|
|
25284
|
-
|
|
25285
|
-
|
|
25286
|
-
pendingClear = setTimeout(() => {
|
|
25287
|
-
pendingClear = null;
|
|
25288
|
-
if (visible === toClear) {
|
|
25289
|
-
visible = null;
|
|
25290
|
-
opts.onTransition(toClear, false);
|
|
25291
|
-
}
|
|
25292
|
-
}, opts.clearQuietMs);
|
|
25293
|
-
}
|
|
25294
|
-
}, QUIET_MS);
|
|
25186
|
+
const matched = scanFooter();
|
|
25187
|
+
if (matched && visible === null) {
|
|
25188
|
+
visible = matched;
|
|
25189
|
+
opts.onTransition(matched, true);
|
|
25190
|
+
} else if (matched && visible !== null) {
|
|
25191
|
+
if (pendingClear) {
|
|
25192
|
+
clearTimeout(pendingClear);
|
|
25193
|
+
pendingClear = null;
|
|
25194
|
+
}
|
|
25195
|
+
} else if (!matched && visible !== null && !pendingClear) {
|
|
25196
|
+
const toClear = visible;
|
|
25197
|
+
pendingClear = setTimeout(() => {
|
|
25198
|
+
pendingClear = null;
|
|
25199
|
+
if (visible === toClear) {
|
|
25200
|
+
visible = null;
|
|
25201
|
+
opts.onTransition(toClear, false);
|
|
25202
|
+
}
|
|
25203
|
+
}, opts.clearQuietMs);
|
|
25204
|
+
}
|
|
25295
25205
|
};
|
|
25296
25206
|
return {
|
|
25297
25207
|
get visibleKind() {
|
|
@@ -25334,10 +25244,6 @@ function createPopupDetector(opts) {
|
|
|
25334
25244
|
},
|
|
25335
25245
|
dispose() {
|
|
25336
25246
|
disposed = true;
|
|
25337
|
-
if (quietTimer) {
|
|
25338
|
-
clearTimeout(quietTimer);
|
|
25339
|
-
quietTimer = null;
|
|
25340
|
-
}
|
|
25341
25247
|
if (pendingClear) {
|
|
25342
25248
|
clearTimeout(pendingClear);
|
|
25343
25249
|
pendingClear = null;
|
|
@@ -25353,6 +25259,64 @@ function createPopupDetector(opts) {
|
|
|
25353
25259
|
}
|
|
25354
25260
|
};
|
|
25355
25261
|
}
|
|
25262
|
+
function createBootGate(pty, ptyChild, logger, toolSessionId) {
|
|
25263
|
+
const FALLBACK_MS = 4e3;
|
|
25264
|
+
const POST_POPUP_QUIET_MS = 800;
|
|
25265
|
+
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, " ");
|
|
25266
|
+
const popups = {
|
|
25267
|
+
trust: { handled: false, regex: /trust this folder/i, accept: "\r", label: "trust-folder" },
|
|
25268
|
+
bypass: {
|
|
25269
|
+
handled: false,
|
|
25270
|
+
regex: /Bypass Permissions mode|By proceeding/i,
|
|
25271
|
+
accept: "2\r",
|
|
25272
|
+
label: "bypass-warning"
|
|
25273
|
+
}
|
|
25274
|
+
};
|
|
25275
|
+
let scanBuf = "";
|
|
25276
|
+
let opened = false;
|
|
25277
|
+
let postPopupQuiet = null;
|
|
25278
|
+
const openGate = (reason) => {
|
|
25279
|
+
if (opened) return;
|
|
25280
|
+
opened = true;
|
|
25281
|
+
logger?.debug("boot gate setReady", { toolSessionId, reason });
|
|
25282
|
+
clearTimeout(fallbackTimer);
|
|
25283
|
+
if (postPopupQuiet) clearTimeout(postPopupQuiet);
|
|
25284
|
+
scanBuf = "";
|
|
25285
|
+
ptyChild.setReady();
|
|
25286
|
+
};
|
|
25287
|
+
const fallbackTimer = setTimeout(() => openGate("timeout-4s"), FALLBACK_MS);
|
|
25288
|
+
return {
|
|
25289
|
+
get opened() {
|
|
25290
|
+
return opened;
|
|
25291
|
+
},
|
|
25292
|
+
feedBytes(data) {
|
|
25293
|
+
scanBuf += data.toString("utf8");
|
|
25294
|
+
const cleanBuf = stripAnsi(scanBuf).replace(/\s+/g, " ");
|
|
25295
|
+
for (const popup of Object.values(popups)) {
|
|
25296
|
+
if (popup.handled) continue;
|
|
25297
|
+
if (popup.regex.test(cleanBuf)) {
|
|
25298
|
+
popup.handled = true;
|
|
25299
|
+
logger?.debug(`${popup.label} popup auto-yes`, { toolSessionId });
|
|
25300
|
+
try {
|
|
25301
|
+
pty.write(popup.accept);
|
|
25302
|
+
} catch (err) {
|
|
25303
|
+
logger?.warn(`${popup.label} auto-yes write failed`, {
|
|
25304
|
+
error: err.message
|
|
25305
|
+
});
|
|
25306
|
+
}
|
|
25307
|
+
scanBuf = "";
|
|
25308
|
+
if (postPopupQuiet) clearTimeout(postPopupQuiet);
|
|
25309
|
+
postPopupQuiet = setTimeout(() => openGate("post-popup-quiet"), POST_POPUP_QUIET_MS);
|
|
25310
|
+
}
|
|
25311
|
+
}
|
|
25312
|
+
if (scanBuf.length > 8192) scanBuf = scanBuf.slice(-4096);
|
|
25313
|
+
},
|
|
25314
|
+
dispose() {
|
|
25315
|
+
clearTimeout(fallbackTimer);
|
|
25316
|
+
if (postPopupQuiet) clearTimeout(postPopupQuiet);
|
|
25317
|
+
}
|
|
25318
|
+
};
|
|
25319
|
+
}
|
|
25356
25320
|
var ClaudeTuiAdapter = class extends ClaudeAdapter {
|
|
25357
25321
|
// id 仍是 'claude'(继承)— UI / SessionFile.tool / capabilities:get RPC 字面量不变,
|
|
25358
25322
|
// 完全兼容 SDK 模式 wiring。TUI 行为通过 daemon mode 流转,不通过 tool id 区分
|
|
@@ -25392,14 +25356,14 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
|
|
|
25392
25356
|
const ptyChild = new PtyChildProcess(pty, {
|
|
25393
25357
|
logger: this.tuiLogger,
|
|
25394
25358
|
tag: ctx.toolSessionId ?? "no-tsid",
|
|
25395
|
-
//
|
|
25396
|
-
//
|
|
25397
|
-
//
|
|
25398
|
-
bootGate:
|
|
25359
|
+
// boot gate:CC TUI 启动 + popup 处理前 stdin.write 一律 buffer,防止用户 prompt 在
|
|
25360
|
+
// CC 加载 node runtime 时被吞。bootGate scanner 在 popup 处理完成 / 4s 兜底任一条件
|
|
25361
|
+
// 触发后调 setReady() 开闸
|
|
25362
|
+
bootGate: true
|
|
25399
25363
|
});
|
|
25364
|
+
const bootGate = createBootGate(pty, ptyChild, this.tuiLogger, ctx.toolSessionId);
|
|
25400
25365
|
const detector = createPopupDetector({
|
|
25401
25366
|
clearQuietMs: 200,
|
|
25402
|
-
// quietMs 走默认 300ms — 屏幕静止判定时长,对 cc TUI 启动期重绘节奏足够
|
|
25403
25367
|
onTransition: (kind, visible) => {
|
|
25404
25368
|
if (!ctx.toolSessionId || !this.tuiOpts.onPopupTransition) return;
|
|
25405
25369
|
this.tuiLogger?.debug("popup transition", {
|
|
@@ -25436,7 +25400,11 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
|
|
|
25436
25400
|
if (ctx.toolSessionId && this.tuiOpts.onPtyData) {
|
|
25437
25401
|
this.tuiOpts.onPtyData(ctx.toolSessionId, merged.toString("base64"), seq);
|
|
25438
25402
|
}
|
|
25439
|
-
|
|
25403
|
+
if (bootGate.opened) {
|
|
25404
|
+
void detector.writeBytes(merged.toString("utf8"), seq);
|
|
25405
|
+
} else {
|
|
25406
|
+
bootGate.feedBytes(merged);
|
|
25407
|
+
}
|
|
25440
25408
|
if (ctx.toolSessionId) {
|
|
25441
25409
|
probePtyDataThrottled(ctx.toolSessionId, merged.length, merged);
|
|
25442
25410
|
}
|
|
@@ -25453,6 +25421,7 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
|
|
|
25453
25421
|
if (coalesceBuf.length > 0) {
|
|
25454
25422
|
flushCoalesced();
|
|
25455
25423
|
}
|
|
25424
|
+
bootGate.dispose();
|
|
25456
25425
|
if (ctx.toolSessionId && this.tuiOpts.onDetectorUnregister) {
|
|
25457
25426
|
this.tuiOpts.onDetectorUnregister(ctx.toolSessionId);
|
|
25458
25427
|
}
|
|
@@ -25970,7 +25939,8 @@ var SessionObserver = class {
|
|
|
25970
25939
|
pollTimer: null,
|
|
25971
25940
|
lastSize: size,
|
|
25972
25941
|
buf: "",
|
|
25973
|
-
adapter: args.adapter
|
|
25942
|
+
adapter: args.adapter,
|
|
25943
|
+
prevIsRejectSentinel: false
|
|
25974
25944
|
};
|
|
25975
25945
|
try {
|
|
25976
25946
|
import_node_fs14.default.mkdirSync(import_node_path15.default.dirname(filePath), { recursive: true });
|
|
@@ -26043,6 +26013,15 @@ var SessionObserver = class {
|
|
|
26043
26013
|
while ((newlineIndex = w2.buf.indexOf("\n")) >= 0) {
|
|
26044
26014
|
const line = w2.buf.slice(0, newlineIndex);
|
|
26045
26015
|
w2.buf = w2.buf.slice(newlineIndex + 1);
|
|
26016
|
+
let parsed = null;
|
|
26017
|
+
try {
|
|
26018
|
+
parsed = line.trim() ? JSON.parse(line) : null;
|
|
26019
|
+
} catch {
|
|
26020
|
+
parsed = null;
|
|
26021
|
+
}
|
|
26022
|
+
const skipAsMarker = w2.prevIsRejectSentinel && parsed !== null && isUserPlainTextLine(parsed);
|
|
26023
|
+
w2.prevIsRejectSentinel = parsed !== null ? isRejectSentinelLine(parsed) : false;
|
|
26024
|
+
if (skipAsMarker) continue;
|
|
26046
26025
|
const events = w2.adapter.parseLine(line);
|
|
26047
26026
|
this.maybeReportUserMessage(w2.sessionId, line);
|
|
26048
26027
|
if (events.length > 0) {
|
package/package.json
CHANGED