@clawos-dev/clawd 0.2.224 → 0.2.226
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 +164 -19
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/guest-Bd7xlmHv.js +557 -0
- package/dist/share-ui/assets/guest-CZnc3fAe.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-BER5fZM8.js +0 -557
- package/dist/share-ui/assets/guest-KbSE5PDA.css +0 -32
package/dist/cli.cjs
CHANGED
|
@@ -11379,6 +11379,45 @@ function hashDirToCwd(hash) {
|
|
|
11379
11379
|
const body = hash.startsWith("-") ? hash.slice(1) : hash;
|
|
11380
11380
|
return "/" + body.replace(/-/g, "/");
|
|
11381
11381
|
}
|
|
11382
|
+
function findTranscriptByToolSessionId(projectsRoot, toolSessionId) {
|
|
11383
|
+
let entries;
|
|
11384
|
+
try {
|
|
11385
|
+
entries = import_node_fs5.default.readdirSync(projectsRoot, { withFileTypes: true });
|
|
11386
|
+
} catch {
|
|
11387
|
+
return null;
|
|
11388
|
+
}
|
|
11389
|
+
let best = null;
|
|
11390
|
+
for (const ent of entries) {
|
|
11391
|
+
if (!ent.isDirectory()) continue;
|
|
11392
|
+
const candidate = import_node_path5.default.join(projectsRoot, ent.name, `${toolSessionId}.jsonl`);
|
|
11393
|
+
try {
|
|
11394
|
+
const st = import_node_fs5.default.statSync(candidate);
|
|
11395
|
+
if (!best || st.mtimeMs > best.mtime) best = { p: candidate, mtime: st.mtimeMs };
|
|
11396
|
+
} catch {
|
|
11397
|
+
}
|
|
11398
|
+
}
|
|
11399
|
+
return best?.p ?? null;
|
|
11400
|
+
}
|
|
11401
|
+
function deriveCwdFromTranscript(filePath) {
|
|
11402
|
+
const dirName = import_node_path5.default.basename(import_node_path5.default.dirname(filePath));
|
|
11403
|
+
let raw;
|
|
11404
|
+
try {
|
|
11405
|
+
raw = import_node_fs5.default.readFileSync(filePath, "utf8");
|
|
11406
|
+
} catch {
|
|
11407
|
+
return null;
|
|
11408
|
+
}
|
|
11409
|
+
let hit = null;
|
|
11410
|
+
for (const line of raw.split("\n")) {
|
|
11411
|
+
const t = line.trim();
|
|
11412
|
+
if (!t) continue;
|
|
11413
|
+
try {
|
|
11414
|
+
const o = JSON.parse(t);
|
|
11415
|
+
if (typeof o.cwd === "string" && cwdToHashDir(o.cwd) === dirName) hit = o.cwd;
|
|
11416
|
+
} catch {
|
|
11417
|
+
}
|
|
11418
|
+
}
|
|
11419
|
+
return hit;
|
|
11420
|
+
}
|
|
11382
11421
|
function safeStatMtime(p2) {
|
|
11383
11422
|
try {
|
|
11384
11423
|
return import_node_fs5.default.statSync(p2).mtimeMs;
|
|
@@ -41880,7 +41919,7 @@ var CONTACT_SSH_SYSTEM_PROMPT_HINT = `## \u8DE8\u8BBE\u5907\u6587\u4EF6\u8BBF\u9
|
|
|
41880
41919
|
|
|
41881
41920
|
**\u6CE8\u610F**\uFF1A
|
|
41882
41921
|
- \u6388\u6743\u76EE\u5F55\u6570\u636E\u6E90\u5B9E\u65F6\uFF08jail \u6BCF\u6B21\u8BFB A \u4FA7\u6700\u65B0\u914D\u7F6E\uFF09\uFF0CA \u6539\u4E86\u6388\u6743\u540E\u4F60\u4E0B\u4E00\u6B21\u62E8\u53F7\u7ACB\u5373\u611F\u77E5
|
|
41883
|
-
- \u6392\u969C\uFF1A\u672C\u673A debug \u65E5\u5FD7\u5728 \`~/.clawd/contact-ssh.log\`\uFF08\u7528\u6237\u53EF \`tail -f\` \u770B\u6BCF\u4E00\u6B65\uFF09\uFF0C\u4F60\u51FA\u9519\u65F6\u544A\u8BC9\u7528\u6237\u67E5\u8FD9\u4E2A\u6587\u4EF6
|
|
41922
|
+
- \u6392\u969C\uFF1A\u672C\u673A debug \u65E5\u5FD7\u5728 \`~/.clawd/log/contact-ssh.log\`\uFF08\u7528\u6237\u53EF \`tail -f\` \u770B\u6BCF\u4E00\u6B65\uFF09\uFF0C\u4F60\u51FA\u9519\u65F6\u544A\u8BC9\u7528\u6237\u67E5\u8FD9\u4E2A\u6587\u4EF6
|
|
41884
41923
|
- \u5982\u679C \`ls ~/.clawd/contact-ssh-keys/\` \u4E3A\u7A7A\uFF0C\u8BF4\u660E\u8FD8\u6CA1\u6709\u5BF9\u7AEF\u6388\u6743\u4F60\u6216 key \u8FD8\u6CA1\u62C9\u5230\uFF08B \u4FA7 daemon \u6BCF 60s \u4E00\u6B21\u81EA\u52A8\u62C9\uFF09\uFF0C\u5982\u5B9E\u544A\u8BC9\u7528\u6237
|
|
41885
41924
|
`;
|
|
41886
41925
|
|
|
@@ -42357,6 +42396,13 @@ function applyCommand(state, command, deps) {
|
|
|
42357
42396
|
}
|
|
42358
42397
|
return { state: next, effects };
|
|
42359
42398
|
}
|
|
42399
|
+
case "sync-cwd": {
|
|
42400
|
+
if (next.file.cwd === command.cwd) return { state: next, effects };
|
|
42401
|
+
next.file = { ...next.file, cwd: command.cwd, updatedAt: nowIso(deps) };
|
|
42402
|
+
effects.push({ kind: "persist-file", file: next.file });
|
|
42403
|
+
effects.push(sessionInfoFrame(next.file));
|
|
42404
|
+
return { state: next, effects };
|
|
42405
|
+
}
|
|
42360
42406
|
case "resume": {
|
|
42361
42407
|
const sameToolSession = next.file.toolSessionId === command.toolSessionId;
|
|
42362
42408
|
const nextFile = {
|
|
@@ -43955,6 +44001,23 @@ var SessionManager = class {
|
|
|
43955
44001
|
this.writeOwned(updated);
|
|
43956
44002
|
return { response: updated, broadcast: [] };
|
|
43957
44003
|
}
|
|
44004
|
+
/**
|
|
44005
|
+
* [T-17] observer 检测到 CC 挪走 transcript(cwd 中途变化)后的 cwd 校正入口。
|
|
44006
|
+
* 不进 withCollector:observer 回调没有 in-flight RPC,session:info 帧走
|
|
44007
|
+
* routeFromRunner 的异步 broadcast 路径。有 runner 走 reducer sync-cwd(无 kill,
|
|
44008
|
+
* 区别于 update 的 RUNTIME_PATCH_KEYS 重启语义);无 runner 直写 store。
|
|
44009
|
+
* 幂等:reducer 同值 noop;session 不存在静默返回(observer 生命周期与 store 解耦)。
|
|
44010
|
+
*/
|
|
44011
|
+
syncSessionCwd(sessionId, cwd) {
|
|
44012
|
+
const runner = this.runners.get(sessionId);
|
|
44013
|
+
if (runner) {
|
|
44014
|
+
runner.input({ kind: "command", command: { kind: "sync-cwd", cwd } });
|
|
44015
|
+
return;
|
|
44016
|
+
}
|
|
44017
|
+
const existing = this.findOwnedSession(sessionId);
|
|
44018
|
+
if (!existing || existing.cwd === cwd) return;
|
|
44019
|
+
this.writeOwned({ ...existing, cwd, updatedAt: nowIso2(this.deps) });
|
|
44020
|
+
}
|
|
43958
44021
|
/**
|
|
43959
44022
|
* 启动清扫:删除所有磁盘残留的 ephemeral(快速问答临时)session。
|
|
43960
44023
|
* 客户端崩溃 / 没关抽屉会留下永久不可见的孤儿(ephemeral 被 sidebar 过滤,用户自己也删不掉)。
|
|
@@ -49640,14 +49703,19 @@ var SessionObserver = class {
|
|
|
49640
49703
|
lastSize: size,
|
|
49641
49704
|
buf: "",
|
|
49642
49705
|
adapter: args.adapter,
|
|
49643
|
-
prevIsRejectSentinel: false
|
|
49706
|
+
prevIsRejectSentinel: false,
|
|
49707
|
+
toolSessionId: args.toolSessionId,
|
|
49708
|
+
sawFile: import_node_fs25.default.existsSync(filePath),
|
|
49709
|
+
lastRelocateScanMs: 0,
|
|
49710
|
+
pendingCwdDerive: false,
|
|
49711
|
+
lastDeriveMs: 0
|
|
49644
49712
|
};
|
|
49645
49713
|
try {
|
|
49646
49714
|
import_node_fs25.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
|
|
49647
49715
|
} catch {
|
|
49648
49716
|
}
|
|
49649
49717
|
w2.watcher = import_node_fs25.default.watch(import_node_path24.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
49650
|
-
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
49718
|
+
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
49651
49719
|
this.poll(w2);
|
|
49652
49720
|
});
|
|
49653
49721
|
w2.pollTimer = setInterval(() => this.poll(w2), 200);
|
|
@@ -49695,8 +49763,10 @@ var SessionObserver = class {
|
|
|
49695
49763
|
try {
|
|
49696
49764
|
size = import_node_fs25.default.statSync(w2.filePath).size;
|
|
49697
49765
|
} catch {
|
|
49766
|
+
if (w2.sawFile) this.maybeRelocate(w2);
|
|
49698
49767
|
return;
|
|
49699
49768
|
}
|
|
49769
|
+
w2.sawFile = true;
|
|
49700
49770
|
if (size < w2.lastSize) {
|
|
49701
49771
|
w2.lastSize = 0;
|
|
49702
49772
|
w2.buf = "";
|
|
@@ -49731,6 +49801,57 @@ var SessionObserver = class {
|
|
|
49731
49801
|
} finally {
|
|
49732
49802
|
import_node_fs25.default.closeSync(fd);
|
|
49733
49803
|
}
|
|
49804
|
+
if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
|
|
49805
|
+
}
|
|
49806
|
+
// [T-17] 文件消失后的兜底重定位:按 tsid 全局扫描 → 切 watcher → lastSize/buf 保留接续读
|
|
49807
|
+
// (CC 是 move,内容前缀不变,不重复喂;异常变小走 poll 的截断重建分支,上游 uuid dedup 兜底)。
|
|
49808
|
+
// 检测点唯一(poll ENOENT),fs.watch rename 事件也 funnel 到 poll,天然幂等;scan 加 1s
|
|
49809
|
+
// rate-limit 防 ENOENT 持续期(如 cleanupPeriodDays 真删除)反复 readdir 空转。
|
|
49810
|
+
maybeRelocate(w2) {
|
|
49811
|
+
const now = Date.now();
|
|
49812
|
+
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
49813
|
+
w2.lastRelocateScanMs = now;
|
|
49814
|
+
const projectsRoot = import_node_path24.default.join(this.home, ".claude", "projects");
|
|
49815
|
+
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
49816
|
+
if (!found || found === w2.filePath) return;
|
|
49817
|
+
try {
|
|
49818
|
+
w2.watcher?.close();
|
|
49819
|
+
} catch {
|
|
49820
|
+
}
|
|
49821
|
+
w2.filePath = found;
|
|
49822
|
+
try {
|
|
49823
|
+
w2.watcher = import_node_fs25.default.watch(import_node_path24.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
49824
|
+
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
49825
|
+
this.poll(w2);
|
|
49826
|
+
});
|
|
49827
|
+
} catch {
|
|
49828
|
+
w2.watcher = null;
|
|
49829
|
+
}
|
|
49830
|
+
const cwd = deriveCwdFromTranscript(found);
|
|
49831
|
+
if (cwd) {
|
|
49832
|
+
this.applyDerivedCwd(w2, cwd);
|
|
49833
|
+
} else {
|
|
49834
|
+
w2.pendingCwdDerive = true;
|
|
49835
|
+
}
|
|
49836
|
+
this.opts.onJsonlRelocated?.(w2.sessionId, { filePath: found, cwd });
|
|
49837
|
+
this.poll(w2);
|
|
49838
|
+
}
|
|
49839
|
+
maybeDeriveCwd(w2) {
|
|
49840
|
+
const now = Date.now();
|
|
49841
|
+
if (now - w2.lastDeriveMs < 500) return;
|
|
49842
|
+
w2.lastDeriveMs = now;
|
|
49843
|
+
const cwd = deriveCwdFromTranscript(w2.filePath);
|
|
49844
|
+
if (!cwd) return;
|
|
49845
|
+
w2.pendingCwdDerive = false;
|
|
49846
|
+
this.applyDerivedCwd(w2, cwd);
|
|
49847
|
+
this.opts.onJsonlRelocated?.(w2.sessionId, { filePath: w2.filePath, cwd });
|
|
49848
|
+
}
|
|
49849
|
+
applyDerivedCwd(w2, cwd) {
|
|
49850
|
+
this.metaObserver?.start({
|
|
49851
|
+
sessionId: w2.sessionId,
|
|
49852
|
+
cwd,
|
|
49853
|
+
toolSessionId: w2.toolSessionId
|
|
49854
|
+
});
|
|
49734
49855
|
}
|
|
49735
49856
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
49736
49857
|
// 且 content 含 text part)时,抽出 real uuid + 第一段 text + timestamp 上报。
|
|
@@ -53069,7 +53190,9 @@ var TunnelManager = class {
|
|
|
53069
53190
|
const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
|
|
53070
53191
|
stdio: ["ignore", "pipe", "pipe"]
|
|
53071
53192
|
});
|
|
53072
|
-
const
|
|
53193
|
+
const logDir = import_node_path35.default.join(this.deps.dataDir, "log");
|
|
53194
|
+
import_node_fs34.default.mkdirSync(logDir, { recursive: true });
|
|
53195
|
+
const logFilePath = import_node_path35.default.join(logDir, "frpc.log");
|
|
53073
53196
|
const logStream = import_node_fs34.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
53074
53197
|
logStream.on("error", () => {
|
|
53075
53198
|
});
|
|
@@ -53310,8 +53433,11 @@ var CLAWD_SSH_JAIL_SCRIPT = String.raw`#!/usr/bin/env bash
|
|
|
53310
53433
|
|
|
53311
53434
|
set -euo pipefail
|
|
53312
53435
|
|
|
53313
|
-
# 用户可读审计日志:追加到 ~/.clawd/contact-ssh.log(跟 daemon TS 侧 contact-ssh-log.ts 共写)
|
|
53314
|
-
|
|
53436
|
+
# 用户可读审计日志:追加到 ~/.clawd/log/contact-ssh.log(跟 daemon TS 侧 contact-ssh-log.ts 共写)
|
|
53437
|
+
# bash 侧写死 ~/.clawd/log/,因为 jail 脚本在 authorized_keys command= 里被 sshd 起,
|
|
53438
|
+
# 拿不到 daemon --data-dir 覆盖。dev daemon 用 --data-dir=/tmp/x 时 jail 仍写 ~/.clawd/log/,
|
|
53439
|
+
# 跟改动前 (~/.clawd/contact-ssh.log) 一样的分歧行为,不做统一。
|
|
53440
|
+
CONTACT_SSH_LOG="${"${HOME}"}/.clawd/log/contact-ssh.log"
|
|
53315
53441
|
log_line() {
|
|
53316
53442
|
# 参数: level tag msg
|
|
53317
53443
|
local ts
|
|
@@ -53508,7 +53634,9 @@ var SshdManager = class {
|
|
|
53508
53634
|
const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(sshdBin, ["-D", "-e", "-f", configPath], {
|
|
53509
53635
|
stdio: ["ignore", "pipe", "pipe"]
|
|
53510
53636
|
});
|
|
53511
|
-
const
|
|
53637
|
+
const sshdLogDir = import_node_path39.default.join(this.deps.dataDir, "log");
|
|
53638
|
+
import_node_fs38.default.mkdirSync(sshdLogDir, { recursive: true });
|
|
53639
|
+
const logStream = import_node_fs38.default.createWriteStream(import_node_path39.default.join(sshdLogDir, "sshd.log"), {
|
|
53512
53640
|
flags: "a",
|
|
53513
53641
|
mode: 384
|
|
53514
53642
|
});
|
|
@@ -53689,7 +53817,7 @@ var import_node_path42 = __toESM(require("path"), 1);
|
|
|
53689
53817
|
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
53690
53818
|
var import_node_path41 = __toESM(require("path"), 1);
|
|
53691
53819
|
function createContactSshLog(dataDir) {
|
|
53692
|
-
const file = import_node_path41.default.join(dataDir, "contact-ssh.log");
|
|
53820
|
+
const file = import_node_path41.default.join(dataDir, "log", "contact-ssh.log");
|
|
53693
53821
|
function append(level, tag, message, meta) {
|
|
53694
53822
|
const time = (/* @__PURE__ */ new Date()).toISOString();
|
|
53695
53823
|
let line = `[${time}] [${level}] [${tag}] ${message}`;
|
|
@@ -54681,10 +54809,18 @@ function readJsonlEntries(file) {
|
|
|
54681
54809
|
}
|
|
54682
54810
|
function forkSession(input) {
|
|
54683
54811
|
const baseDir = input.baseDir ?? import_node_path47.default.join(import_node_os16.default.homedir(), ".claude");
|
|
54684
|
-
|
|
54685
|
-
|
|
54812
|
+
let projectDir = import_node_path47.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
54813
|
+
let sourceFile = import_node_path47.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
54686
54814
|
if (!import_node_fs45.default.existsSync(sourceFile)) {
|
|
54687
|
-
|
|
54815
|
+
const found = findTranscriptByToolSessionId(
|
|
54816
|
+
import_node_path47.default.join(baseDir, "projects"),
|
|
54817
|
+
input.toolSessionId
|
|
54818
|
+
);
|
|
54819
|
+
if (!found) {
|
|
54820
|
+
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
54821
|
+
}
|
|
54822
|
+
sourceFile = found;
|
|
54823
|
+
projectDir = import_node_path47.default.dirname(found);
|
|
54688
54824
|
}
|
|
54689
54825
|
const entries = readJsonlEntries(sourceFile);
|
|
54690
54826
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -59292,18 +59428,20 @@ async function startDaemon(config) {
|
|
|
59292
59428
|
sampling: logShippingCfg.sampling,
|
|
59293
59429
|
homeDir: import_node_os21.default.homedir()
|
|
59294
59430
|
});
|
|
59431
|
+
const logDir = import_node_path64.default.join(config.dataDir, "log");
|
|
59432
|
+
import_node_fs51.default.mkdirSync(logDir, { recursive: true });
|
|
59295
59433
|
const logger = createLogger({
|
|
59296
59434
|
level: config.logLevel,
|
|
59297
|
-
file: import_node_path64.default.join(
|
|
59435
|
+
file: import_node_path64.default.join(logDir, "clawd.log"),
|
|
59298
59436
|
logClient
|
|
59299
59437
|
});
|
|
59300
59438
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
59301
59439
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
59302
|
-
file: import_node_path64.default.join(
|
|
59440
|
+
file: import_node_path64.default.join(logDir, "screen-idle-probe.log"),
|
|
59303
59441
|
level: "debug"
|
|
59304
59442
|
});
|
|
59305
59443
|
logger.info("screen-idle probe logger enabled", {
|
|
59306
|
-
file: import_node_path64.default.join(
|
|
59444
|
+
file: import_node_path64.default.join(logDir, "screen-idle-probe.log")
|
|
59307
59445
|
});
|
|
59308
59446
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
59309
59447
|
const pre = stateMgr.preflight();
|
|
@@ -59474,7 +59612,7 @@ async function startDaemon(config) {
|
|
|
59474
59612
|
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
59475
59613
|
let dispatchMcpConfigPath2;
|
|
59476
59614
|
if (dispatchServerScriptPath) {
|
|
59477
|
-
const dispatchLogPath = import_node_path64.default.join(
|
|
59615
|
+
const dispatchLogPath = import_node_path64.default.join(logDir, "dispatch-mcp-server.log");
|
|
59478
59616
|
dispatchMcpConfigPath2 = writeDispatchMcpConfig({
|
|
59479
59617
|
dataDir: config.dataDir,
|
|
59480
59618
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -59497,7 +59635,7 @@ async function startDaemon(config) {
|
|
|
59497
59635
|
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
59498
59636
|
let ticketMcpConfigPath2;
|
|
59499
59637
|
if (ticketServerScriptPath) {
|
|
59500
|
-
const ticketLogPath = import_node_path64.default.join(
|
|
59638
|
+
const ticketLogPath = import_node_path64.default.join(logDir, "ticket-mcp-server.log");
|
|
59501
59639
|
ticketMcpConfigPath2 = writeTicketMcpConfig({
|
|
59502
59640
|
dataDir: config.dataDir,
|
|
59503
59641
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -59522,7 +59660,7 @@ async function startDaemon(config) {
|
|
|
59522
59660
|
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
59523
59661
|
let shiftMcpConfigPath2;
|
|
59524
59662
|
if (shiftServerScriptPath) {
|
|
59525
|
-
const shiftLogPath = import_node_path64.default.join(
|
|
59663
|
+
const shiftLogPath = import_node_path64.default.join(logDir, "shift-mcp-server.log");
|
|
59526
59664
|
shiftMcpConfigPath2 = await writeShiftMcpConfig({
|
|
59527
59665
|
dataDir: config.dataDir,
|
|
59528
59666
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -59546,7 +59684,7 @@ async function startDaemon(config) {
|
|
|
59546
59684
|
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
59547
59685
|
let inboxMcpConfigPath2;
|
|
59548
59686
|
if (inboxServerScriptPath) {
|
|
59549
|
-
const inboxLogPath = import_node_path64.default.join(
|
|
59687
|
+
const inboxLogPath = import_node_path64.default.join(logDir, "inbox-mcp-server.log");
|
|
59550
59688
|
inboxMcpConfigPath2 = await writeInboxMcpConfig({
|
|
59551
59689
|
dataDir: config.dataDir,
|
|
59552
59690
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -59686,6 +59824,13 @@ async function startDaemon(config) {
|
|
|
59686
59824
|
// daemon 内部转译,UI 看到的始终是 events 流里的 synth uuid(详见 manager 注释)
|
|
59687
59825
|
onUserMessageObserved: (sessionId, realUuid, text) => {
|
|
59688
59826
|
manager.recordRealUserUuid({ sessionId, realUuid, text });
|
|
59827
|
+
},
|
|
59828
|
+
// [T-17] CC 中途改 cwd 挪走 transcript:observer 重定位后校正 SessionFile.cwd
|
|
59829
|
+
// (persist + session:info,不 kill),fork / respawn / UI 缓存随之对齐。
|
|
59830
|
+
// cwd 可能两段式到达(挪走瞬间新 cwd 行未落盘 → 先 null 后补),回调幂等
|
|
59831
|
+
onJsonlRelocated: (sessionId, { filePath, cwd }) => {
|
|
59832
|
+
logger.info("observer jsonl relocated", { sessionId, filePath, cwd });
|
|
59833
|
+
if (cwd) manager.syncSessionCwd(sessionId, cwd);
|
|
59689
59834
|
}
|
|
59690
59835
|
});
|
|
59691
59836
|
manager.attachObserver(observer);
|
|
@@ -60351,7 +60496,7 @@ async function startDaemon(config) {
|
|
|
60351
60496
|
`Tunnel: ${r.url}`,
|
|
60352
60497
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
60353
60498
|
`Frpc config: ${import_node_path64.default.join(config.dataDir, "frpc.toml")}`,
|
|
60354
|
-
`Frpc log: ${import_node_path64.default.join(
|
|
60499
|
+
`Frpc log: ${import_node_path64.default.join(logDir, "frpc.log")}`
|
|
60355
60500
|
];
|
|
60356
60501
|
const width = Math.max(...lines.map((l) => l.length));
|
|
60357
60502
|
const bar = "\u2550".repeat(width + 4);
|