@clawos-dev/clawd 0.2.598 → 0.2.600
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
CHANGED
|
@@ -46612,6 +46612,7 @@ function applyCommand(state, command, deps) {
|
|
|
46612
46612
|
resolvedModel: _model,
|
|
46613
46613
|
// aiLabel 是旧对话内容生成的标题,/clear 后属于不存在的话题,一并清掉
|
|
46614
46614
|
aiLabel: _aiLabel,
|
|
46615
|
+
aiLabelGeneratedAt: _titleGeneratedAt,
|
|
46615
46616
|
...rest
|
|
46616
46617
|
} = next.file;
|
|
46617
46618
|
void _drop;
|
|
@@ -46620,6 +46621,7 @@ function applyCommand(state, command, deps) {
|
|
|
46620
46621
|
void _branch;
|
|
46621
46622
|
void _model;
|
|
46622
46623
|
void _aiLabel;
|
|
46624
|
+
void _titleGeneratedAt;
|
|
46623
46625
|
const nextFile = {
|
|
46624
46626
|
...rest,
|
|
46625
46627
|
...command.nextToolSessionId ? { toolSessionId: command.nextToolSessionId } : {},
|
|
@@ -47686,7 +47688,7 @@ var SessionManager = class {
|
|
|
47686
47688
|
// sessionId → SessionRunner;在 send / ensureSession 时按需创建
|
|
47687
47689
|
runners = /* @__PURE__ */ new Map();
|
|
47688
47690
|
// 标题生成 in-flight 防重(进程内);跨重启防重靠 SessionFile.aiLabelGeneratedAt
|
|
47689
|
-
titleGenPending = /* @__PURE__ */ new
|
|
47691
|
+
titleGenPending = /* @__PURE__ */ new Map();
|
|
47690
47692
|
// 当同步命令执行期间,runner 的 emit-frame 临时 push 到这里;
|
|
47691
47693
|
// null 表示当前是异步路径(stdout 'data' / proc 'exit' 等),走 deps.broadcastFrame
|
|
47692
47694
|
currentCollector = null;
|
|
@@ -48445,6 +48447,10 @@ var SessionManager = class {
|
|
|
48445
48447
|
}
|
|
48446
48448
|
update(args) {
|
|
48447
48449
|
const existing = this.getFile(args.sessionId);
|
|
48450
|
+
if (args.patch.model !== void 0 || args.patch.label) {
|
|
48451
|
+
this.titleGenPending.get(args.sessionId)?.abort();
|
|
48452
|
+
this.titleGenPending.delete(args.sessionId);
|
|
48453
|
+
}
|
|
48448
48454
|
const runner = this.runners.get(args.sessionId);
|
|
48449
48455
|
if (runner) {
|
|
48450
48456
|
const { value, broadcast } = this.withCollector(() => {
|
|
@@ -48454,6 +48460,12 @@ var SessionManager = class {
|
|
|
48454
48460
|
return { response: value, broadcast };
|
|
48455
48461
|
}
|
|
48456
48462
|
const updated = { ...existing, ...args.patch, updatedAt: nowIso2(this.deps) };
|
|
48463
|
+
if (args.patch.model !== void 0) {
|
|
48464
|
+
delete updated.resolvedModel;
|
|
48465
|
+
delete updated.resolvedEffort;
|
|
48466
|
+
} else if (args.patch.effort !== void 0) {
|
|
48467
|
+
delete updated.resolvedEffort;
|
|
48468
|
+
}
|
|
48457
48469
|
this.writeOwned(updated);
|
|
48458
48470
|
return { response: updated, broadcast: [] };
|
|
48459
48471
|
}
|
|
@@ -48517,6 +48529,7 @@ var SessionManager = class {
|
|
|
48517
48529
|
delete(args) {
|
|
48518
48530
|
const existing = this.findOwnedSession(args.sessionId);
|
|
48519
48531
|
if (!existing) throw new ClawdError(ERROR_CODES.SESSION_NOT_FOUND, args.sessionId);
|
|
48532
|
+
this.titleGenPending.get(args.sessionId)?.abort();
|
|
48520
48533
|
const scope = this.scopeForFile(existing);
|
|
48521
48534
|
const runner = this.runners.get(args.sessionId);
|
|
48522
48535
|
if (runner) {
|
|
@@ -48580,7 +48593,7 @@ var SessionManager = class {
|
|
|
48580
48593
|
/**
|
|
48581
48594
|
* 首条 send 触发的智能标题自产(spec:PR #1196 追加拍板 2026-08-17)。
|
|
48582
48595
|
* 背景见 tools/title-generator.ts 头注释——CC/codex 两条上游标题数据源都等不来
|
|
48583
|
-
* 「首轮即有」,daemon
|
|
48596
|
+
* 「首轮即有」,daemon 用本会话选定的引擎和模型自己生成,与主 turn 并行,完成后经
|
|
48584
48597
|
* manager.update 内部通道写 aiLabel(marker patch:不刷 updatedAt、广播 session:info)。
|
|
48585
48598
|
*
|
|
48586
48599
|
* 跳过条件:
|
|
@@ -48595,15 +48608,20 @@ var SessionManager = class {
|
|
|
48595
48608
|
const sessionId = file.sessionId;
|
|
48596
48609
|
if (file.aiLabelGeneratedAt || file.label || file.larkChatId) return;
|
|
48597
48610
|
if (this.titleGenPending.has(sessionId)) return;
|
|
48598
|
-
|
|
48599
|
-
|
|
48611
|
+
const controller = new AbortController();
|
|
48612
|
+
this.titleGenPending.set(sessionId, controller);
|
|
48613
|
+
void generate(file, text, controller.signal).then((title) => {
|
|
48614
|
+
if (controller.signal.aborted) return;
|
|
48615
|
+
const current = this.findOwnedSession(sessionId);
|
|
48616
|
+
if (!current || current.label || current.aiLabelGeneratedAt || current.tool !== file.tool || current.model !== file.model) return;
|
|
48600
48617
|
if (!title) return;
|
|
48601
48618
|
this.applyResolvedMeta(sessionId, { aiLabel: title });
|
|
48602
48619
|
this.deps.logger?.info("title-gen ok", { sessionId, tool: file.tool, title });
|
|
48603
48620
|
}).catch((err) => {
|
|
48621
|
+
if (controller.signal.aborted) return;
|
|
48604
48622
|
this.deps.logger?.warn("title-gen failed", { sessionId, message: err.message });
|
|
48605
48623
|
}).finally(() => {
|
|
48606
|
-
this.titleGenPending.delete(sessionId);
|
|
48624
|
+
if (this.titleGenPending.get(sessionId) === controller) this.titleGenPending.delete(sessionId);
|
|
48607
48625
|
});
|
|
48608
48626
|
}
|
|
48609
48627
|
/**
|
|
@@ -48842,6 +48860,8 @@ var SessionManager = class {
|
|
|
48842
48860
|
}
|
|
48843
48861
|
newSession(args) {
|
|
48844
48862
|
const existingFile = this.getFile(args.sessionId);
|
|
48863
|
+
this.titleGenPending.get(args.sessionId)?.abort();
|
|
48864
|
+
this.titleGenPending.delete(args.sessionId);
|
|
48845
48865
|
const nextToolSessionId = this.deps.mode === "tui" && (existingFile.tool ?? "claude") === "claude" ? (0, import_node_crypto3.randomUUID)() : void 0;
|
|
48846
48866
|
this.clearPendingTurnEnd(args.sessionId);
|
|
48847
48867
|
const runner = this.runners.get(args.sessionId);
|
|
@@ -48862,6 +48882,8 @@ var SessionManager = class {
|
|
|
48862
48882
|
contextWindowSize: _win,
|
|
48863
48883
|
gitBranch: _branch,
|
|
48864
48884
|
resolvedModel: _model,
|
|
48885
|
+
aiLabel: _aiLabel,
|
|
48886
|
+
aiLabelGeneratedAt: _titleGeneratedAt,
|
|
48865
48887
|
...rest
|
|
48866
48888
|
} = existing;
|
|
48867
48889
|
void _drop;
|
|
@@ -48869,6 +48891,8 @@ var SessionManager = class {
|
|
|
48869
48891
|
void _win;
|
|
48870
48892
|
void _branch;
|
|
48871
48893
|
void _model;
|
|
48894
|
+
void _aiLabel;
|
|
48895
|
+
void _titleGeneratedAt;
|
|
48872
48896
|
const updated = {
|
|
48873
48897
|
...rest,
|
|
48874
48898
|
...nextToolSessionId ? { toolSessionId: nextToolSessionId } : {},
|
|
@@ -48941,6 +48965,8 @@ var SessionManager = class {
|
|
|
48941
48965
|
return { runningSessions: running };
|
|
48942
48966
|
}
|
|
48943
48967
|
stopAll() {
|
|
48968
|
+
for (const controller of this.titleGenPending.values()) controller.abort();
|
|
48969
|
+
this.titleGenPending.clear();
|
|
48944
48970
|
for (const r2 of this.runners.values()) {
|
|
48945
48971
|
r2.input({ kind: "command", command: { kind: "stop" } });
|
|
48946
48972
|
}
|
|
@@ -49117,6 +49143,8 @@ var SessionManager = class {
|
|
|
49117
49143
|
`sub-session not found: ${scopeKey(args.scope)}/${args.sessionId}`
|
|
49118
49144
|
);
|
|
49119
49145
|
}
|
|
49146
|
+
this.titleGenPending.get(args.sessionId)?.abort();
|
|
49147
|
+
this.titleGenPending.delete(args.sessionId);
|
|
49120
49148
|
const runner = this.ensureRunnerForScope(file, args.scope);
|
|
49121
49149
|
const nextToolSessionId = this.deps.mode === "tui" && (file.tool ?? "claude") === "claude" ? (0, import_node_crypto3.randomUUID)() : void 0;
|
|
49122
49150
|
const { broadcast } = this.withCollector(() => {
|
|
@@ -64362,6 +64390,7 @@ var CloudGatewayClient = class {
|
|
|
64362
64390
|
personaId: personaId2,
|
|
64363
64391
|
...opts.toolSessionId ? { engineSessionId: opts.toolSessionId } : {},
|
|
64364
64392
|
...opts.instructions ? { instructions: opts.instructions } : {},
|
|
64393
|
+
...opts.purpose ? { purpose: opts.purpose } : {},
|
|
64365
64394
|
logger: this.deps.logger
|
|
64366
64395
|
});
|
|
64367
64396
|
}
|
|
@@ -64428,7 +64457,7 @@ function parseControlLine(line) {
|
|
|
64428
64457
|
}
|
|
64429
64458
|
}
|
|
64430
64459
|
function openHttpLineStream(opts) {
|
|
64431
|
-
const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, engineSessionId, instructions, logger } = opts;
|
|
64460
|
+
const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, engineSessionId, instructions, purpose, logger } = opts;
|
|
64432
64461
|
const headers = { authorization: `Bearer ${apiKey}`, "content-type": "application/json" };
|
|
64433
64462
|
const ac = new AbortController();
|
|
64434
64463
|
const lineCbs = [];
|
|
@@ -64496,7 +64525,7 @@ function openHttpLineStream(opts) {
|
|
|
64496
64525
|
res = await fetchImpl(gatewayUrl + GATEWAY_ROUTES.session(personaId2), {
|
|
64497
64526
|
method: "POST",
|
|
64498
64527
|
headers,
|
|
64499
|
-
body: JSON.stringify({ ...engineSessionId ? { engineSessionId } : {}, ...instructions ? { instructions } : {} }),
|
|
64528
|
+
body: JSON.stringify({ ...engineSessionId ? { engineSessionId } : {}, ...instructions ? { instructions } : {}, ...purpose ? { purpose } : {} }),
|
|
64500
64529
|
signal: ac.signal
|
|
64501
64530
|
});
|
|
64502
64531
|
} catch (e) {
|
|
@@ -64613,8 +64642,8 @@ init_protocol();
|
|
|
64613
64642
|
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
64614
64643
|
function cloudThreadParams(ctx, paths) {
|
|
64615
64644
|
const { model: _model, ...base } = threadStartParams(ctx);
|
|
64616
|
-
const developerInstructions = [ctx.extraSystemPrompt, workDirPrompt(paths.workDir, ctx.personaMode ?? "owner")].filter((x2) => Boolean(x2)).join("\n\n");
|
|
64617
|
-
return { ...base, cwd: paths.personaDir, approvalPolicy: "never", sandbox: "danger-full-access", developerInstructions };
|
|
64645
|
+
const developerInstructions = ctx.titleOnly ? "\u53EA\u6839\u636E\u7528\u6237\u6D88\u606F\u8FD4\u56DE\u7B80\u77ED\u6807\u9898\u3002\u4E0D\u8981\u8C03\u7528\u5DE5\u5177\u3001\u8BFB\u53D6\u6587\u4EF6\u3001\u8BBF\u95EE\u7F51\u7EDC\u6216\u4FEE\u6539\u4EFB\u4F55\u5185\u5BB9\u3002" : [ctx.extraSystemPrompt, workDirPrompt(paths.workDir, ctx.personaMode ?? "owner")].filter((x2) => Boolean(x2)).join("\n\n");
|
|
64646
|
+
return { ...base, cwd: paths.personaDir, approvalPolicy: "never", sandbox: ctx.titleOnly ? "read-only" : "danger-full-access", developerInstructions };
|
|
64618
64647
|
}
|
|
64619
64648
|
function deferredLineStream() {
|
|
64620
64649
|
let target = null;
|
|
@@ -64701,7 +64730,9 @@ function createCloudCodexSession(ctx, sink, deps) {
|
|
|
64701
64730
|
// 云 persona 运行看板(design 2026-09-23-cloud-persona-metrics §3.7):提问那一行带「一轮开始」头,轮末镜像顺带报这一轮的结果
|
|
64702
64731
|
onTurnStarting: () => channel?.markNextLineTurnStart(),
|
|
64703
64732
|
// 轮末镜像带上这一轮的结果与首字节(design 2026-09-23-cloud-persona-metrics §3.7)
|
|
64704
|
-
onTurnCompleted: (outcome, afterFirstByteMs) =>
|
|
64733
|
+
onTurnCompleted: (outcome, afterFirstByteMs) => {
|
|
64734
|
+
if (!ctx.titleOnly) void channel?.mirror({ outcome, ...afterFirstByteMs !== void 0 ? { afterFirstByteMs } : {} });
|
|
64735
|
+
},
|
|
64705
64736
|
now: deps.now
|
|
64706
64737
|
});
|
|
64707
64738
|
if (!personaId2) {
|
|
@@ -64711,7 +64742,7 @@ function createCloudCodexSession(ctx, sink, deps) {
|
|
|
64711
64742
|
});
|
|
64712
64743
|
return driver.session;
|
|
64713
64744
|
}
|
|
64714
|
-
void deps.client.openSession(personaId2).then(
|
|
64745
|
+
void (ctx.titleOnly ? deps.client.openSession(personaId2, { purpose: "title" }) : deps.client.openSession(personaId2)).then(
|
|
64715
64746
|
(opened) => {
|
|
64716
64747
|
channel = opened;
|
|
64717
64748
|
channel.onControl((c2) => {
|
|
@@ -65431,7 +65462,9 @@ function createCloudPiSession(ctx, sink, deps) {
|
|
|
65431
65462
|
// 云 persona 运行看板(design 2026-09-23-cloud-persona-metrics §3.7):提问那一行带「一轮开始」头,轮末镜像顺带报这一轮的结果
|
|
65432
65463
|
onTurnStarting: () => channel?.markNextLineTurnStart(),
|
|
65433
65464
|
// 轮末镜像带上这一轮的结果与首字节(design 2026-09-23-cloud-persona-metrics §3.7)
|
|
65434
|
-
onTurnCompleted: (outcome, afterFirstByteMs) =>
|
|
65465
|
+
onTurnCompleted: (outcome, afterFirstByteMs) => {
|
|
65466
|
+
if (!ctx.titleOnly) void channel?.mirror({ outcome, ...afterFirstByteMs !== void 0 ? { afterFirstByteMs } : {} });
|
|
65467
|
+
},
|
|
65435
65468
|
now: deps.now
|
|
65436
65469
|
});
|
|
65437
65470
|
if (!personaId2) {
|
|
@@ -65441,7 +65474,7 @@ function createCloudPiSession(ctx, sink, deps) {
|
|
|
65441
65474
|
});
|
|
65442
65475
|
return driver.session;
|
|
65443
65476
|
}
|
|
65444
|
-
void deps.client.openSession(personaId2, { toolSessionId: sessionId, instructions: cloudPiInstructions(ctx) }).then(
|
|
65477
|
+
void deps.client.openSession(personaId2, { toolSessionId: sessionId, instructions: ctx.titleOnly ? "" : cloudPiInstructions(ctx), ...ctx.titleOnly ? { purpose: "title" } : {} }).then(
|
|
65445
65478
|
(opened) => {
|
|
65446
65479
|
channel = opened;
|
|
65447
65480
|
channel.onControl((c2) => {
|
|
@@ -66313,10 +66346,6 @@ var import_node_fs45 = __toESM(require("fs"), 1);
|
|
|
66313
66346
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
66314
66347
|
var import_node_path49 = __toESM(require("path"), 1);
|
|
66315
66348
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
66316
|
-
var TITLE_MODEL_BY_TOOL = {
|
|
66317
|
-
claude: "haiku",
|
|
66318
|
-
codex: "gpt-5.4-mini"
|
|
66319
|
-
};
|
|
66320
66349
|
var TITLE_INPUT_MAX_CHARS = 400;
|
|
66321
66350
|
var DEFAULT_TITLE_GEN_TIMEOUT_MS = 45e3;
|
|
66322
66351
|
var outFileSeq = 0;
|
|
@@ -66337,8 +66366,8 @@ function sanitizeTitle(raw) {
|
|
|
66337
66366
|
if (!stripped) return null;
|
|
66338
66367
|
return stripped.slice(0, 60);
|
|
66339
66368
|
}
|
|
66340
|
-
function buildClaudeTitleArgs(prompt) {
|
|
66341
|
-
return ["-p", "--model",
|
|
66369
|
+
function buildClaudeTitleArgs(prompt, model) {
|
|
66370
|
+
return ["-p", "--no-session-persistence", "--tools", "", ...model ? ["--model", model] : [], prompt];
|
|
66342
66371
|
}
|
|
66343
66372
|
var CODEX_TITLE_SCHEMA = JSON.stringify({
|
|
66344
66373
|
type: "object",
|
|
@@ -66358,7 +66387,7 @@ function parseTitleJson(raw) {
|
|
|
66358
66387
|
}
|
|
66359
66388
|
return sanitizeTitle(text);
|
|
66360
66389
|
}
|
|
66361
|
-
function buildCodexTitleArgs(prompt, outFile, schemaFile) {
|
|
66390
|
+
function buildCodexTitleArgs(prompt, outFile, schemaFile, model) {
|
|
66362
66391
|
return [
|
|
66363
66392
|
"exec",
|
|
66364
66393
|
"--ephemeral",
|
|
@@ -66367,8 +66396,7 @@ function buildCodexTitleArgs(prompt, outFile, schemaFile) {
|
|
|
66367
66396
|
schemaFile,
|
|
66368
66397
|
"-s",
|
|
66369
66398
|
"read-only",
|
|
66370
|
-
"-m",
|
|
66371
|
-
TITLE_MODEL_BY_TOOL.codex,
|
|
66399
|
+
...model ? ["-m", model] : [],
|
|
66372
66400
|
"--color",
|
|
66373
66401
|
"never",
|
|
66374
66402
|
"-o",
|
|
@@ -66376,10 +66404,35 @@ function buildCodexTitleArgs(prompt, outFile, schemaFile) {
|
|
|
66376
66404
|
prompt
|
|
66377
66405
|
];
|
|
66378
66406
|
}
|
|
66379
|
-
|
|
66380
|
-
|
|
66407
|
+
function buildPiTitleArgs(prompt, model) {
|
|
66408
|
+
return [
|
|
66409
|
+
"-p",
|
|
66410
|
+
"--mode",
|
|
66411
|
+
"text",
|
|
66412
|
+
"--no-session",
|
|
66413
|
+
"--no-tools",
|
|
66414
|
+
"--no-skills",
|
|
66415
|
+
"--no-context-files",
|
|
66416
|
+
...model ? ["--model", model] : [],
|
|
66417
|
+
"--",
|
|
66418
|
+
prompt
|
|
66419
|
+
];
|
|
66420
|
+
}
|
|
66421
|
+
async function generateSessionTitle(file, firstMessage, deps = {}) {
|
|
66422
|
+
const tool = file.tool ?? "claude";
|
|
66423
|
+
if (tool !== "claude" && tool !== "pi" && tool !== "pi-cloud" && !isCodexFamily(tool)) return null;
|
|
66381
66424
|
const text = firstMessage.trim();
|
|
66382
|
-
if (!text) return null;
|
|
66425
|
+
if (!text || deps.signal?.aborted) return null;
|
|
66426
|
+
if (tool === "codex-cloud" || tool === "pi-cloud") {
|
|
66427
|
+
if (!deps.generateCloud) return null;
|
|
66428
|
+
try {
|
|
66429
|
+
const raw = await deps.generateCloud(file, buildClaudeTitlePrompt(text), deps.signal);
|
|
66430
|
+
return raw && !deps.signal?.aborted ? parseTitleJson(raw) : null;
|
|
66431
|
+
} catch (err) {
|
|
66432
|
+
deps.logger?.warn("title-gen cloud failed", { tool, message: err.message });
|
|
66433
|
+
return null;
|
|
66434
|
+
}
|
|
66435
|
+
}
|
|
66383
66436
|
let workDir;
|
|
66384
66437
|
try {
|
|
66385
66438
|
workDir = import_node_fs45.default.mkdtempSync(import_node_path49.default.join(import_node_os18.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
@@ -66394,7 +66447,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
66394
66447
|
};
|
|
66395
66448
|
const outFile = import_node_path49.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
66396
66449
|
const schemaFile = import_node_path49.default.join(workDir, "title-schema.json");
|
|
66397
|
-
if (
|
|
66450
|
+
if (tool === "codex") {
|
|
66398
66451
|
try {
|
|
66399
66452
|
import_node_fs45.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
66400
66453
|
} catch {
|
|
@@ -66402,14 +66455,16 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
66402
66455
|
return null;
|
|
66403
66456
|
}
|
|
66404
66457
|
}
|
|
66405
|
-
const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : process.env.CODEX_BIN ?? "codex";
|
|
66406
|
-
const
|
|
66458
|
+
const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : tool === "pi" ? process.env.PI_BIN ?? "pi" : process.env.CODEX_BIN ?? "codex";
|
|
66459
|
+
const chosenModel = file.resolvedModel || file.model;
|
|
66460
|
+
const model = tool === "codex" ? sanitizeCodexModel(chosenModel) : chosenModel;
|
|
66461
|
+
const args = tool === "claude" ? buildClaudeTitleArgs(buildClaudeTitlePrompt(text), model) : tool === "pi" ? buildPiTitleArgs(buildClaudeTitlePrompt(text), model) : buildCodexTitleArgs(buildTitlePrompt(text), outFile, schemaFile, model);
|
|
66407
66462
|
const doSpawn = deps.spawnOverride ?? ((c2, a2, o2) => (0, import_node_child_process13.spawn)(c2, a2, { ...o2, stdio: ["ignore", "pipe", "pipe"] }));
|
|
66408
66463
|
const timeoutMs = deps.timeoutMs ?? DEFAULT_TITLE_GEN_TIMEOUT_MS;
|
|
66409
66464
|
return await new Promise((resolve9) => {
|
|
66410
66465
|
let proc;
|
|
66411
66466
|
try {
|
|
66412
|
-
proc = doSpawn(cmd, args, { cwd: workDir });
|
|
66467
|
+
proc = doSpawn(cmd, args, { cwd: model ? workDir : file.cwd });
|
|
66413
66468
|
} catch (err) {
|
|
66414
66469
|
deps.logger?.warn("title-gen spawn failed", { tool, message: err.message });
|
|
66415
66470
|
cleanupWorkDir();
|
|
@@ -66421,10 +66476,13 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
66421
66476
|
if (settled) return;
|
|
66422
66477
|
settled = true;
|
|
66423
66478
|
clearTimeout(timer);
|
|
66479
|
+
deps.signal?.removeEventListener("abort", onAbort);
|
|
66424
66480
|
if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGKILL");
|
|
66425
66481
|
cleanupWorkDir();
|
|
66426
66482
|
resolve9(title);
|
|
66427
66483
|
};
|
|
66484
|
+
const onAbort = () => finish(null);
|
|
66485
|
+
deps.signal?.addEventListener("abort", onAbort, { once: true });
|
|
66428
66486
|
const timer = setTimeout(() => {
|
|
66429
66487
|
deps.logger?.warn("title-gen timed out", { tool, timeoutMs });
|
|
66430
66488
|
finish(null);
|
|
@@ -66443,7 +66501,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
66443
66501
|
deps.logger?.warn("title-gen exited non-zero", { tool, code });
|
|
66444
66502
|
return finish(null);
|
|
66445
66503
|
}
|
|
66446
|
-
if (tool === "claude") return finish(parseTitleJson(stdout));
|
|
66504
|
+
if (tool === "claude" || tool === "pi") return finish(parseTitleJson(stdout));
|
|
66447
66505
|
let fileText = "";
|
|
66448
66506
|
try {
|
|
66449
66507
|
fileText = import_node_fs45.default.readFileSync(outFile, "utf8");
|
|
@@ -66455,6 +66513,57 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
66455
66513
|
});
|
|
66456
66514
|
}
|
|
66457
66515
|
|
|
66516
|
+
// src/tools/cloud-title.ts
|
|
66517
|
+
function generateCloudTitle(file, prompt, signal, getAdapter2, timeoutMs = 45e3) {
|
|
66518
|
+
if (signal?.aborted) return Promise.resolve(null);
|
|
66519
|
+
return new Promise((resolve9) => {
|
|
66520
|
+
let agent;
|
|
66521
|
+
let settled = false;
|
|
66522
|
+
let finalText = "";
|
|
66523
|
+
let partialText = "";
|
|
66524
|
+
let failed = false;
|
|
66525
|
+
const finish = (raw) => {
|
|
66526
|
+
if (settled) return;
|
|
66527
|
+
settled = true;
|
|
66528
|
+
clearTimeout(timer);
|
|
66529
|
+
signal?.removeEventListener("abort", onAbort);
|
|
66530
|
+
try {
|
|
66531
|
+
void Promise.resolve(agent?.stop("SIGKILL")).catch(() => {
|
|
66532
|
+
});
|
|
66533
|
+
} catch {
|
|
66534
|
+
}
|
|
66535
|
+
resolve9(raw);
|
|
66536
|
+
};
|
|
66537
|
+
const onAbort = () => finish(null);
|
|
66538
|
+
const timer = setTimeout(() => finish(null), timeoutMs);
|
|
66539
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
66540
|
+
try {
|
|
66541
|
+
const adapter = getAdapter2(file.tool);
|
|
66542
|
+
if (!adapter.createSession) return finish(null);
|
|
66543
|
+
agent = adapter.createSession({ cwd: file.cwd, env: {}, titleOnly: true }, {
|
|
66544
|
+
pushEvents(events) {
|
|
66545
|
+
for (const event of events) {
|
|
66546
|
+
if (event.kind === "text") {
|
|
66547
|
+
if (event.partialId) partialText += event.text;
|
|
66548
|
+
else finalText = event.text;
|
|
66549
|
+
} else if (event.kind === "error" || event.kind === "tool_call" || event.kind === "permission_request") {
|
|
66550
|
+
failed = true;
|
|
66551
|
+
finish(null);
|
|
66552
|
+
} else if (event.kind === "turn_end") {
|
|
66553
|
+
finish(failed ? null : finalText || partialText || null);
|
|
66554
|
+
}
|
|
66555
|
+
}
|
|
66556
|
+
},
|
|
66557
|
+
onExit: () => finish(null),
|
|
66558
|
+
onError: () => finish(null)
|
|
66559
|
+
});
|
|
66560
|
+
agent.startTurn(prompt);
|
|
66561
|
+
} catch {
|
|
66562
|
+
finish(null);
|
|
66563
|
+
}
|
|
66564
|
+
});
|
|
66565
|
+
}
|
|
66566
|
+
|
|
66458
66567
|
// ../node_modules/.pnpm/ws@8.20.0/node_modules/ws/wrapper.mjs
|
|
66459
66568
|
var import_stream = __toESM(require_stream(), 1);
|
|
66460
66569
|
var import_extension2 = __toESM(require_extension(), 1);
|
|
@@ -72959,7 +73068,7 @@ function computeMethodAccess(args) {
|
|
|
72959
73068
|
}
|
|
72960
73069
|
|
|
72961
73070
|
// src/version.ts
|
|
72962
|
-
var version = "0.2.
|
|
73071
|
+
var version = "0.2.600".length > 0 ? "0.2.600" : "dev";
|
|
72963
73072
|
|
|
72964
73073
|
// src/cli-probe/probe.ts
|
|
72965
73074
|
var fs83 = __toESM(require("fs"), 1);
|
|
@@ -75912,9 +76021,13 @@ async function startDaemon(config) {
|
|
|
75912
76021
|
// per-persona 凭据注入(M1b Step 5):runner 在解释 spawn effect 时按 ctx.personaId 调,
|
|
75913
76022
|
// 产出拼进 ctx.mcpConfigs。**不在 reducer 里**——渲染要读写 fs,那边是纯函数。
|
|
75914
76023
|
resolvePersonaMcpConfig,
|
|
75915
|
-
// 会话标题自产(首条 send 并行 fire
|
|
76024
|
+
// 会话标题自产(首条 send 并行 fire,沿用会话引擎和模型)。
|
|
75916
76025
|
// 不注入 = 功能关(manager 测试默认关闭防烧真调用),这里是唯一的生产装配点。
|
|
75917
|
-
generateTitle: (
|
|
76026
|
+
generateTitle: (file, firstMessage, signal) => generateSessionTitle(file, firstMessage, {
|
|
76027
|
+
logger,
|
|
76028
|
+
signal,
|
|
76029
|
+
generateCloud: (titleFile, prompt, titleSignal) => generateCloudTitle(titleFile, prompt, titleSignal, getAdapter)
|
|
76030
|
+
}),
|
|
75918
76031
|
broadcastFrame: (frame, target) => {
|
|
75919
76032
|
if (target === "all") {
|
|
75920
76033
|
transport?.broadcastAll(frame);
|