@clawos-dev/clawd 0.2.367 → 0.2.368

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.
Files changed (2) hide show
  1. package/dist/cli.cjs +1069 -1019
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -11151,7 +11151,7 @@ var require_transport = __commonJS({
11151
11151
  "use strict";
11152
11152
  var { createRequire: createRequire2 } = require("module");
11153
11153
  var getCallers = require_caller();
11154
- var { join: join17, isAbsolute: isAbsolute3, sep: sep3 } = require("path");
11154
+ var { join: join17, isAbsolute: isAbsolute3, sep: sep4 } = require("path");
11155
11155
  var sleep2 = require_atomic_sleep();
11156
11156
  var onExit = require_on_exit_leak_free();
11157
11157
  var ThreadStream = require_thread_stream();
@@ -11259,7 +11259,7 @@ var require_transport = __commonJS({
11259
11259
  let fixTarget2;
11260
11260
  for (const filePath of callers) {
11261
11261
  try {
11262
- const context = filePath === "node:repl" ? process.cwd() + sep3 : filePath;
11262
+ const context = filePath === "node:repl" ? process.cwd() + sep4 : filePath;
11263
11263
  fixTarget2 = createRequire2(context).resolve(origin);
11264
11264
  break;
11265
11265
  } catch (err) {
@@ -14638,14 +14638,14 @@ var init_claude_history = __esm({
14638
14638
  // src/tools/claude.ts
14639
14639
  function probeViaWhich() {
14640
14640
  try {
14641
- const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
14642
- if (out && import_node_fs16.default.existsSync(out)) return out;
14641
+ const out = (0, import_node_child_process4.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
14642
+ if (out && import_node_fs18.default.existsSync(out)) return out;
14643
14643
  } catch {
14644
14644
  }
14645
14645
  return null;
14646
14646
  }
14647
14647
  async function probeClaude(env = process.env) {
14648
- if (env.CLAUDE_BIN && import_node_fs16.default.existsSync(env.CLAUDE_BIN)) {
14648
+ if (env.CLAUDE_BIN && import_node_fs18.default.existsSync(env.CLAUDE_BIN)) {
14649
14649
  return { available: true, path: env.CLAUDE_BIN };
14650
14650
  }
14651
14651
  const w2 = probeViaWhich();
@@ -15114,13 +15114,13 @@ function encodeClaudeStdin(text) {
15114
15114
  };
15115
15115
  return JSON.stringify(frame) + "\n";
15116
15116
  }
15117
- var import_node_child_process, import_node_child_process2, import_node_fs16, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODEL_IDS, CLAUDE_MODELS, _assertModelIdsAligned, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
15117
+ var import_node_child_process3, import_node_child_process4, import_node_fs18, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODEL_IDS, CLAUDE_MODELS, _assertModelIdsAligned, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
15118
15118
  var init_claude = __esm({
15119
15119
  "src/tools/claude.ts"() {
15120
15120
  "use strict";
15121
- import_node_child_process = require("child_process");
15122
- import_node_child_process2 = require("child_process");
15123
- import_node_fs16 = __toESM(require("fs"), 1);
15121
+ import_node_child_process3 = require("child_process");
15122
+ import_node_child_process4 = require("child_process");
15123
+ import_node_fs18 = __toESM(require("fs"), 1);
15124
15124
  init_protocol();
15125
15125
  init_claude_history();
15126
15126
  init_tool_result_extra();
@@ -15249,7 +15249,7 @@ var init_claude = __esm({
15249
15249
  spawn(ctx) {
15250
15250
  const args = buildSpawnArgs(ctx);
15251
15251
  const cmd = process.env.CLAUDE_BIN ?? "claude";
15252
- const child = (0, import_node_child_process.spawn)(cmd, args, {
15252
+ const child = (0, import_node_child_process3.spawn)(cmd, args, {
15253
15253
  cwd: ctx.cwd,
15254
15254
  env: buildSpawnEnv(ctx.env),
15255
15255
  stdio: ["pipe", "pipe", "pipe"]
@@ -23027,7 +23027,7 @@ var require_luxon = __commonJS({
23027
23027
  }, zone || mergedZone, next];
23028
23028
  }, [{}, null, 1]).slice(0, 2);
23029
23029
  }
23030
- function parse(s2, ...patterns) {
23030
+ function parse2(s2, ...patterns) {
23031
23031
  if (s2 == null) {
23032
23032
  return [null, null];
23033
23033
  }
@@ -23170,26 +23170,26 @@ var require_luxon = __commonJS({
23170
23170
  var extractISOOrdinalDateAndTime = combineExtractors(extractISOOrdinalData, extractISOTime, extractISOOffset, extractIANAZone);
23171
23171
  var extractISOTimeAndOffset = combineExtractors(extractISOTime, extractISOOffset, extractIANAZone);
23172
23172
  function parseISODate(s2) {
23173
- return parse(s2, [isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset], [isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDateAndTime], [isoTimeCombinedRegex, extractISOTimeAndOffset]);
23173
+ return parse2(s2, [isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset], [isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDateAndTime], [isoTimeCombinedRegex, extractISOTimeAndOffset]);
23174
23174
  }
23175
23175
  function parseRFC2822Date(s2) {
23176
- return parse(preprocessRFC2822(s2), [rfc2822, extractRFC2822]);
23176
+ return parse2(preprocessRFC2822(s2), [rfc2822, extractRFC2822]);
23177
23177
  }
23178
23178
  function parseHTTPDate(s2) {
23179
- return parse(s2, [rfc1123, extractRFC1123Or850], [rfc850, extractRFC1123Or850], [ascii, extractASCII]);
23179
+ return parse2(s2, [rfc1123, extractRFC1123Or850], [rfc850, extractRFC1123Or850], [ascii, extractASCII]);
23180
23180
  }
23181
23181
  function parseISODuration(s2) {
23182
- return parse(s2, [isoDuration, extractISODuration]);
23182
+ return parse2(s2, [isoDuration, extractISODuration]);
23183
23183
  }
23184
23184
  var extractISOTimeOnly = combineExtractors(extractISOTime);
23185
23185
  function parseISOTimeOnly(s2) {
23186
- return parse(s2, [isoTimeOnly, extractISOTimeOnly]);
23186
+ return parse2(s2, [isoTimeOnly, extractISOTimeOnly]);
23187
23187
  }
23188
23188
  var sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex);
23189
23189
  var sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex);
23190
23190
  var extractISOTimeOffsetAndIANAZone = combineExtractors(extractISOTime, extractISOOffset, extractIANAZone);
23191
23191
  function parseSQL(s2) {
23192
- return parse(s2, [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone]);
23192
+ return parse2(s2, [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone]);
23193
23193
  }
23194
23194
  var INVALID$2 = "Invalid Duration";
23195
23195
  var lowOrderMatrix = {
@@ -31541,7 +31541,7 @@ var require_extension = __commonJS({
31541
31541
  if (dest[name] === void 0) dest[name] = [elem];
31542
31542
  else dest[name].push(elem);
31543
31543
  }
31544
- function parse(header) {
31544
+ function parse2(header) {
31545
31545
  const offers = /* @__PURE__ */ Object.create(null);
31546
31546
  let params = /* @__PURE__ */ Object.create(null);
31547
31547
  let mustUnescape = false;
@@ -31681,7 +31681,7 @@ var require_extension = __commonJS({
31681
31681
  }).join(", ");
31682
31682
  }).join(", ");
31683
31683
  }
31684
- module2.exports = { format, parse };
31684
+ module2.exports = { format, parse: parse2 };
31685
31685
  }
31686
31686
  });
31687
31687
 
@@ -31715,7 +31715,7 @@ var require_websocket = __commonJS({
31715
31715
  var {
31716
31716
  EventTarget: { addEventListener, removeEventListener }
31717
31717
  } = require_event_target();
31718
- var { format, parse } = require_extension();
31718
+ var { format, parse: parse2 } = require_extension();
31719
31719
  var { toBuffer } = require_buffer_util();
31720
31720
  var kAborted = /* @__PURE__ */ Symbol("kAborted");
31721
31721
  var protocolVersions = [8, 13];
@@ -32384,7 +32384,7 @@ var require_websocket = __commonJS({
32384
32384
  }
32385
32385
  let extensions;
32386
32386
  try {
32387
- extensions = parse(secWebSocketExtensions);
32387
+ extensions = parse2(secWebSocketExtensions);
32388
32388
  } catch (err) {
32389
32389
  const message = "Invalid Sec-WebSocket-Extensions header";
32390
32390
  abortHandshake(websocket, socket, message);
@@ -32674,7 +32674,7 @@ var require_subprotocol = __commonJS({
32674
32674
  "../node_modules/.pnpm/ws@8.20.0/node_modules/ws/lib/subprotocol.js"(exports2, module2) {
32675
32675
  "use strict";
32676
32676
  var { tokenChars } = require_validation();
32677
- function parse(header) {
32677
+ function parse2(header) {
32678
32678
  const protocols = /* @__PURE__ */ new Set();
32679
32679
  let start = -1;
32680
32680
  let end = -1;
@@ -32710,7 +32710,7 @@ var require_subprotocol = __commonJS({
32710
32710
  protocols.add(protocol);
32711
32711
  return protocols;
32712
32712
  }
32713
- module2.exports = { parse };
32713
+ module2.exports = { parse: parse2 };
32714
32714
  }
32715
32715
  });
32716
32716
 
@@ -48181,6 +48181,13 @@ var fs10 = __toESM(require("fs"), 1);
48181
48181
  var os5 = __toESM(require("os"), 1);
48182
48182
  var path12 = __toESM(require("path"), 1);
48183
48183
  init_protocol();
48184
+ var DEFAULT_TMP_ROOTS = () => [
48185
+ "/tmp",
48186
+ "/private/tmp",
48187
+ "/var/folders",
48188
+ "/private/var/folders",
48189
+ path12.resolve(os5.tmpdir())
48190
+ ];
48184
48191
  var ProjectsStore = class {
48185
48192
  constructor(opts) {
48186
48193
  this.opts = opts;
@@ -48197,7 +48204,7 @@ var ProjectsStore = class {
48197
48204
  }
48198
48205
  try {
48199
48206
  const parsed = JSON.parse(raw);
48200
- this.entries = (parsed.projects ?? []).map((p2) => ProjectEntry.parse(p2));
48207
+ this.entries = (parsed.projects ?? []).map((p2) => ProjectEntry.parse(p2)).filter((e) => this.isProjectablePath(e.path));
48201
48208
  } catch (err) {
48202
48209
  this.opts.logger?.warn("projects.json corrupt, rebuilding", { err: String(err) });
48203
48210
  this.entries = [];
@@ -48213,8 +48220,27 @@ var ProjectsStore = class {
48213
48220
  return path12.resolve(expanded);
48214
48221
  }
48215
48222
  isProjectablePath(p2) {
48216
- const rel = path12.relative(path12.resolve(this.opts.clawdDir), this.normalize(p2));
48217
- return rel.startsWith("..") || path12.isAbsolute(rel);
48223
+ const abs = this.normalize(p2);
48224
+ const rel = path12.relative(path12.resolve(this.opts.clawdDir), abs);
48225
+ const insideClawd = !(rel.startsWith("..") || path12.isAbsolute(rel));
48226
+ if (insideClawd) return false;
48227
+ if (abs === path12.resolve(os5.homedir()) || abs === path12.parse(abs).root) return false;
48228
+ for (const root of this.tmpRoots()) {
48229
+ if (abs === root || abs.startsWith(root.endsWith(path12.sep) ? root : root + path12.sep)) {
48230
+ return false;
48231
+ }
48232
+ }
48233
+ return true;
48234
+ }
48235
+ /** 层 2 的临时区根(缺省自适应,见构造器 opts.tmpRoots 注释) */
48236
+ tmpRoots() {
48237
+ if (this.opts.tmpRoots) return this.opts.tmpRoots;
48238
+ const defaults = DEFAULT_TMP_ROOTS();
48239
+ const clawd = path12.resolve(this.opts.clawdDir);
48240
+ const clawdItselfInTmp = defaults.some(
48241
+ (r) => clawd === r || clawd.startsWith(r + path12.sep)
48242
+ );
48243
+ return clawdItselfInTmp ? [] : defaults;
48218
48244
  }
48219
48245
  list() {
48220
48246
  return [...this.entries];
@@ -48238,6 +48264,16 @@ var ProjectsStore = class {
48238
48264
  this.entries.push(entry);
48239
48265
  return entry;
48240
48266
  }
48267
+ /**
48268
+ * 从 Codex / CC 全局历史播种(2026-08-18 老板拍板「完全对齐」):让终端里直接用
48269
+ * codex/claude 跑过、但从没在 clawd 建过会话的目录也出现在项目区,两边列表对得上。
48270
+ * 调用方传 session/external-scan 的 scanExternalSessions() 产物(它已过滤空会话与
48271
+ * 已不存在的目录);噪音由本模块的三层判据挡。
48272
+ */
48273
+ seedFromExternal(candidates) {
48274
+ for (const c of candidates) this.add(c.cwd);
48275
+ this.save();
48276
+ }
48241
48277
  seedFromSessions(files) {
48242
48278
  for (const f of files) {
48243
48279
  if (f.originOwnerPrincipalId) continue;
@@ -48248,29 +48284,479 @@ var ProjectsStore = class {
48248
48284
  }
48249
48285
  };
48250
48286
 
48287
+ // src/session/external-scan.ts
48288
+ var import_node_fs11 = __toESM(require("fs"), 1);
48289
+ var import_promises = __toESM(require("fs/promises"), 1);
48290
+ var import_node_os7 = __toESM(require("os"), 1);
48291
+ var import_node_path11 = __toESM(require("path"), 1);
48292
+ var import_node_module = require("module");
48293
+
48294
+ // src/tools/title-generator.ts
48295
+ var import_node_child_process = require("child_process");
48296
+ var import_node_fs10 = __toESM(require("fs"), 1);
48297
+ var import_node_os6 = __toESM(require("os"), 1);
48298
+ var import_node_path10 = __toESM(require("path"), 1);
48299
+ var TITLE_GEN_DIR_PREFIX = "clawd-title-";
48300
+ var TITLE_MODEL_BY_TOOL = {
48301
+ claude: "haiku",
48302
+ codex: "gpt-5.4-mini"
48303
+ };
48304
+ var TITLE_INPUT_MAX_CHARS = 400;
48305
+ var DEFAULT_TITLE_GEN_TIMEOUT_MS = 45e3;
48306
+ var outFileSeq = 0;
48307
+ function buildTitlePrompt(firstMessage) {
48308
+ const text = firstMessage.slice(0, TITLE_INPUT_MAX_CHARS);
48309
+ return `\u4E3A\u4E0B\u9762\u8FD9\u6761\u7528\u6237\u6D88\u606F\u751F\u6210\u4E00\u4E2A\u7B80\u6D01\u7684\u4F1A\u8BDD\u6807\u9898\uFF1A\u4E0D\u8D85\u8FC7 20 \u4E2A\u5B57\uFF08\u82F1\u6587\u5219\u4E0D\u8D85\u8FC7 6 \u4E2A\u5355\u8BCD\uFF09\uFF0C\u4F7F\u7528\u4E0E\u6D88\u606F\u76F8\u540C\u7684\u8BED\u8A00\uFF0C\u53EA\u6982\u62EC\u6D88\u606F\u4E3B\u9898\u3002
48310
+
48311
+ \u7528\u6237\u6D88\u606F\uFF1A
48312
+ ${text}`;
48313
+ }
48314
+ function buildClaudeTitlePrompt(firstMessage) {
48315
+ return buildTitlePrompt(firstMessage) + '\n\n\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u683C\u5F0F\uFF1A{"greeting":"\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC","title":"\u4F1A\u8BDD\u6807\u9898"}\uFF0C\u4E0D\u8981\u8F93\u51FA JSON \u4EE5\u5916\u7684\u4EFB\u4F55\u5185\u5BB9\u3002';
48316
+ }
48317
+ function sanitizeTitle(raw) {
48318
+ const line = raw.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
48319
+ if (!line) return null;
48320
+ const stripped = line.replace(/^["'“”‘’「」《》\[\((]+/, "").replace(/["'“”‘’「」《》\]\))]+$/, "").replace(/[。..!!??]+$/, "").replace(/\s+/g, " ").trim();
48321
+ if (!stripped) return null;
48322
+ return stripped.slice(0, 60);
48323
+ }
48324
+ function buildClaudeTitleArgs(prompt) {
48325
+ return ["-p", "--model", TITLE_MODEL_BY_TOOL.claude, prompt];
48326
+ }
48327
+ var CODEX_TITLE_SCHEMA = JSON.stringify({
48328
+ type: "object",
48329
+ properties: {
48330
+ greeting: { type: "string", description: "\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC" },
48331
+ title: { type: "string", description: "\u4F1A\u8BDD\u6807\u9898\uFF1A\u53EA\u542B\u6D88\u606F\u4E3B\u9898" }
48332
+ },
48333
+ required: ["greeting", "title"],
48334
+ additionalProperties: false
48335
+ });
48336
+ function parseTitleJson(raw) {
48337
+ const text = raw.trim().replace(/^```[a-zA-Z]*\s*/, "").replace(/```\s*$/, "").trim();
48338
+ try {
48339
+ const obj = JSON.parse(text);
48340
+ if (typeof obj.title === "string") return sanitizeTitle(obj.title);
48341
+ } catch {
48342
+ }
48343
+ return sanitizeTitle(text);
48344
+ }
48345
+ function buildCodexTitleArgs(prompt, outFile, schemaFile) {
48346
+ return [
48347
+ "exec",
48348
+ "--ephemeral",
48349
+ "--skip-git-repo-check",
48350
+ "--output-schema",
48351
+ schemaFile,
48352
+ "-s",
48353
+ "read-only",
48354
+ "-m",
48355
+ TITLE_MODEL_BY_TOOL.codex,
48356
+ "--color",
48357
+ "never",
48358
+ "-o",
48359
+ outFile,
48360
+ prompt
48361
+ ];
48362
+ }
48363
+ async function generateSessionTitle(tool, firstMessage, deps = {}) {
48364
+ if (tool !== "claude" && tool !== "codex") return null;
48365
+ const text = firstMessage.trim();
48366
+ if (!text) return null;
48367
+ let workDir;
48368
+ try {
48369
+ workDir = import_node_fs10.default.mkdtempSync(import_node_path10.default.join(import_node_os6.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
48370
+ } catch {
48371
+ return null;
48372
+ }
48373
+ const cleanupWorkDir = () => {
48374
+ try {
48375
+ import_node_fs10.default.rmSync(workDir, { recursive: true, force: true });
48376
+ } catch {
48377
+ }
48378
+ };
48379
+ const outFile = import_node_path10.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
48380
+ const schemaFile = import_node_path10.default.join(workDir, "title-schema.json");
48381
+ if (tool === "codex") {
48382
+ try {
48383
+ import_node_fs10.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
48384
+ } catch {
48385
+ cleanupWorkDir();
48386
+ return null;
48387
+ }
48388
+ }
48389
+ const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : process.env.CODEX_BIN ?? "codex";
48390
+ const args = tool === "claude" ? buildClaudeTitleArgs(buildClaudeTitlePrompt(text)) : buildCodexTitleArgs(buildTitlePrompt(text), outFile, schemaFile);
48391
+ const doSpawn = deps.spawnOverride ?? ((c, a, o) => (0, import_node_child_process.spawn)(c, a, { ...o, stdio: ["ignore", "pipe", "pipe"] }));
48392
+ const timeoutMs = deps.timeoutMs ?? DEFAULT_TITLE_GEN_TIMEOUT_MS;
48393
+ return await new Promise((resolve7) => {
48394
+ let proc;
48395
+ try {
48396
+ proc = doSpawn(cmd, args, { cwd: workDir });
48397
+ } catch (err) {
48398
+ deps.logger?.warn("title-gen spawn failed", { tool, message: err.message });
48399
+ cleanupWorkDir();
48400
+ return resolve7(null);
48401
+ }
48402
+ let stdout = "";
48403
+ let settled = false;
48404
+ const finish = (title) => {
48405
+ if (settled) return;
48406
+ settled = true;
48407
+ clearTimeout(timer);
48408
+ if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGKILL");
48409
+ cleanupWorkDir();
48410
+ resolve7(title);
48411
+ };
48412
+ const timer = setTimeout(() => {
48413
+ deps.logger?.warn("title-gen timed out", { tool, timeoutMs });
48414
+ finish(null);
48415
+ }, timeoutMs);
48416
+ proc.stdout?.on("data", (c) => {
48417
+ stdout += c.toString();
48418
+ });
48419
+ proc.stderr?.on("data", () => {
48420
+ });
48421
+ proc.on("error", (err) => {
48422
+ deps.logger?.warn("title-gen proc error", { tool, message: err.message });
48423
+ finish(null);
48424
+ });
48425
+ proc.on("close", (code) => {
48426
+ if (code !== 0) {
48427
+ deps.logger?.warn("title-gen exited non-zero", { tool, code });
48428
+ return finish(null);
48429
+ }
48430
+ if (tool === "claude") return finish(parseTitleJson(stdout));
48431
+ let fileText = "";
48432
+ try {
48433
+ fileText = import_node_fs10.default.readFileSync(outFile, "utf8");
48434
+ } catch {
48435
+ return finish(null);
48436
+ }
48437
+ finish(parseTitleJson(fileText));
48438
+ });
48439
+ });
48440
+ }
48441
+
48442
+ // src/session/external-scan.ts
48443
+ var import_node_child_process2 = require("child_process");
48444
+ var import_meta = {};
48445
+ function defaultRoots() {
48446
+ const home = import_node_os7.default.homedir();
48447
+ return {
48448
+ claudeProjectsDir: import_node_path11.default.join(home, ".claude", "projects"),
48449
+ codexDir: import_node_path11.default.join(home, ".codex"),
48450
+ clawdDir: import_node_path11.default.join(home, ".clawd")
48451
+ };
48452
+ }
48453
+ function width(s) {
48454
+ let w2 = 0;
48455
+ for (const ch of s) w2 += /[ᄀ-ᅟ⺀-꓏가-힣豈-﫿︰-﹏＀-⦆¢-₩]/.test(ch) ? 2 : 1;
48456
+ return w2;
48457
+ }
48458
+ function clipW(text, n) {
48459
+ const s = String(text ?? "").split(/\s+/).filter(Boolean).join(" ");
48460
+ if (width(s) <= n) return s;
48461
+ let out = "";
48462
+ let w2 = 0;
48463
+ for (const ch of s) {
48464
+ const cw = width(ch);
48465
+ if (w2 + cw > n - 1) break;
48466
+ out += ch;
48467
+ w2 += cw;
48468
+ }
48469
+ return out + "\u2026";
48470
+ }
48471
+ function toMs(v2) {
48472
+ const n = Number(v2 || 0);
48473
+ return n > 1e11 ? Math.round(n) : Math.round(n * 1e3);
48474
+ }
48475
+ function listFiles(dir, depth = 0, maxDepth = 8, out = []) {
48476
+ let entries;
48477
+ try {
48478
+ entries = import_node_fs11.default.readdirSync(dir, { withFileTypes: true });
48479
+ } catch {
48480
+ return out;
48481
+ }
48482
+ for (const e of entries) {
48483
+ const full = import_node_path11.default.join(dir, e.name);
48484
+ if (e.isDirectory()) {
48485
+ if (depth < maxDepth) listFiles(full, depth + 1, maxDepth, out);
48486
+ } else if (e.isFile()) {
48487
+ out.push(full);
48488
+ }
48489
+ }
48490
+ return out;
48491
+ }
48492
+ async function* jsonLines(file) {
48493
+ let raw;
48494
+ try {
48495
+ raw = await import_promises.default.readFile(file, "utf8");
48496
+ } catch {
48497
+ return;
48498
+ }
48499
+ for (const line of raw.split("\n")) {
48500
+ const t = line.trim();
48501
+ if (!t) continue;
48502
+ try {
48503
+ yield JSON.parse(t);
48504
+ } catch {
48505
+ }
48506
+ }
48507
+ }
48508
+ function userText(msg) {
48509
+ const content = msg && typeof msg === "object" ? msg.content : null;
48510
+ if (typeof content === "string") return content;
48511
+ if (Array.isArray(content)) {
48512
+ return content.map((b2) => b2 && b2.type === "text" ? String(b2.text ?? "") : "").join("");
48513
+ }
48514
+ return "";
48515
+ }
48516
+ function isDir(p2) {
48517
+ try {
48518
+ return import_node_fs11.default.statSync(p2).isDirectory();
48519
+ } catch {
48520
+ return false;
48521
+ }
48522
+ }
48523
+ async function scanClaude(roots) {
48524
+ const out = [];
48525
+ let dirs;
48526
+ try {
48527
+ dirs = import_node_fs11.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
48528
+ } catch {
48529
+ return out;
48530
+ }
48531
+ for (const d of dirs) {
48532
+ if (!d.isDirectory()) continue;
48533
+ let files;
48534
+ try {
48535
+ files = import_node_fs11.default.readdirSync(import_node_path11.default.join(roots.claudeProjectsDir, d.name));
48536
+ } catch {
48537
+ continue;
48538
+ }
48539
+ for (const name of files) {
48540
+ if (!name.endsWith(".jsonl")) continue;
48541
+ const file = import_node_path11.default.join(roots.claudeProjectsDir, d.name, name);
48542
+ let st;
48543
+ try {
48544
+ st = import_node_fs11.default.statSync(file);
48545
+ } catch {
48546
+ continue;
48547
+ }
48548
+ let cwd = "";
48549
+ let title = "";
48550
+ let firstUser = "";
48551
+ let turns = 0;
48552
+ let firstTs = 0;
48553
+ let lastTs = 0;
48554
+ let hasMainLine = false;
48555
+ for await (const rec4 of jsonLines(file)) {
48556
+ if (!cwd && typeof rec4.cwd === "string") cwd = rec4.cwd;
48557
+ if (typeof rec4.timestamp === "string") {
48558
+ const t = Date.parse(rec4.timestamp);
48559
+ if (Number.isFinite(t)) {
48560
+ firstTs ||= t;
48561
+ lastTs = t;
48562
+ }
48563
+ }
48564
+ if (rec4.type === "ai-title" && rec4.aiTitle) {
48565
+ title = String(rec4.aiTitle);
48566
+ continue;
48567
+ }
48568
+ if (rec4.type !== "user" && rec4.type !== "assistant") continue;
48569
+ if (!rec4.isSidechain) hasMainLine = true;
48570
+ if (rec4.type !== "user" || rec4.isSidechain || rec4.isMeta) continue;
48571
+ const text = userText(rec4.message || {});
48572
+ if (!text.trim() || text.trimStart().startsWith("<")) continue;
48573
+ turns += 1;
48574
+ firstUser ||= text;
48575
+ }
48576
+ const cand = {
48577
+ tool: "claude",
48578
+ toolSessionId: name.slice(0, -".jsonl".length),
48579
+ cwd,
48580
+ label: clipW(title || firstUser, 56),
48581
+ turns,
48582
+ createdMs: firstTs || st.mtimeMs,
48583
+ updatedMs: lastTs || st.mtimeMs,
48584
+ skip: ""
48585
+ };
48586
+ if (!hasMainLine) cand.skip = "subagent \u652F\u7EBF";
48587
+ else if (!cwd) cand.skip = "\u65E0 cwd";
48588
+ else if (import_node_path11.default.basename(cwd).startsWith(TITLE_GEN_DIR_PREFIX)) cand.skip = "\u6807\u9898\u751F\u6210\u4E34\u65F6\u4F1A\u8BDD";
48589
+ out.push(cand);
48590
+ }
48591
+ }
48592
+ return out;
48593
+ }
48594
+ async function countCodexTurns(rolloutPath) {
48595
+ if (!rolloutPath || !import_node_fs11.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
48596
+ let turns = 0;
48597
+ let first = "";
48598
+ for await (const rec4 of jsonLines(rolloutPath)) {
48599
+ const p2 = rec4.payload || {};
48600
+ if (p2.type !== "message" || p2.role !== "user") continue;
48601
+ const text = (p2.content || []).map((b2) => String(b2 && b2.text || "")).join("");
48602
+ if (!text.trim() || text.trimStart().startsWith("<")) continue;
48603
+ turns += 1;
48604
+ first ||= text;
48605
+ }
48606
+ return { turns, first };
48607
+ }
48608
+ function readCodexThreads(db) {
48609
+ const COLS = ["id", "cwd", "created_at", "updated_at", "name", "title", "preview", "first_user_message", "archived", "rollout_path"];
48610
+ try {
48611
+ const { DatabaseSync } = (0, import_node_module.createRequire)(import_meta.url)("node:sqlite");
48612
+ const conn = new DatabaseSync(db, { readOnly: true });
48613
+ try {
48614
+ const have = new Set(
48615
+ conn.prepare("PRAGMA table_info(threads)").all().map((r) => r.name)
48616
+ );
48617
+ if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
48618
+ const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
48619
+ return conn.prepare(`SELECT ${sel} FROM threads`).all();
48620
+ } finally {
48621
+ conn.close();
48622
+ }
48623
+ } catch {
48624
+ }
48625
+ try {
48626
+ const info = (0, import_node_child_process2.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
48627
+ if (info.status !== 0) return null;
48628
+ const have = new Set(
48629
+ info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
48630
+ );
48631
+ if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
48632
+ const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
48633
+ const res = (0, import_node_child_process2.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
48634
+ encoding: "utf8",
48635
+ maxBuffer: 64 * 1024 * 1024
48636
+ });
48637
+ if (res.status !== 0 || !res.stdout.trim()) return null;
48638
+ return JSON.parse(res.stdout);
48639
+ } catch {
48640
+ return null;
48641
+ }
48642
+ }
48643
+ async function codexFromRows(rows) {
48644
+ const out = [];
48645
+ for (const r of rows) {
48646
+ const updatedMs = toMs(r.updated_at);
48647
+ const { turns, first } = await countCodexTurns(String(r.rollout_path || ""));
48648
+ const label = clipW(r.name || r.title || r.preview || r.first_user_message || first, 56);
48649
+ const cand = {
48650
+ tool: "codex",
48651
+ toolSessionId: String(r.id),
48652
+ cwd: String(r.cwd || ""),
48653
+ label,
48654
+ turns,
48655
+ createdMs: toMs(r.created_at) || updatedMs,
48656
+ updatedMs,
48657
+ skip: ""
48658
+ };
48659
+ if (r.archived) cand.skip = "\u5DF2\u5F52\u6863";
48660
+ else if (!label) cand.skip = "\u7A7A\u4F1A\u8BDD";
48661
+ out.push(cand);
48662
+ }
48663
+ return out;
48664
+ }
48665
+ async function scanCodexRollouts(roots) {
48666
+ const out = [];
48667
+ for (const file of listFiles(import_node_path11.default.join(roots.codexDir, "sessions"))) {
48668
+ if (!file.endsWith(".jsonl")) continue;
48669
+ let st;
48670
+ try {
48671
+ st = import_node_fs11.default.statSync(file);
48672
+ } catch {
48673
+ continue;
48674
+ }
48675
+ let meta = null;
48676
+ for await (const rec4 of jsonLines(file)) {
48677
+ if (rec4.type === "session_meta") {
48678
+ meta = rec4.payload || {};
48679
+ break;
48680
+ }
48681
+ }
48682
+ const tid = meta && (meta.session_id || meta.id);
48683
+ if (!tid) continue;
48684
+ const { turns, first } = await countCodexTurns(file);
48685
+ const cand = {
48686
+ tool: "codex",
48687
+ toolSessionId: String(tid),
48688
+ cwd: String(meta?.cwd || ""),
48689
+ label: clipW(first, 56),
48690
+ turns,
48691
+ createdMs: st.mtimeMs,
48692
+ updatedMs: st.mtimeMs,
48693
+ skip: ""
48694
+ };
48695
+ if (!cand.cwd) cand.skip = "\u65E0 cwd";
48696
+ out.push(cand);
48697
+ }
48698
+ return out;
48699
+ }
48700
+ async function scanCodex(roots) {
48701
+ let dbs = [];
48702
+ try {
48703
+ dbs = import_node_fs11.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path11.default.join(roots.codexDir, n));
48704
+ } catch {
48705
+ }
48706
+ if (dbs.length) {
48707
+ const rows = readCodexThreads(dbs[dbs.length - 1]);
48708
+ if (rows) return codexFromRows(rows);
48709
+ }
48710
+ return scanCodexRollouts(roots);
48711
+ }
48712
+ async function scanExternalSessions(rootsIn) {
48713
+ const roots = { ...defaultRoots(), ...rootsIn };
48714
+ const personaRoot = import_node_path11.default.join(roots.clawdDir, "personas");
48715
+ const all = [...await scanClaude(roots), ...await scanCodex(roots)];
48716
+ const out = [];
48717
+ for (const c of all) {
48718
+ if (c.skip) continue;
48719
+ if (c.turns < 1) continue;
48720
+ if (!c.cwd || !isDir(c.cwd)) continue;
48721
+ if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path11.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path11.default.sep)) {
48722
+ continue;
48723
+ }
48724
+ out.push({
48725
+ tool: c.tool,
48726
+ cwd: c.cwd,
48727
+ toolSessionId: c.toolSessionId,
48728
+ ...c.label ? { label: c.label } : {},
48729
+ createdAt: new Date(c.createdMs).toISOString(),
48730
+ updatedAt: new Date(c.updatedMs).toISOString(),
48731
+ turns: c.turns
48732
+ });
48733
+ }
48734
+ return out;
48735
+ }
48736
+
48251
48737
  // src/persona/store.ts
48252
- var fs11 = __toESM(require("fs"), 1);
48253
- var path13 = __toESM(require("path"), 1);
48738
+ var fs13 = __toESM(require("fs"), 1);
48739
+ var path15 = __toESM(require("path"), 1);
48254
48740
  init_protocol();
48255
48741
  var PersonaStore = class {
48256
48742
  constructor(root) {
48257
48743
  this.root = root;
48258
- fs11.mkdirSync(root, { recursive: true });
48744
+ fs13.mkdirSync(root, { recursive: true });
48259
48745
  }
48260
48746
  root;
48261
48747
  personaDir(personaId2) {
48262
- return path13.join(this.root, safeFileName(personaId2));
48748
+ return path15.join(this.root, safeFileName(personaId2));
48263
48749
  }
48264
48750
  metaPath(personaId2) {
48265
- return path13.join(this.personaDir(personaId2), ".clawd", "persona.json");
48751
+ return path15.join(this.personaDir(personaId2), ".clawd", "persona.json");
48266
48752
  }
48267
48753
  claudeMdPath(personaId2) {
48268
- return path13.join(this.personaDir(personaId2), "CLAUDE.md");
48754
+ return path15.join(this.personaDir(personaId2), "CLAUDE.md");
48269
48755
  }
48270
48756
  // codex 原生读 cwd 的 AGENTS.md。人格双写镜像:claude 读 CLAUDE.md、codex 读 AGENTS.md,
48271
48757
  // 两份内容恒一致,persona 切 tool 零迁移。
48272
48758
  agentsMdPath(personaId2) {
48273
- return path13.join(this.personaDir(personaId2), "AGENTS.md");
48759
+ return path15.join(this.personaDir(personaId2), "AGENTS.md");
48274
48760
  }
48275
48761
  /**
48276
48762
  * persona 级 sandbox base 落盘路径 —— 故意放 `.clawd/` 而非 `.claude/`,让 CC 的 project
@@ -48279,11 +48765,11 @@ var PersonaStore = class {
48279
48765
  * spawn 前 per-guest 动态拼到各自 session 目录的那份(base + 强制底座 + 本 guest userWorkDir carve)。
48280
48766
  */
48281
48767
  sandboxSettingsPath(personaId2) {
48282
- return path13.join(this.personaDir(personaId2), ".clawd", "sandbox-settings.json");
48768
+ return path15.join(this.personaDir(personaId2), ".clawd", "sandbox-settings.json");
48283
48769
  }
48284
48770
  write(persona, personality) {
48285
48771
  const dir = this.personaDir(persona.personaId);
48286
- fs11.mkdirSync(path13.join(dir, ".clawd"), { recursive: true });
48772
+ fs13.mkdirSync(path15.join(dir, ".clawd"), { recursive: true });
48287
48773
  this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
48288
48774
  this.atomicWrite(this.agentsMdPath(persona.personaId), personality);
48289
48775
  this.writeSandboxSettings(persona.personaId, buildGuestSettingsV1());
@@ -48302,9 +48788,9 @@ var PersonaStore = class {
48302
48788
  ensureAgentsMirror(personaId2) {
48303
48789
  const claudeMd = this.claudeMdPath(personaId2);
48304
48790
  const agentsMd = this.agentsMdPath(personaId2);
48305
- if (!fs11.existsSync(claudeMd)) return false;
48306
- if (fs11.existsSync(agentsMd)) return false;
48307
- this.atomicWrite(agentsMd, fs11.readFileSync(claudeMd, "utf8"));
48791
+ if (!fs13.existsSync(claudeMd)) return false;
48792
+ if (fs13.existsSync(agentsMd)) return false;
48793
+ this.atomicWrite(agentsMd, fs13.readFileSync(claudeMd, "utf8"));
48308
48794
  return true;
48309
48795
  }
48310
48796
  /**
@@ -48354,22 +48840,22 @@ var PersonaStore = class {
48354
48840
  };
48355
48841
  }
48356
48842
  codexSandboxSettingsPath(personaId2) {
48357
- return path13.join(this.personaDir(personaId2), ".clawd", "codex-sandbox.json");
48843
+ return path15.join(this.personaDir(personaId2), ".clawd", "codex-sandbox.json");
48358
48844
  }
48359
48845
  /** 读 codex-sandbox.json;不存在/损坏 → null。 */
48360
48846
  readCodexSandboxSettings(personaId2) {
48361
48847
  const p2 = this.codexSandboxSettingsPath(personaId2);
48362
- if (!fs11.existsSync(p2)) return null;
48848
+ if (!fs13.existsSync(p2)) return null;
48363
48849
  try {
48364
- return CodexSandboxSettingsSchema.parse(JSON.parse(fs11.readFileSync(p2, "utf8")));
48850
+ return CodexSandboxSettingsSchema.parse(JSON.parse(fs13.readFileSync(p2, "utf8")));
48365
48851
  } catch {
48366
48852
  return null;
48367
48853
  }
48368
48854
  }
48369
48855
  /** 覆盖写 codex-sandbox.json(seed/migrate 用)。 */
48370
48856
  writeCodexSandboxSettings(personaId2, settings) {
48371
- const dir = path13.join(this.personaDir(personaId2), ".clawd");
48372
- fs11.mkdirSync(dir, { recursive: true });
48857
+ const dir = path15.join(this.personaDir(personaId2), ".clawd");
48858
+ fs13.mkdirSync(dir, { recursive: true });
48373
48859
  this.atomicWrite(this.codexSandboxSettingsPath(personaId2), JSON.stringify(settings, null, 2));
48374
48860
  }
48375
48861
  writeMeta(persona) {
@@ -48377,8 +48863,8 @@ var PersonaStore = class {
48377
48863
  }
48378
48864
  read(personaId2) {
48379
48865
  const p2 = this.metaPath(personaId2);
48380
- if (!fs11.existsSync(p2)) return null;
48381
- const raw = JSON.parse(fs11.readFileSync(p2, "utf8"));
48866
+ if (!fs13.existsSync(p2)) return null;
48867
+ const raw = JSON.parse(fs13.readFileSync(p2, "utf8"));
48382
48868
  if (raw && typeof raw === "object" && "tokenMap" in raw) {
48383
48869
  delete raw.tokenMap;
48384
48870
  this.atomicWrite(p2, JSON.stringify(raw, null, 2));
@@ -48386,13 +48872,13 @@ var PersonaStore = class {
48386
48872
  return PersonaFileSchema.parse(raw);
48387
48873
  }
48388
48874
  has(personaId2) {
48389
- return fs11.existsSync(this.metaPath(personaId2));
48875
+ return fs13.existsSync(this.metaPath(personaId2));
48390
48876
  }
48391
48877
  readPersonality(personaId2) {
48392
48878
  const claudeMd = this.claudeMdPath(personaId2);
48393
- if (fs11.existsSync(claudeMd)) return fs11.readFileSync(claudeMd, "utf8");
48879
+ if (fs13.existsSync(claudeMd)) return fs13.readFileSync(claudeMd, "utf8");
48394
48880
  const agentsMd = this.agentsMdPath(personaId2);
48395
- if (fs11.existsSync(agentsMd)) return fs11.readFileSync(agentsMd, "utf8");
48881
+ if (fs13.existsSync(agentsMd)) return fs13.readFileSync(agentsMd, "utf8");
48396
48882
  return null;
48397
48883
  }
48398
48884
  /**
@@ -48401,23 +48887,23 @@ var PersonaStore = class {
48401
48887
  */
48402
48888
  readSandboxSettings(personaId2) {
48403
48889
  const p2 = this.sandboxSettingsPath(personaId2);
48404
- if (!fs11.existsSync(p2)) return null;
48890
+ if (!fs13.existsSync(p2)) return null;
48405
48891
  try {
48406
- return JSON.parse(fs11.readFileSync(p2, "utf8"));
48892
+ return JSON.parse(fs13.readFileSync(p2, "utf8"));
48407
48893
  } catch {
48408
48894
  return null;
48409
48895
  }
48410
48896
  }
48411
48897
  /** Persona 私有 skills 目录路径:<personaDir>/.claude/skills */
48412
48898
  skillsDir(personaId2) {
48413
- return path13.join(this.personaDir(personaId2), ".claude", "skills");
48899
+ return path15.join(this.personaDir(personaId2), ".claude", "skills");
48414
48900
  }
48415
48901
  /**
48416
48902
  * Claude Code 项目级 settings 路径:`<personaDir>/.claude/settings.json`。
48417
48903
  * 这里只读 `enabledPlugins` 字段,由 owner 通过 CC `/plugin` 之类命令维护,daemon 不写。
48418
48904
  */
48419
48905
  claudeSettingsPath(personaId2) {
48420
- return path13.join(this.personaDir(personaId2), ".claude", "settings.json");
48906
+ return path15.join(this.personaDir(personaId2), ".claude", "settings.json");
48421
48907
  }
48422
48908
  /**
48423
48909
  * 读取 persona 的 `.claude/settings.json` 中 `enabledPlugins` map,把 value === true
@@ -48432,10 +48918,10 @@ var PersonaStore = class {
48432
48918
  */
48433
48919
  readEnabledPlugins(personaId2) {
48434
48920
  const p2 = this.claudeSettingsPath(personaId2);
48435
- if (!fs11.existsSync(p2)) return [];
48921
+ if (!fs13.existsSync(p2)) return [];
48436
48922
  let raw;
48437
48923
  try {
48438
- raw = JSON.parse(fs11.readFileSync(p2, "utf8"));
48924
+ raw = JSON.parse(fs13.readFileSync(p2, "utf8"));
48439
48925
  } catch {
48440
48926
  return [];
48441
48927
  }
@@ -48449,22 +48935,22 @@ var PersonaStore = class {
48449
48935
  return out;
48450
48936
  }
48451
48937
  list() {
48452
- if (!fs11.existsSync(this.root)) return [];
48453
- return fs11.readdirSync(this.root).filter((name) => {
48454
- return fs11.existsSync(path13.join(this.root, name, ".clawd", "persona.json"));
48938
+ if (!fs13.existsSync(this.root)) return [];
48939
+ return fs13.readdirSync(this.root).filter((name) => {
48940
+ return fs13.existsSync(path15.join(this.root, name, ".clawd", "persona.json"));
48455
48941
  });
48456
48942
  }
48457
48943
  remove(personaId2) {
48458
48944
  const dir = this.personaDir(personaId2);
48459
- if (fs11.existsSync(dir)) fs11.rmSync(dir, { recursive: true, force: true });
48945
+ if (fs13.existsSync(dir)) fs13.rmSync(dir, { recursive: true, force: true });
48460
48946
  }
48461
48947
  personaDirPath(personaId2) {
48462
48948
  return this.personaDir(personaId2);
48463
48949
  }
48464
48950
  atomicWrite(file, content) {
48465
48951
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
48466
- fs11.writeFileSync(tmp, content, { mode: 384 });
48467
- fs11.renameSync(tmp, file);
48952
+ fs13.writeFileSync(tmp, content, { mode: 384 });
48953
+ fs13.renameSync(tmp, file);
48468
48954
  }
48469
48955
  };
48470
48956
 
@@ -48507,9 +48993,9 @@ var PersonaRegistry = class {
48507
48993
  };
48508
48994
 
48509
48995
  // src/skills/scanner.ts
48510
- var import_node_fs10 = __toESM(require("fs"), 1);
48511
- var import_node_os6 = __toESM(require("os"), 1);
48512
- var import_node_path10 = __toESM(require("path"), 1);
48996
+ var import_node_fs12 = __toESM(require("fs"), 1);
48997
+ var import_node_os8 = __toESM(require("os"), 1);
48998
+ var import_node_path12 = __toESM(require("path"), 1);
48513
48999
 
48514
49000
  // src/skills/frontmatter.ts
48515
49001
  var STRIP_QUOTES = /^["']|["']$/g;
@@ -48618,7 +49104,7 @@ function parseDescription(content) {
48618
49104
  }
48619
49105
  function isDirLikeSync(p2) {
48620
49106
  try {
48621
- return import_node_fs10.default.statSync(p2).isDirectory();
49107
+ return import_node_fs12.default.statSync(p2).isDirectory();
48622
49108
  } catch {
48623
49109
  return false;
48624
49110
  }
@@ -48626,19 +49112,19 @@ function isDirLikeSync(p2) {
48626
49112
  function scanSkillDir(dir, source, seen, out, pluginName) {
48627
49113
  let entries;
48628
49114
  try {
48629
- entries = import_node_fs10.default.readdirSync(dir, { withFileTypes: true });
49115
+ entries = import_node_fs12.default.readdirSync(dir, { withFileTypes: true });
48630
49116
  } catch {
48631
49117
  return;
48632
49118
  }
48633
49119
  for (const ent of entries) {
48634
- const entryPath = import_node_path10.default.join(dir, ent.name);
49120
+ const entryPath = import_node_path12.default.join(dir, ent.name);
48635
49121
  if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
48636
49122
  let content;
48637
49123
  try {
48638
- content = import_node_fs10.default.readFileSync(import_node_path10.default.join(entryPath, "SKILL.md"), "utf8");
49124
+ content = import_node_fs12.default.readFileSync(import_node_path12.default.join(entryPath, "SKILL.md"), "utf8");
48639
49125
  } catch {
48640
49126
  try {
48641
- content = import_node_fs10.default.readFileSync(import_node_path10.default.join(entryPath, "skill.md"), "utf8");
49127
+ content = import_node_fs12.default.readFileSync(import_node_path12.default.join(entryPath, "skill.md"), "utf8");
48642
49128
  } catch {
48643
49129
  continue;
48644
49130
  }
@@ -48662,26 +49148,26 @@ function listSkillsForDir(dir, source) {
48662
49148
  function scanCommandDir(dir, source, seen, out, pluginName) {
48663
49149
  let entries;
48664
49150
  try {
48665
- entries = import_node_fs10.default.readdirSync(dir, { withFileTypes: true });
49151
+ entries = import_node_fs12.default.readdirSync(dir, { withFileTypes: true });
48666
49152
  } catch {
48667
49153
  return;
48668
49154
  }
48669
49155
  for (const ent of entries) {
48670
- const entryPath = import_node_path10.default.join(dir, ent.name);
49156
+ const entryPath = import_node_path12.default.join(dir, ent.name);
48671
49157
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
48672
49158
  const ns = ent.name;
48673
49159
  let subEntries;
48674
49160
  try {
48675
- subEntries = import_node_fs10.default.readdirSync(entryPath, { withFileTypes: true });
49161
+ subEntries = import_node_fs12.default.readdirSync(entryPath, { withFileTypes: true });
48676
49162
  } catch {
48677
49163
  continue;
48678
49164
  }
48679
49165
  for (const se of subEntries) {
48680
49166
  if (!se.name.endsWith(".md")) continue;
48681
- const sePath = import_node_path10.default.join(entryPath, se.name);
49167
+ const sePath = import_node_path12.default.join(entryPath, se.name);
48682
49168
  let content;
48683
49169
  try {
48684
- content = import_node_fs10.default.readFileSync(sePath, "utf8");
49170
+ content = import_node_fs12.default.readFileSync(sePath, "utf8");
48685
49171
  } catch {
48686
49172
  continue;
48687
49173
  }
@@ -48698,7 +49184,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
48698
49184
  } else if (ent.name.endsWith(".md")) {
48699
49185
  let content;
48700
49186
  try {
48701
- content = import_node_fs10.default.readFileSync(entryPath, "utf8");
49187
+ content = import_node_fs12.default.readFileSync(entryPath, "utf8");
48702
49188
  } catch {
48703
49189
  continue;
48704
49190
  }
@@ -48714,10 +49200,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
48714
49200
  }
48715
49201
  }
48716
49202
  function readInstalledPlugins(home) {
48717
- const file = import_node_path10.default.join(home, ".claude", "plugins", "installed_plugins.json");
49203
+ const file = import_node_path12.default.join(home, ".claude", "plugins", "installed_plugins.json");
48718
49204
  let raw;
48719
49205
  try {
48720
- raw = import_node_fs10.default.readFileSync(file, "utf8");
49206
+ raw = import_node_fs12.default.readFileSync(file, "utf8");
48721
49207
  } catch {
48722
49208
  return [];
48723
49209
  }
@@ -48742,7 +49228,7 @@ var SkillsScanner = class {
48742
49228
  home;
48743
49229
  extraPluginRoots;
48744
49230
  constructor(opts = {}) {
48745
- this.home = opts.home ?? import_node_os6.default.homedir();
49231
+ this.home = opts.home ?? import_node_os8.default.homedir();
48746
49232
  this.extraPluginRoots = opts.extraPluginRoots ?? [];
48747
49233
  }
48748
49234
  /**
@@ -48765,14 +49251,14 @@ var SkillsScanner = class {
48765
49251
  });
48766
49252
  }
48767
49253
  const fsBlock = [];
48768
- scanSkillDir(import_node_path10.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
48769
- scanCommandDir(import_node_path10.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
48770
- scanSkillDir(import_node_path10.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
48771
- scanCommandDir(import_node_path10.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
49254
+ scanSkillDir(import_node_path12.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
49255
+ scanCommandDir(import_node_path12.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
49256
+ scanSkillDir(import_node_path12.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
49257
+ scanCommandDir(import_node_path12.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
48772
49258
  const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
48773
49259
  for (const { name, root } of plugins) {
48774
- scanSkillDir(import_node_path10.default.join(root, "skills"), "plugin", seen, fsBlock, name);
48775
- scanCommandDir(import_node_path10.default.join(root, "commands"), "plugin", seen, fsBlock, name);
49260
+ scanSkillDir(import_node_path12.default.join(root, "skills"), "plugin", seen, fsBlock, name);
49261
+ scanCommandDir(import_node_path12.default.join(root, "commands"), "plugin", seen, fsBlock, name);
48776
49262
  }
48777
49263
  fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
48778
49264
  return [...builtinBlock, ...fsBlock];
@@ -48876,10 +49362,10 @@ var PersonaManager = class {
48876
49362
  };
48877
49363
 
48878
49364
  // src/persona/seed.ts
48879
- var fs13 = __toESM(require("fs"), 1);
48880
- var path15 = __toESM(require("path"), 1);
49365
+ var fs15 = __toESM(require("fs"), 1);
49366
+ var path17 = __toESM(require("path"), 1);
48881
49367
  var import_node_url = require("url");
48882
- var import_meta = {};
49368
+ var import_meta2 = {};
48883
49369
  var DEFAULT_BYPASS_PROFILE = {
48884
49370
  permissions: { defaultMode: "bypassPermissions" }
48885
49371
  };
@@ -49053,24 +49539,24 @@ function bundleSiblingFromArgv(argv1, sibling) {
49053
49539
  if (!argv1) return null;
49054
49540
  let real = argv1;
49055
49541
  try {
49056
- real = fs13.realpathSync(argv1);
49542
+ real = fs15.realpathSync(argv1);
49057
49543
  } catch {
49058
49544
  }
49059
- return path15.resolve(path15.dirname(real), sibling);
49545
+ return path17.resolve(path17.dirname(real), sibling);
49060
49546
  }
49061
49547
  function findDefaultsRoot(logger) {
49062
49548
  const candidates = [];
49063
49549
  try {
49064
- const here = path15.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
49065
- candidates.push(path15.resolve(here, "defaults"));
49066
- candidates.push(path15.resolve(here, "persona-defaults"));
49550
+ const here = path17.dirname((0, import_node_url.fileURLToPath)(import_meta2.url));
49551
+ candidates.push(path17.resolve(here, "defaults"));
49552
+ candidates.push(path17.resolve(here, "persona-defaults"));
49067
49553
  } catch {
49068
49554
  }
49069
49555
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "persona-defaults");
49070
49556
  if (fromArgv) candidates.push(fromArgv);
49071
49557
  for (const c of candidates) {
49072
49558
  try {
49073
- if (fs13.statSync(c).isDirectory()) {
49559
+ if (fs15.statSync(c).isDirectory()) {
49074
49560
  logger?.info("persona.defaults-root.resolved", { root: c });
49075
49561
  return c;
49076
49562
  }
@@ -49087,8 +49573,8 @@ function seedDefaultPersonas(args) {
49087
49573
  args.logger.info("persona.seed.skip", { personaId: entry.personaId, reason: "exists" });
49088
49574
  continue;
49089
49575
  }
49090
- const bundleDir = path15.join(args.defaultsRoot, entry.personaId);
49091
- if (!fs13.existsSync(bundleDir)) {
49576
+ const bundleDir = path17.join(args.defaultsRoot, entry.personaId);
49577
+ if (!fs15.existsSync(bundleDir)) {
49092
49578
  args.logger.warn("persona.seed.skip", {
49093
49579
  personaId: entry.personaId,
49094
49580
  reason: "bundle-missing",
@@ -49096,8 +49582,8 @@ function seedDefaultPersonas(args) {
49096
49582
  });
49097
49583
  continue;
49098
49584
  }
49099
- const claudeMdPath = path15.join(bundleDir, "CLAUDE.md");
49100
- if (!fs13.existsSync(claudeMdPath)) {
49585
+ const claudeMdPath = path17.join(bundleDir, "CLAUDE.md");
49586
+ if (!fs15.existsSync(claudeMdPath)) {
49101
49587
  args.logger.warn("persona.seed.skip", {
49102
49588
  personaId: entry.personaId,
49103
49589
  reason: "no-CLAUDE.md",
@@ -49105,7 +49591,7 @@ function seedDefaultPersonas(args) {
49105
49591
  });
49106
49592
  continue;
49107
49593
  }
49108
- const personality = fs13.readFileSync(claudeMdPath, "utf8");
49594
+ const personality = fs15.readFileSync(claudeMdPath, "utf8");
49109
49595
  const now = Date.now();
49110
49596
  const persona = {
49111
49597
  personaId: entry.personaId,
@@ -49132,51 +49618,51 @@ function seedDefaultPersonas(args) {
49132
49618
  }
49133
49619
  }
49134
49620
  function skipNodeModulesUnder(srcRoot) {
49135
- return (src) => !path15.relative(srcRoot, src).split(path15.sep).includes("node_modules");
49621
+ return (src) => !path17.relative(srcRoot, src).split(path17.sep).includes("node_modules");
49136
49622
  }
49137
49623
  function copyBundleExtras(srcDir, dstDir) {
49138
- for (const entry of fs13.readdirSync(srcDir, { withFileTypes: true })) {
49624
+ for (const entry of fs15.readdirSync(srcDir, { withFileTypes: true })) {
49139
49625
  if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
49140
- const srcPath = path15.join(srcDir, entry.name);
49141
- const dstPath = path15.join(dstDir, entry.name);
49626
+ const srcPath = path17.join(srcDir, entry.name);
49627
+ const dstPath = path17.join(dstDir, entry.name);
49142
49628
  if (entry.isDirectory()) {
49143
- fs13.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
49629
+ fs15.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
49144
49630
  } else if (entry.isFile()) {
49145
- fs13.copyFileSync(srcPath, dstPath);
49631
+ fs15.copyFileSync(srcPath, dstPath);
49146
49632
  }
49147
49633
  }
49148
49634
  }
49149
49635
  var DAEMON_MANAGED_PATHS = ["extension-kit", "CLAUDE.md", ".mcp.json", ".claude/skills"];
49150
49636
  function replaceManagedPath(src, dst) {
49151
- if (!fs13.statSync(src).isDirectory()) {
49152
- fs13.mkdirSync(path15.dirname(dst), { recursive: true });
49153
- fs13.rmSync(dst, { recursive: true, force: true });
49154
- fs13.cpSync(src, dst, { dereference: true });
49637
+ if (!fs15.statSync(src).isDirectory()) {
49638
+ fs15.mkdirSync(path17.dirname(dst), { recursive: true });
49639
+ fs15.rmSync(dst, { recursive: true, force: true });
49640
+ fs15.cpSync(src, dst, { dereference: true });
49155
49641
  return;
49156
49642
  }
49157
- fs13.mkdirSync(dst, { recursive: true });
49158
- for (const e of fs13.readdirSync(src, { withFileTypes: true })) {
49643
+ fs15.mkdirSync(dst, { recursive: true });
49644
+ for (const e of fs15.readdirSync(src, { withFileTypes: true })) {
49159
49645
  if (e.name === "node_modules") continue;
49160
- const child = path15.join(dst, e.name);
49161
- fs13.rmSync(child, { recursive: true, force: true });
49162
- fs13.cpSync(path15.join(src, e.name), child, { recursive: true, dereference: true });
49646
+ const child = path17.join(dst, e.name);
49647
+ fs15.rmSync(child, { recursive: true, force: true });
49648
+ fs15.cpSync(path17.join(src, e.name), child, { recursive: true, dereference: true });
49163
49649
  }
49164
49650
  }
49165
49651
  function refreshDaemonManagedDirs(args) {
49166
49652
  const entries = args.entries ?? DEFAULT_PERSONAS;
49167
49653
  for (const entry of entries) {
49168
- const bundleDir = path15.join(args.defaultsRoot, entry.personaId);
49169
- if (!fs13.existsSync(bundleDir)) continue;
49654
+ const bundleDir = path17.join(args.defaultsRoot, entry.personaId);
49655
+ if (!fs15.existsSync(bundleDir)) continue;
49170
49656
  const personaDir = args.store.personaDirPath(entry.personaId);
49171
- if (!fs13.existsSync(personaDir)) continue;
49657
+ if (!fs15.existsSync(personaDir)) continue;
49172
49658
  for (const relPath of DAEMON_MANAGED_PATHS) {
49173
- const srcPath = path15.join(bundleDir, relPath);
49174
- if (!fs13.existsSync(srcPath)) continue;
49175
- const dstPath = path15.join(personaDir, relPath);
49659
+ const srcPath = path17.join(bundleDir, relPath);
49660
+ if (!fs15.existsSync(srcPath)) continue;
49661
+ const dstPath = path17.join(personaDir, relPath);
49176
49662
  try {
49177
49663
  replaceManagedPath(srcPath, dstPath);
49178
49664
  if (relPath === "CLAUDE.md") {
49179
- replaceManagedPath(srcPath, path15.join(personaDir, "AGENTS.md"));
49665
+ replaceManagedPath(srcPath, path17.join(personaDir, "AGENTS.md"));
49180
49666
  }
49181
49667
  args.logger.info("persona.refresh.synced", {
49182
49668
  personaId: entry.personaId,
@@ -49276,7 +49762,7 @@ function migrateSandboxAllowRead(args) {
49276
49762
  for (const personaId2 of args.store.list()) {
49277
49763
  try {
49278
49764
  const readPath = tildePath(args.store.personaDirPath(personaId2));
49279
- if (!fs13.existsSync(args.store.sandboxSettingsPath(personaId2))) {
49765
+ if (!fs15.existsSync(args.store.sandboxSettingsPath(personaId2))) {
49280
49766
  args.store.writeSandboxSettings(personaId2, buildGuestSettingsV1());
49281
49767
  n++;
49282
49768
  continue;
@@ -49319,13 +49805,13 @@ var PERSONA_BUILDER_TOMBSTONE = `${PERSONA_BUILDER_TOMBSTONE_MARKER}
49319
49805
  function containsAnyFile(dir) {
49320
49806
  let entries;
49321
49807
  try {
49322
- entries = fs13.readdirSync(dir, { withFileTypes: true });
49808
+ entries = fs15.readdirSync(dir, { withFileTypes: true });
49323
49809
  } catch {
49324
49810
  return false;
49325
49811
  }
49326
49812
  for (const e of entries) {
49327
49813
  if (e.isDirectory()) {
49328
- if (containsAnyFile(path15.join(dir, e.name))) return true;
49814
+ if (containsAnyFile(path17.join(dir, e.name))) return true;
49329
49815
  } else {
49330
49816
  return true;
49331
49817
  }
@@ -49334,9 +49820,9 @@ function containsAnyFile(dir) {
49334
49820
  }
49335
49821
  function retirePersonaBuilder(args) {
49336
49822
  const dir = args.store.personaDirPath(PERSONA_BUILDER_ID);
49337
- if (!fs13.existsSync(dir)) return;
49823
+ if (!fs15.existsSync(dir)) return;
49338
49824
  try {
49339
- const used = containsAnyFile(path15.join(dir, ".clawd", "sessions")) || containsAnyFile(path15.join(dir, ".claude", "skills")) || containsAnyFile(path15.join(dir, "projects"));
49825
+ const used = containsAnyFile(path17.join(dir, ".clawd", "sessions")) || containsAnyFile(path17.join(dir, ".claude", "skills")) || containsAnyFile(path17.join(dir, "projects"));
49340
49826
  if (!used) {
49341
49827
  args.store.remove(PERSONA_BUILDER_ID);
49342
49828
  args.logger.info("persona.retire-builder.removed", { personaId: PERSONA_BUILDER_ID });
@@ -49344,10 +49830,10 @@ function retirePersonaBuilder(args) {
49344
49830
  }
49345
49831
  let wrote = false;
49346
49832
  for (const name of ["CLAUDE.md", "AGENTS.md"]) {
49347
- const p2 = path15.join(dir, name);
49348
- const cur = fs13.existsSync(p2) ? fs13.readFileSync(p2, "utf8") : null;
49833
+ const p2 = path17.join(dir, name);
49834
+ const cur = fs15.existsSync(p2) ? fs15.readFileSync(p2, "utf8") : null;
49349
49835
  if (cur?.startsWith(PERSONA_BUILDER_TOMBSTONE_MARKER)) continue;
49350
- fs13.writeFileSync(p2, PERSONA_BUILDER_TOMBSTONE);
49836
+ fs15.writeFileSync(p2, PERSONA_BUILDER_TOMBSTONE);
49351
49837
  wrote = true;
49352
49838
  }
49353
49839
  if (wrote) args.logger.info("persona.retire-builder.tombstoned", { personaId: PERSONA_BUILDER_ID });
@@ -49361,15 +49847,15 @@ function retirePersonaBuilder(args) {
49361
49847
  function findDeployKitRoot(logger) {
49362
49848
  const candidates = [];
49363
49849
  try {
49364
- const here = path15.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
49365
- candidates.push(path15.resolve(here, "..", "deploy-kit"));
49850
+ const here = path17.dirname((0, import_node_url.fileURLToPath)(import_meta2.url));
49851
+ candidates.push(path17.resolve(here, "..", "deploy-kit"));
49366
49852
  } catch {
49367
49853
  }
49368
49854
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "deploy-kit");
49369
49855
  if (fromArgv) candidates.push(fromArgv);
49370
49856
  for (const c of candidates) {
49371
49857
  try {
49372
- if (fs13.statSync(c).isDirectory()) {
49858
+ if (fs15.statSync(c).isDirectory()) {
49373
49859
  logger?.info("persona.deploy-kit-root.resolved", { root: c });
49374
49860
  return c;
49375
49861
  }
@@ -49380,8 +49866,8 @@ function findDeployKitRoot(logger) {
49380
49866
  return null;
49381
49867
  }
49382
49868
  function seedDeployKit(args) {
49383
- const dst = path15.join(args.dataDir, "deploy-kit");
49384
- fs13.cpSync(args.deployKitBundleRoot, dst, {
49869
+ const dst = path17.join(args.dataDir, "deploy-kit");
49870
+ fs15.cpSync(args.deployKitBundleRoot, dst, {
49385
49871
  recursive: true,
49386
49872
  dereference: true,
49387
49873
  force: false,
@@ -49390,35 +49876,35 @@ function seedDeployKit(args) {
49390
49876
  args.logger.info("deploy-kit.seed.done", { dst });
49391
49877
  }
49392
49878
  function refreshDeployKit(args) {
49393
- const dst = path15.join(args.dataDir, "deploy-kit");
49394
- if (!fs13.existsSync(dst)) {
49879
+ const dst = path17.join(args.dataDir, "deploy-kit");
49880
+ if (!fs15.existsSync(dst)) {
49395
49881
  seedDeployKit(args);
49396
49882
  return;
49397
49883
  }
49398
49884
  for (const sub of ["scripts", "contract"]) {
49399
- const s = path15.join(args.deployKitBundleRoot, sub);
49400
- if (fs13.existsSync(s)) {
49401
- fs13.cpSync(s, path15.join(dst, sub), { recursive: true, force: true, dereference: true });
49885
+ const s = path17.join(args.deployKitBundleRoot, sub);
49886
+ if (fs15.existsSync(s)) {
49887
+ fs15.cpSync(s, path17.join(dst, sub), { recursive: true, force: true, dereference: true });
49402
49888
  }
49403
49889
  }
49404
- const secretsSrc = path15.join(args.deployKitBundleRoot, ".secrets");
49405
- if (fs13.existsSync(secretsSrc)) {
49406
- fs13.mkdirSync(path15.join(dst, ".secrets"), { recursive: true });
49407
- for (const f of fs13.readdirSync(secretsSrc)) {
49890
+ const secretsSrc = path17.join(args.deployKitBundleRoot, ".secrets");
49891
+ if (fs15.existsSync(secretsSrc)) {
49892
+ fs15.mkdirSync(path17.join(dst, ".secrets"), { recursive: true });
49893
+ for (const f of fs15.readdirSync(secretsSrc)) {
49408
49894
  if (f.endsWith(".local")) continue;
49409
- fs13.copyFileSync(path15.join(secretsSrc, f), path15.join(dst, ".secrets", f));
49895
+ fs15.copyFileSync(path17.join(secretsSrc, f), path17.join(dst, ".secrets", f));
49410
49896
  }
49411
49897
  }
49412
49898
  args.logger.info("deploy-kit.refresh.done", { dst });
49413
49899
  }
49414
49900
 
49415
49901
  // src/share-md-viewer/load.ts
49416
- var import_node_fs12 = __toESM(require("fs"), 1);
49417
- var import_node_path11 = __toESM(require("path"), 1);
49902
+ var import_node_fs14 = __toESM(require("fs"), 1);
49903
+ var import_node_path13 = __toESM(require("path"), 1);
49418
49904
  var import_node_url2 = require("url");
49419
49905
 
49420
49906
  // src/share-md-viewer/asset-loader.ts
49421
- var import_node_fs11 = __toESM(require("fs"), 1);
49907
+ var import_node_fs13 = __toESM(require("fs"), 1);
49422
49908
  function htmlEscape(s) {
49423
49909
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
49424
49910
  }
@@ -49426,12 +49912,12 @@ function createViewerAssetLoader(opts) {
49426
49912
  let viewerTemplate;
49427
49913
  let errorTemplate;
49428
49914
  try {
49429
- viewerTemplate = import_node_fs11.default.readFileSync(opts.viewerHtmlPath, "utf8");
49915
+ viewerTemplate = import_node_fs13.default.readFileSync(opts.viewerHtmlPath, "utf8");
49430
49916
  } catch (err) {
49431
49917
  throw new Error(`viewer asset not found at ${opts.viewerHtmlPath}: ${err.message}`);
49432
49918
  }
49433
49919
  try {
49434
- errorTemplate = import_node_fs11.default.readFileSync(opts.errorHtmlPath, "utf8");
49920
+ errorTemplate = import_node_fs13.default.readFileSync(opts.errorHtmlPath, "utf8");
49435
49921
  } catch (err) {
49436
49922
  throw new Error(`viewer error asset not found at ${opts.errorHtmlPath}: ${err.message}`);
49437
49923
  }
@@ -49446,29 +49932,29 @@ function createViewerAssetLoader(opts) {
49446
49932
  }
49447
49933
 
49448
49934
  // src/share-md-viewer/load.ts
49449
- var import_meta2 = {};
49935
+ var import_meta3 = {};
49450
49936
  function tryLoadViewerAssets(logger) {
49451
49937
  const candidates = [];
49452
49938
  try {
49453
- const here = import_node_path11.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
49939
+ const here = import_node_path13.default.dirname((0, import_node_url2.fileURLToPath)(import_meta3.url));
49454
49940
  candidates.push(here);
49455
- candidates.push(import_node_path11.default.resolve(here, ".."));
49456
- candidates.push(import_node_path11.default.resolve(here, "..", "..", "dist"));
49941
+ candidates.push(import_node_path13.default.resolve(here, ".."));
49942
+ candidates.push(import_node_path13.default.resolve(here, "..", "..", "dist"));
49457
49943
  } catch {
49458
49944
  }
49459
49945
  if (process.argv[1]) {
49460
49946
  let real = process.argv[1];
49461
49947
  try {
49462
- real = import_node_fs12.default.realpathSync(process.argv[1]);
49948
+ real = import_node_fs14.default.realpathSync(process.argv[1]);
49463
49949
  } catch {
49464
49950
  }
49465
- candidates.push(import_node_path11.default.dirname(real));
49951
+ candidates.push(import_node_path13.default.dirname(real));
49466
49952
  }
49467
49953
  for (const root of candidates) {
49468
- const viewerHtmlPath = import_node_path11.default.join(root, "share-md-viewer.html");
49469
- const errorHtmlPath = import_node_path11.default.join(root, "share-md-viewer-error.html");
49954
+ const viewerHtmlPath = import_node_path13.default.join(root, "share-md-viewer.html");
49955
+ const errorHtmlPath = import_node_path13.default.join(root, "share-md-viewer-error.html");
49470
49956
  try {
49471
- if (import_node_fs12.default.statSync(viewerHtmlPath).isFile() && import_node_fs12.default.statSync(errorHtmlPath).isFile()) {
49957
+ if (import_node_fs14.default.statSync(viewerHtmlPath).isFile() && import_node_fs14.default.statSync(errorHtmlPath).isFile()) {
49472
49958
  logger?.info("share-md-viewer.assets-root.resolved", { root });
49473
49959
  return createViewerAssetLoader({ viewerHtmlPath, errorHtmlPath });
49474
49960
  }
@@ -49483,30 +49969,30 @@ function tryLoadViewerAssets(logger) {
49483
49969
  }
49484
49970
 
49485
49971
  // src/share-ui/load.ts
49486
- var import_node_fs14 = __toESM(require("fs"), 1);
49487
- var import_node_path13 = __toESM(require("path"), 1);
49972
+ var import_node_fs16 = __toESM(require("fs"), 1);
49973
+ var import_node_path15 = __toESM(require("path"), 1);
49488
49974
  var import_node_url3 = require("url");
49489
49975
 
49490
49976
  // src/share-ui/asset-loader.ts
49491
- var import_node_fs13 = __toESM(require("fs"), 1);
49492
- var import_node_path12 = __toESM(require("path"), 1);
49977
+ var import_node_fs15 = __toESM(require("fs"), 1);
49978
+ var import_node_path14 = __toESM(require("path"), 1);
49493
49979
  function createShareUiAssetLoader(opts) {
49494
49980
  let indexHtml;
49495
49981
  try {
49496
- indexHtml = import_node_fs13.default.readFileSync(opts.indexHtmlPath, "utf8");
49982
+ indexHtml = import_node_fs15.default.readFileSync(opts.indexHtmlPath, "utf8");
49497
49983
  } catch (err) {
49498
49984
  throw new Error(`share-ui index.html not found at ${opts.indexHtmlPath}: ${err.message}`);
49499
49985
  }
49500
- const assetsDir = import_node_path12.default.resolve(opts.assetsDir);
49986
+ const assetsDir = import_node_path14.default.resolve(opts.assetsDir);
49501
49987
  return {
49502
49988
  renderIndexHtml() {
49503
49989
  return indexHtml;
49504
49990
  },
49505
49991
  resolveAssetPath(rel) {
49506
- const resolved = import_node_path12.default.resolve(assetsDir, rel);
49507
- if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path12.default.sep)) return null;
49992
+ const resolved = import_node_path14.default.resolve(assetsDir, rel);
49993
+ if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path14.default.sep)) return null;
49508
49994
  try {
49509
- if (import_node_fs13.default.statSync(resolved).isFile()) return resolved;
49995
+ if (import_node_fs15.default.statSync(resolved).isFile()) return resolved;
49510
49996
  } catch {
49511
49997
  }
49512
49998
  return null;
@@ -49515,33 +50001,33 @@ function createShareUiAssetLoader(opts) {
49515
50001
  }
49516
50002
 
49517
50003
  // src/share-ui/load.ts
49518
- var import_meta3 = {};
50004
+ var import_meta4 = {};
49519
50005
  function bundleDirFromArgv(argv1) {
49520
50006
  if (!argv1) return null;
49521
50007
  let real = argv1;
49522
50008
  try {
49523
- real = import_node_fs14.default.realpathSync(argv1);
50009
+ real = import_node_fs16.default.realpathSync(argv1);
49524
50010
  } catch {
49525
50011
  }
49526
- return import_node_path13.default.dirname(real);
50012
+ return import_node_path15.default.dirname(real);
49527
50013
  }
49528
50014
  function tryLoadShareUi(logger) {
49529
50015
  const candidates = [];
49530
50016
  try {
49531
- const here = import_node_path13.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url));
50017
+ const here = import_node_path15.default.dirname((0, import_node_url3.fileURLToPath)(import_meta4.url));
49532
50018
  candidates.push(here);
49533
- candidates.push(import_node_path13.default.resolve(here, ".."));
49534
- candidates.push(import_node_path13.default.resolve(here, "..", "..", "dist"));
50019
+ candidates.push(import_node_path15.default.resolve(here, ".."));
50020
+ candidates.push(import_node_path15.default.resolve(here, "..", "..", "dist"));
49535
50021
  } catch {
49536
50022
  }
49537
50023
  const argvDir = bundleDirFromArgv(process.argv[1]);
49538
50024
  if (argvDir) candidates.push(argvDir);
49539
50025
  for (const root of candidates) {
49540
- const shareUiDir = import_node_path13.default.join(root, "share-ui");
49541
- const indexHtmlPath = import_node_path13.default.join(shareUiDir, "guest.html");
49542
- const assetsDir = import_node_path13.default.join(shareUiDir, "assets");
50026
+ const shareUiDir = import_node_path15.default.join(root, "share-ui");
50027
+ const indexHtmlPath = import_node_path15.default.join(shareUiDir, "guest.html");
50028
+ const assetsDir = import_node_path15.default.join(shareUiDir, "assets");
49543
50029
  try {
49544
- if (import_node_fs14.default.statSync(indexHtmlPath).isFile() && import_node_fs14.default.statSync(assetsDir).isDirectory()) {
50030
+ if (import_node_fs16.default.statSync(indexHtmlPath).isFile() && import_node_fs16.default.statSync(assetsDir).isDirectory()) {
49545
50031
  logger?.info("share-ui.assets-root.resolved", { root: shareUiDir });
49546
50032
  return createShareUiAssetLoader({ indexHtmlPath, assetsDir });
49547
50033
  }
@@ -49624,20 +50110,20 @@ function buildVisitorLogin(deps) {
49624
50110
  }
49625
50111
 
49626
50112
  // src/visitor/visitor-store.ts
49627
- var import_node_fs15 = __toESM(require("fs"), 1);
49628
- var import_node_path14 = __toESM(require("path"), 1);
50113
+ var import_node_fs17 = __toESM(require("fs"), 1);
50114
+ var import_node_path16 = __toESM(require("path"), 1);
49629
50115
  function createVisitorStore(opts) {
49630
- const file = import_node_path14.default.join(opts.dir, "visitors.json");
50116
+ const file = import_node_path16.default.join(opts.dir, "visitors.json");
49631
50117
  const read = () => {
49632
50118
  try {
49633
- return JSON.parse(import_node_fs15.default.readFileSync(file, "utf8"));
50119
+ return JSON.parse(import_node_fs17.default.readFileSync(file, "utf8"));
49634
50120
  } catch {
49635
50121
  return [];
49636
50122
  }
49637
50123
  };
49638
50124
  const write = (rows) => {
49639
- import_node_fs15.default.mkdirSync(opts.dir, { recursive: true });
49640
- import_node_fs15.default.writeFileSync(file, JSON.stringify(rows, null, 2));
50125
+ import_node_fs17.default.mkdirSync(opts.dir, { recursive: true });
50126
+ import_node_fs17.default.writeFileSync(file, JSON.stringify(rows, null, 2));
49641
50127
  };
49642
50128
  return {
49643
50129
  upsert(r) {
@@ -49670,12 +50156,12 @@ function createVisitorStore(opts) {
49670
50156
  init_claude();
49671
50157
 
49672
50158
  // src/tools/codex.ts
49673
- var import_node_child_process6 = require("child_process");
49674
- var import_node_fs18 = __toESM(require("fs"), 1);
50159
+ var import_node_child_process8 = require("child_process");
50160
+ var import_node_fs20 = __toESM(require("fs"), 1);
49675
50161
 
49676
50162
  // src/tools/codex-session.ts
49677
- var import_node_child_process4 = require("child_process");
49678
- var import_node_path16 = __toESM(require("path"), 1);
50163
+ var import_node_child_process6 = require("child_process");
50164
+ var import_node_path18 = __toESM(require("path"), 1);
49679
50165
 
49680
50166
  // src/tools/codex-app-server-client.ts
49681
50167
  var import_node_readline = require("readline");
@@ -50148,16 +50634,16 @@ function turnStartInput(text) {
50148
50634
  }
50149
50635
 
50150
50636
  // src/tools/codex-mcp-config.ts
50151
- var import_node_fs17 = __toESM(require("fs"), 1);
50152
- var import_node_path15 = __toESM(require("path"), 1);
50637
+ var import_node_fs19 = __toESM(require("fs"), 1);
50638
+ var import_node_path17 = __toESM(require("path"), 1);
50153
50639
  function loadCodexMcpServerDefs(args) {
50154
50640
  const out = [];
50155
50641
  const seen = /* @__PURE__ */ new Set();
50156
- const sources = [...args.mcpConfigPaths, import_node_path15.default.join(args.cwd, ".mcp.json")];
50642
+ const sources = [...args.mcpConfigPaths, import_node_path17.default.join(args.cwd, ".mcp.json")];
50157
50643
  for (const file of sources) {
50158
50644
  let parsed;
50159
50645
  try {
50160
- parsed = JSON.parse(import_node_fs17.default.readFileSync(file, "utf8"));
50646
+ parsed = JSON.parse(import_node_fs19.default.readFileSync(file, "utf8"));
50161
50647
  } catch (e) {
50162
50648
  const code = e.code;
50163
50649
  if (code !== "ENOENT") {
@@ -50201,12 +50687,12 @@ function loadCodexMcpServerDefs(args) {
50201
50687
  }
50202
50688
 
50203
50689
  // src/tools/codex-features.ts
50204
- var import_node_child_process3 = require("child_process");
50690
+ var import_node_child_process5 = require("child_process");
50205
50691
  var cachedNetworkProxy;
50206
50692
  function hasNetworkProxyFeature(deps = {}) {
50207
50693
  if (cachedNetworkProxy !== void 0) return cachedNetworkProxy;
50208
50694
  try {
50209
- const out = deps.execOverride ? deps.execOverride() : (0, import_node_child_process3.execFileSync)(process.env.CODEX_BIN ?? "codex", ["features", "list"], {
50695
+ const out = deps.execOverride ? deps.execOverride() : (0, import_node_child_process5.execFileSync)(process.env.CODEX_BIN ?? "codex", ["features", "list"], {
50210
50696
  encoding: "utf8",
50211
50697
  timeout: 3e3
50212
50698
  });
@@ -50221,7 +50707,7 @@ var warming = false;
50221
50707
  function warmCodexFeatureCache() {
50222
50708
  if (cachedNetworkProxy !== void 0 || warming) return;
50223
50709
  warming = true;
50224
- (0, import_node_child_process3.execFile)(
50710
+ (0, import_node_child_process5.execFile)(
50225
50711
  process.env.CODEX_BIN ?? "codex",
50226
50712
  ["features", "list"],
50227
50713
  { encoding: "utf8", timeout: 3e3 },
@@ -50262,7 +50748,7 @@ function createCodexSession(ctx, sink, deps = {}) {
50262
50748
  )
50263
50749
  );
50264
50750
  const env = { ...process.env, ...ctx.env };
50265
- const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0, import_node_child_process4.spawn)(cmd, args, { cwd: ctx.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
50751
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0, import_node_child_process6.spawn)(cmd, args, { cwd: ctx.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
50266
50752
  let threadId = ctx.toolSessionId;
50267
50753
  let turnId;
50268
50754
  const approvalIds = /* @__PURE__ */ new Map();
@@ -50335,7 +50821,7 @@ function createCodexSession(ctx, sink, deps = {}) {
50335
50821
  capabilities: null
50336
50822
  });
50337
50823
  client.notify("initialized", {});
50338
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path16.default.join(ctx.cwd, ".claude", "skills")] }).catch((e) => deps.logger?.warn("codex skills/extraRoots/set failed", { message: e.message }));
50824
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path18.default.join(ctx.cwd, ".claude", "skills")] }).catch((e) => deps.logger?.warn("codex skills/extraRoots/set failed", { message: e.message }));
50339
50825
  if (threadId) {
50340
50826
  await client.request("thread/resume", { threadId, ...threadStartParams(ctx) });
50341
50827
  } else {
@@ -50388,12 +50874,12 @@ function stringValue2(value) {
50388
50874
  }
50389
50875
 
50390
50876
  // src/tools/codex-app-server-query.ts
50391
- var import_node_child_process5 = require("child_process");
50877
+ var import_node_child_process7 = require("child_process");
50392
50878
  var DEFAULT_CODEX_QUERY_TIMEOUT_MS = 8e3;
50393
50879
  async function queryCodexAppServer(cwd, method, params, deps = {}) {
50394
50880
  const cmd = process.env.CODEX_BIN ?? "codex";
50395
50881
  const args = ["app-server", "--listen", "stdio://"];
50396
- const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process5.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
50882
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process7.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
50397
50883
  const client = new CodexAppServerClient(proc, {});
50398
50884
  const timeoutMs = deps.timeoutMs ?? DEFAULT_CODEX_QUERY_TIMEOUT_MS;
50399
50885
  let timer;
@@ -50545,10 +51031,10 @@ function sanitizeCodexModel(model) {
50545
51031
  return model;
50546
51032
  }
50547
51033
  async function probeCodex(env = process.env) {
50548
- if (env.CODEX_BIN && import_node_fs18.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
51034
+ if (env.CODEX_BIN && import_node_fs20.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
50549
51035
  try {
50550
- const out = (0, import_node_child_process6.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
50551
- if (out && import_node_fs18.default.existsSync(out)) return { available: true, path: out };
51036
+ const out = (0, import_node_child_process8.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
51037
+ if (out && import_node_fs20.default.existsSync(out)) return { available: true, path: out };
50552
51038
  } catch {
50553
51039
  }
50554
51040
  return { available: false };
@@ -50615,9 +51101,9 @@ var CodexAdapter = class {
50615
51101
 
50616
51102
  // src/tools/claude-tui.ts
50617
51103
  var import_node_crypto5 = require("crypto");
50618
- var import_node_fs19 = __toESM(require("fs"), 1);
50619
- var import_node_os7 = __toESM(require("os"), 1);
50620
- var import_node_path17 = __toESM(require("path"), 1);
51104
+ var import_node_fs21 = __toESM(require("fs"), 1);
51105
+ var import_node_os9 = __toESM(require("os"), 1);
51106
+ var import_node_path19 = __toESM(require("path"), 1);
50621
51107
  var import_headless = __toESM(require_xterm_headless(), 1);
50622
51108
 
50623
51109
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -51851,10 +52337,10 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
51851
52337
  }
51852
52338
  function jsonlExistsForCtx(ctx) {
51853
52339
  if (!ctx.toolSessionId) return false;
51854
- const home = import_node_os7.default.homedir();
51855
- const file = import_node_path17.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
52340
+ const home = import_node_os9.default.homedir();
52341
+ const file = import_node_path19.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
51856
52342
  try {
51857
- return import_node_fs19.default.statSync(file).isFile();
52343
+ return import_node_fs21.default.statSync(file).isFile();
51858
52344
  } catch {
51859
52345
  return false;
51860
52346
  }
@@ -51931,8 +52417,8 @@ var PersonaDispatchManager = class {
51931
52417
  };
51932
52418
 
51933
52419
  // src/dispatch/store.ts
51934
- var import_promises = __toESM(require("fs/promises"), 1);
51935
- var import_node_path18 = __toESM(require("path"), 1);
52420
+ var import_promises2 = __toESM(require("fs/promises"), 1);
52421
+ var import_node_path20 = __toESM(require("path"), 1);
51936
52422
 
51937
52423
  // src/shift/constants.ts
51938
52424
  var MAX_RUNS_PER_SHIFT = 30;
@@ -51950,7 +52436,7 @@ function createDispatchStore(deps) {
51950
52436
  async function load() {
51951
52437
  let raw;
51952
52438
  try {
51953
- raw = await import_promises.default.readFile(deps.filePath, "utf8");
52439
+ raw = await import_promises2.default.readFile(deps.filePath, "utf8");
51954
52440
  } catch (e) {
51955
52441
  if (e.code === "ENOENT") {
51956
52442
  records = [];
@@ -51970,10 +52456,10 @@ function createDispatchStore(deps) {
51970
52456
  flushTimer = null;
51971
52457
  }
51972
52458
  const content = { version: 1, records };
51973
- await import_promises.default.mkdir(import_node_path18.default.dirname(deps.filePath), { recursive: true });
52459
+ await import_promises2.default.mkdir(import_node_path20.default.dirname(deps.filePath), { recursive: true });
51974
52460
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
51975
- await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
51976
- await import_promises.default.rename(tmp, deps.filePath);
52461
+ await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
52462
+ await import_promises2.default.rename(tmp, deps.filePath);
51977
52463
  }
51978
52464
  function scheduleFlush() {
51979
52465
  if (flushTimer) return;
@@ -52032,10 +52518,10 @@ function createDispatchStore(deps) {
52032
52518
  }
52033
52519
 
52034
52520
  // src/dispatch/mcp-config.ts
52035
- var import_node_fs20 = __toESM(require("fs"), 1);
52036
- var import_node_path19 = __toESM(require("path"), 1);
52521
+ var import_node_fs22 = __toESM(require("fs"), 1);
52522
+ var import_node_path21 = __toESM(require("path"), 1);
52037
52523
  function dispatchMcpConfigPath(dataDir) {
52038
- return import_node_path19.default.join(dataDir, "dispatch.mcp.json");
52524
+ return import_node_path21.default.join(dataDir, "dispatch.mcp.json");
52039
52525
  }
52040
52526
  function writeDispatchMcpConfig(args) {
52041
52527
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -52054,16 +52540,16 @@ function writeDispatchMcpConfig(args) {
52054
52540
  }
52055
52541
  }
52056
52542
  };
52057
- import_node_fs20.default.mkdirSync(args.dataDir, { recursive: true });
52058
- import_node_fs20.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
52543
+ import_node_fs22.default.mkdirSync(args.dataDir, { recursive: true });
52544
+ import_node_fs22.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
52059
52545
  return cfgPath;
52060
52546
  }
52061
52547
 
52062
52548
  // src/ticket/mcp-config.ts
52063
- var import_node_fs21 = __toESM(require("fs"), 1);
52064
- var import_node_path20 = __toESM(require("path"), 1);
52549
+ var import_node_fs23 = __toESM(require("fs"), 1);
52550
+ var import_node_path22 = __toESM(require("path"), 1);
52065
52551
  function ticketMcpConfigPath(dataDir) {
52066
- return import_node_path20.default.join(dataDir, "ticket.mcp.json");
52552
+ return import_node_path22.default.join(dataDir, "ticket.mcp.json");
52067
52553
  }
52068
52554
  function writeTicketMcpConfig(args) {
52069
52555
  const cfgPath = ticketMcpConfigPath(args.dataDir);
@@ -52085,16 +52571,16 @@ function writeTicketMcpConfig(args) {
52085
52571
  }
52086
52572
  }
52087
52573
  };
52088
- import_node_fs21.default.mkdirSync(args.dataDir, { recursive: true });
52089
- import_node_fs21.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
52574
+ import_node_fs23.default.mkdirSync(args.dataDir, { recursive: true });
52575
+ import_node_fs23.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
52090
52576
  return cfgPath;
52091
52577
  }
52092
52578
 
52093
52579
  // src/shift/mcp-config.ts
52094
- var import_node_fs22 = __toESM(require("fs"), 1);
52095
- var import_node_path21 = __toESM(require("path"), 1);
52580
+ var import_node_fs24 = __toESM(require("fs"), 1);
52581
+ var import_node_path23 = __toESM(require("path"), 1);
52096
52582
  function shiftMcpConfigPath(dataDir) {
52097
- return import_node_path21.default.join(dataDir, "shift.mcp.json");
52583
+ return import_node_path23.default.join(dataDir, "shift.mcp.json");
52098
52584
  }
52099
52585
  async function writeShiftMcpConfig(args) {
52100
52586
  const cfgPath = shiftMcpConfigPath(args.dataDir);
@@ -52113,16 +52599,16 @@ async function writeShiftMcpConfig(args) {
52113
52599
  }
52114
52600
  }
52115
52601
  };
52116
- await import_node_fs22.default.promises.mkdir(args.dataDir, { recursive: true });
52117
- await import_node_fs22.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
52602
+ await import_node_fs24.default.promises.mkdir(args.dataDir, { recursive: true });
52603
+ await import_node_fs24.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
52118
52604
  return cfgPath;
52119
52605
  }
52120
52606
 
52121
52607
  // src/inbox/mcp-config.ts
52122
- var import_node_fs23 = __toESM(require("fs"), 1);
52123
- var import_node_path22 = __toESM(require("path"), 1);
52608
+ var import_node_fs25 = __toESM(require("fs"), 1);
52609
+ var import_node_path24 = __toESM(require("path"), 1);
52124
52610
  function inboxMcpConfigPath(dataDir) {
52125
- return import_node_path22.default.join(dataDir, "inbox.mcp.json");
52611
+ return import_node_path24.default.join(dataDir, "inbox.mcp.json");
52126
52612
  }
52127
52613
  async function writeInboxMcpConfig(args) {
52128
52614
  const cfgPath = inboxMcpConfigPath(args.dataDir);
@@ -52141,16 +52627,16 @@ async function writeInboxMcpConfig(args) {
52141
52627
  }
52142
52628
  }
52143
52629
  };
52144
- await import_node_fs23.default.promises.mkdir(args.dataDir, { recursive: true });
52145
- await import_node_fs23.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
52630
+ await import_node_fs25.default.promises.mkdir(args.dataDir, { recursive: true });
52631
+ await import_node_fs25.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
52146
52632
  return cfgPath;
52147
52633
  }
52148
52634
 
52149
52635
  // src/peer-ops/mcp-config.ts
52150
- var import_node_fs24 = __toESM(require("fs"), 1);
52151
- var import_node_path23 = __toESM(require("path"), 1);
52636
+ var import_node_fs26 = __toESM(require("fs"), 1);
52637
+ var import_node_path25 = __toESM(require("path"), 1);
52152
52638
  function peerOpsMcpConfigPath(dataDir) {
52153
- return import_node_path23.default.join(dataDir, "peer-ops.mcp.json");
52639
+ return import_node_path25.default.join(dataDir, "peer-ops.mcp.json");
52154
52640
  }
52155
52641
  function writePeerOpsMcpConfig(args) {
52156
52642
  const cfgPath = peerOpsMcpConfigPath(args.dataDir);
@@ -52167,16 +52653,16 @@ function writePeerOpsMcpConfig(args) {
52167
52653
  }
52168
52654
  }
52169
52655
  };
52170
- import_node_fs24.default.mkdirSync(args.dataDir, { recursive: true });
52171
- import_node_fs24.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
52656
+ import_node_fs26.default.mkdirSync(args.dataDir, { recursive: true });
52657
+ import_node_fs26.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
52172
52658
  return cfgPath;
52173
52659
  }
52174
52660
 
52175
52661
  // src/rpc-tool/mcp-config.ts
52176
- var import_node_fs25 = __toESM(require("fs"), 1);
52177
- var import_node_path24 = __toESM(require("path"), 1);
52662
+ var import_node_fs27 = __toESM(require("fs"), 1);
52663
+ var import_node_path26 = __toESM(require("path"), 1);
52178
52664
  function rpcToolMcpConfigPath(dataDir) {
52179
- return import_node_path24.default.join(dataDir, "rpc-tool.mcp.json");
52665
+ return import_node_path26.default.join(dataDir, "rpc-tool.mcp.json");
52180
52666
  }
52181
52667
  function writeRpcToolMcpConfig(args) {
52182
52668
  const cfgPath = rpcToolMcpConfigPath(args.dataDir);
@@ -52195,18 +52681,18 @@ function writeRpcToolMcpConfig(args) {
52195
52681
  }
52196
52682
  }
52197
52683
  };
52198
- import_node_fs25.default.mkdirSync(args.dataDir, { recursive: true });
52199
- import_node_fs25.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
52684
+ import_node_fs27.default.mkdirSync(args.dataDir, { recursive: true });
52685
+ import_node_fs27.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
52200
52686
  return cfgPath;
52201
52687
  }
52202
52688
 
52203
52689
  // src/dispatch/source-transcript.ts
52204
- var import_node_path25 = __toESM(require("path"), 1);
52690
+ var import_node_path27 = __toESM(require("path"), 1);
52205
52691
  init_claude_history();
52206
52692
  var NO_SOURCE_TRANSCRIPT = "(no transcript yet \u2014 operate from the task description alone)";
52207
52693
  function resolveSourceJsonlPath(sourceFile, home) {
52208
52694
  if (!sourceFile?.toolSessionId) return NO_SOURCE_TRANSCRIPT;
52209
- return import_node_path25.default.join(
52695
+ return import_node_path27.default.join(
52210
52696
  home,
52211
52697
  ".claude",
52212
52698
  "projects",
@@ -52216,8 +52702,8 @@ function resolveSourceJsonlPath(sourceFile, home) {
52216
52702
  }
52217
52703
 
52218
52704
  // src/shift/store.ts
52219
- var import_promises2 = __toESM(require("fs/promises"), 1);
52220
- var import_node_path26 = __toESM(require("path"), 1);
52705
+ var import_promises3 = __toESM(require("fs/promises"), 1);
52706
+ var import_node_path28 = __toESM(require("path"), 1);
52221
52707
  var import_node_crypto6 = require("crypto");
52222
52708
 
52223
52709
  // src/shift/schedule.ts
@@ -52264,7 +52750,7 @@ function createShiftStore(deps) {
52264
52750
  async function load() {
52265
52751
  let raw;
52266
52752
  try {
52267
- raw = await import_promises2.default.readFile(deps.filePath, "utf8");
52753
+ raw = await import_promises3.default.readFile(deps.filePath, "utf8");
52268
52754
  } catch (e) {
52269
52755
  if (e.code === "ENOENT") {
52270
52756
  shifts = [];
@@ -52292,10 +52778,10 @@ function createShiftStore(deps) {
52292
52778
  flushTimer = null;
52293
52779
  }
52294
52780
  const content = { version: 1, shifts };
52295
- await import_promises2.default.mkdir(import_node_path26.default.dirname(deps.filePath), { recursive: true });
52781
+ await import_promises3.default.mkdir(import_node_path28.default.dirname(deps.filePath), { recursive: true });
52296
52782
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
52297
- await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
52298
- await import_promises2.default.rename(tmp, deps.filePath);
52783
+ await import_promises3.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
52784
+ await import_promises3.default.rename(tmp, deps.filePath);
52299
52785
  }
52300
52786
  function scheduleFlush() {
52301
52787
  if (flushTimer) return;
@@ -52375,7 +52861,7 @@ function createShiftStore(deps) {
52375
52861
  }
52376
52862
 
52377
52863
  // src/github/gh.ts
52378
- var import_node_child_process7 = require("child_process");
52864
+ var import_node_child_process9 = require("child_process");
52379
52865
  var GhError = class extends Error {
52380
52866
  constructor(kind, message, stderr) {
52381
52867
  super(message);
@@ -52393,7 +52879,7 @@ function createGhRunner(defaults) {
52393
52879
  return {
52394
52880
  run(args, opts) {
52395
52881
  return new Promise((resolve7, reject) => {
52396
- (0, import_node_child_process7.execFile)(
52882
+ (0, import_node_child_process9.execFile)(
52397
52883
  "gh",
52398
52884
  args,
52399
52885
  { timeout: opts?.timeoutMs ?? baseTimeoutMs, maxBuffer: MAX_BUFFER },
@@ -52960,15 +53446,15 @@ async function refreshTunnelUrlOnStartup(deps) {
52960
53446
  }
52961
53447
 
52962
53448
  // src/lark-bot-connector/binding-store.ts
52963
- var import_node_fs26 = __toESM(require("fs"), 1);
52964
- var import_node_path27 = __toESM(require("path"), 1);
53449
+ var import_node_fs28 = __toESM(require("fs"), 1);
53450
+ var import_node_path29 = __toESM(require("path"), 1);
52965
53451
  function createLarkBotBindingStore(personaRoot) {
52966
- const filePath = (personaId2) => import_node_path27.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
53452
+ const filePath = (personaId2) => import_node_path29.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
52967
53453
  const read = (personaId2) => {
52968
53454
  const file = filePath(personaId2);
52969
- if (!import_node_fs26.default.existsSync(file)) return null;
53455
+ if (!import_node_fs28.default.existsSync(file)) return null;
52970
53456
  try {
52971
- const raw = JSON.parse(import_node_fs26.default.readFileSync(file, "utf8"));
53457
+ const raw = JSON.parse(import_node_fs28.default.readFileSync(file, "utf8"));
52972
53458
  if (typeof raw?.appId !== "string" || raw.appId.length === 0) return null;
52973
53459
  return raw;
52974
53460
  } catch {
@@ -52977,16 +53463,16 @@ function createLarkBotBindingStore(personaRoot) {
52977
53463
  };
52978
53464
  const write = (personaId2, meta) => {
52979
53465
  const file = filePath(personaId2);
52980
- import_node_fs26.default.mkdirSync(import_node_path27.default.dirname(file), { recursive: true });
53466
+ import_node_fs28.default.mkdirSync(import_node_path29.default.dirname(file), { recursive: true });
52981
53467
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
52982
- import_node_fs26.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
52983
- import_node_fs26.default.renameSync(tmp, file);
53468
+ import_node_fs28.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
53469
+ import_node_fs28.default.renameSync(tmp, file);
52984
53470
  };
52985
53471
  return {
52986
53472
  read,
52987
53473
  write,
52988
53474
  remove(personaId2) {
52989
- import_node_fs26.default.rmSync(filePath(personaId2), { force: true });
53475
+ import_node_fs28.default.rmSync(filePath(personaId2), { force: true });
52990
53476
  },
52991
53477
  addRemovedChat(personaId2, chatId) {
52992
53478
  const meta = read(personaId2);
@@ -53140,8 +53626,8 @@ function createLarkBotCloudClient(opts) {
53140
53626
  }
53141
53627
 
53142
53628
  // src/lark-bot-connector/chat-router.ts
53143
- var import_node_fs27 = __toESM(require("fs"), 1);
53144
- var import_node_path28 = __toESM(require("path"), 1);
53629
+ var import_node_fs29 = __toESM(require("fs"), 1);
53630
+ var import_node_path30 = __toESM(require("path"), 1);
53145
53631
  init_protocol();
53146
53632
  var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
53147
53633
  var LOCAL_TURN_RETRIES = 2;
@@ -53206,9 +53692,9 @@ function createLarkChatRouter(deps) {
53206
53692
  continue;
53207
53693
  }
53208
53694
  const dir = deps.mediaRootFor(env.chatId);
53209
- import_node_fs27.default.mkdirSync(dir, { recursive: true });
53210
- const p2 = import_node_path28.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
53211
- import_node_fs27.default.writeFileSync(p2, r.data);
53695
+ import_node_fs29.default.mkdirSync(dir, { recursive: true });
53696
+ const p2 = import_node_path30.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
53697
+ import_node_fs29.default.writeFileSync(p2, r.data);
53212
53698
  lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
53213
53699
  } catch (err) {
53214
53700
  deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
@@ -53229,9 +53715,9 @@ function createLarkChatRouter(deps) {
53229
53715
  continue;
53230
53716
  }
53231
53717
  const dir = deps.mediaRootFor(env.chatId);
53232
- import_node_fs27.default.mkdirSync(dir, { recursive: true });
53233
- const p2 = import_node_path28.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
53234
- import_node_fs27.default.writeFileSync(p2, r.data);
53718
+ import_node_fs29.default.mkdirSync(dir, { recursive: true });
53719
+ const p2 = import_node_path30.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
53720
+ import_node_fs29.default.writeFileSync(p2, r.data);
53235
53721
  lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
53236
53722
  } catch (err) {
53237
53723
  deps.logger?.warn(`larkBot file fetch failed ${f.key}: ${err.message}`);
@@ -54160,7 +54646,7 @@ var CodexHistoryReader = class {
54160
54646
  };
54161
54647
 
54162
54648
  // src/tools/codex-skills.ts
54163
- var import_node_path29 = __toESM(require("path"), 1);
54649
+ var import_node_path31 = __toESM(require("path"), 1);
54164
54650
  function str3(v2) {
54165
54651
  return typeof v2 === "string" ? v2 : void 0;
54166
54652
  }
@@ -54197,14 +54683,14 @@ async function listCodexSkills(cwd, deps = {}) {
54197
54683
  // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
54198
54684
  // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
54199
54685
  beforeRequest: (client) => {
54200
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path29.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
54686
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path31.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
54201
54687
  }
54202
54688
  });
54203
54689
  return mapSkillsListResponse(res);
54204
54690
  }
54205
54691
 
54206
54692
  // src/tools/codex-turn-context.ts
54207
- var import_promises3 = __toESM(require("fs/promises"), 1);
54693
+ var import_promises4 = __toESM(require("fs/promises"), 1);
54208
54694
  function parseTurnContextFromRollout(raw) {
54209
54695
  const lines = raw.split("\n");
54210
54696
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -54239,7 +54725,7 @@ async function readCodexTurnContext(args, deps = {}) {
54239
54725
  );
54240
54726
  const rolloutPath = str4(rec3(res?.thread)?.path);
54241
54727
  if (!rolloutPath) return null;
54242
- return parseTurnContextFromRollout(await import_promises3.default.readFile(rolloutPath, "utf8"));
54728
+ return parseTurnContextFromRollout(await import_promises4.default.readFile(rolloutPath, "utf8"));
54243
54729
  }
54244
54730
  function createCodexResolvedMetaHydrator(deps) {
54245
54731
  const fetchedThreadIds = /* @__PURE__ */ new Set();
@@ -54282,23 +54768,23 @@ function str4(v2) {
54282
54768
  }
54283
54769
 
54284
54770
  // src/workspace/browser.ts
54285
- var import_node_fs28 = __toESM(require("fs"), 1);
54286
- var import_node_os8 = __toESM(require("os"), 1);
54287
- var import_node_path30 = __toESM(require("path"), 1);
54771
+ var import_node_fs30 = __toESM(require("fs"), 1);
54772
+ var import_node_os10 = __toESM(require("os"), 1);
54773
+ var import_node_path32 = __toESM(require("path"), 1);
54288
54774
  init_protocol();
54289
54775
  var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
54290
54776
  function resolveInsideCwd(cwd, subpath) {
54291
- const absCwd = import_node_path30.default.resolve(cwd);
54292
- const joined = import_node_path30.default.resolve(absCwd, subpath ?? ".");
54293
- const rel = import_node_path30.default.relative(absCwd, joined);
54294
- if (rel.startsWith("..") || import_node_path30.default.isAbsolute(rel)) {
54777
+ const absCwd = import_node_path32.default.resolve(cwd);
54778
+ const joined = import_node_path32.default.resolve(absCwd, subpath ?? ".");
54779
+ const rel = import_node_path32.default.relative(absCwd, joined);
54780
+ if (rel.startsWith("..") || import_node_path32.default.isAbsolute(rel)) {
54295
54781
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
54296
54782
  }
54297
54783
  return joined;
54298
54784
  }
54299
54785
  function ensureCwd(cwd) {
54300
54786
  try {
54301
- const stat = import_node_fs28.default.statSync(cwd);
54787
+ const stat = import_node_fs30.default.statSync(cwd);
54302
54788
  if (!stat.isDirectory()) {
54303
54789
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
54304
54790
  }
@@ -54309,10 +54795,10 @@ function ensureCwd(cwd) {
54309
54795
  }
54310
54796
  var WorkspaceBrowser = class {
54311
54797
  list(args) {
54312
- const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
54798
+ const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os10.default.homedir();
54313
54799
  ensureCwd(cwd);
54314
54800
  const full = resolveInsideCwd(cwd, args.path);
54315
- const dirents = import_node_fs28.default.readdirSync(full, { withFileTypes: true });
54801
+ const dirents = import_node_fs30.default.readdirSync(full, { withFileTypes: true });
54316
54802
  const entries = [];
54317
54803
  for (const d of dirents) {
54318
54804
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -54322,7 +54808,7 @@ var WorkspaceBrowser = class {
54322
54808
  mtime: ""
54323
54809
  };
54324
54810
  try {
54325
- const st = import_node_fs28.default.statSync(import_node_path30.default.join(full, d.name));
54811
+ const st = import_node_fs30.default.statSync(import_node_path32.default.join(full, d.name));
54326
54812
  entry.mtime = new Date(st.mtimeMs).toISOString();
54327
54813
  if (d.isFile()) entry.size = st.size;
54328
54814
  } catch {
@@ -54338,14 +54824,14 @@ var WorkspaceBrowser = class {
54338
54824
  read(args) {
54339
54825
  ensureCwd(args.cwd);
54340
54826
  const full = resolveInsideCwd(args.cwd, args.path);
54341
- const st = import_node_fs28.default.statSync(full);
54827
+ const st = import_node_fs30.default.statSync(full);
54342
54828
  if (!st.isFile()) {
54343
54829
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
54344
54830
  }
54345
54831
  if (st.size > MAX_FILE_BYTES2) {
54346
54832
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
54347
54833
  }
54348
- const buf = import_node_fs28.default.readFileSync(full);
54834
+ const buf = import_node_fs30.default.readFileSync(full);
54349
54835
  const isBinary = buf.includes(0);
54350
54836
  if (isBinary) {
54351
54837
  return {
@@ -54367,20 +54853,20 @@ var WorkspaceBrowser = class {
54367
54853
  };
54368
54854
 
54369
54855
  // src/skills/agents-scanner.ts
54370
- var import_node_fs29 = __toESM(require("fs"), 1);
54371
- var import_node_os9 = __toESM(require("os"), 1);
54372
- var import_node_path31 = __toESM(require("path"), 1);
54856
+ var import_node_fs31 = __toESM(require("fs"), 1);
54857
+ var import_node_os11 = __toESM(require("os"), 1);
54858
+ var import_node_path33 = __toESM(require("path"), 1);
54373
54859
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
54374
54860
  function isDirLikeSync2(p2) {
54375
54861
  try {
54376
- return import_node_fs29.default.statSync(p2).isDirectory();
54862
+ return import_node_fs31.default.statSync(p2).isDirectory();
54377
54863
  } catch {
54378
54864
  return false;
54379
54865
  }
54380
54866
  }
54381
54867
  function fileExistsSync(p2) {
54382
54868
  try {
54383
- return import_node_fs29.default.statSync(p2).isFile();
54869
+ return import_node_fs31.default.statSync(p2).isFile();
54384
54870
  } catch {
54385
54871
  return false;
54386
54872
  }
@@ -54388,7 +54874,7 @@ function fileExistsSync(p2) {
54388
54874
  function parseAgentFile(filePath) {
54389
54875
  let content;
54390
54876
  try {
54391
- content = import_node_fs29.default.readFileSync(filePath, "utf8");
54877
+ content = import_node_fs31.default.readFileSync(filePath, "utf8");
54392
54878
  } catch {
54393
54879
  return {};
54394
54880
  }
@@ -54401,16 +54887,16 @@ function parseAgentFile(filePath) {
54401
54887
  function scanAgentsDir(dir, source, seen, out) {
54402
54888
  let entries;
54403
54889
  try {
54404
- entries = import_node_fs29.default.readdirSync(dir, { withFileTypes: true });
54890
+ entries = import_node_fs31.default.readdirSync(dir, { withFileTypes: true });
54405
54891
  } catch {
54406
54892
  return;
54407
54893
  }
54408
54894
  for (const ent of entries) {
54409
54895
  if (!ent.name.endsWith(".md")) continue;
54410
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path31.default.join(dir, ent.name)))) {
54896
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path33.default.join(dir, ent.name)))) {
54411
54897
  continue;
54412
54898
  }
54413
- const filePath = import_node_path31.default.join(dir, ent.name);
54899
+ const filePath = import_node_path33.default.join(dir, ent.name);
54414
54900
  const baseName = ent.name.replace(/\.md$/, "");
54415
54901
  if (seen.has(baseName)) continue;
54416
54902
  seen.add(baseName);
@@ -54428,12 +54914,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
54428
54914
  function walk2(dir, namespaces) {
54429
54915
  let entries;
54430
54916
  try {
54431
- entries = import_node_fs29.default.readdirSync(dir, { withFileTypes: true });
54917
+ entries = import_node_fs31.default.readdirSync(dir, { withFileTypes: true });
54432
54918
  } catch {
54433
54919
  return;
54434
54920
  }
54435
54921
  for (const ent of entries) {
54436
- const childPath = import_node_path31.default.join(dir, ent.name);
54922
+ const childPath = import_node_path33.default.join(dir, ent.name);
54437
54923
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
54438
54924
  walk2(childPath, [...namespaces, ent.name]);
54439
54925
  continue;
@@ -54458,13 +54944,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
54458
54944
  walk2(root, []);
54459
54945
  }
54460
54946
  function readInstalledPlugins2(home) {
54461
- const pluginsDir = import_node_path31.default.join(home, ".claude", "plugins");
54462
- const v2 = import_node_path31.default.join(pluginsDir, "installed_plugins_v2.json");
54463
- const v1 = import_node_path31.default.join(pluginsDir, "installed_plugins.json");
54947
+ const pluginsDir = import_node_path33.default.join(home, ".claude", "plugins");
54948
+ const v2 = import_node_path33.default.join(pluginsDir, "installed_plugins_v2.json");
54949
+ const v1 = import_node_path33.default.join(pluginsDir, "installed_plugins.json");
54464
54950
  let raw = null;
54465
54951
  for (const candidate of [v2, v1]) {
54466
54952
  try {
54467
- raw = import_node_fs29.default.readFileSync(candidate, "utf8");
54953
+ raw = import_node_fs31.default.readFileSync(candidate, "utf8");
54468
54954
  break;
54469
54955
  } catch {
54470
54956
  }
@@ -54489,19 +54975,19 @@ function readInstalledPlugins2(home) {
54489
54975
  return out;
54490
54976
  }
54491
54977
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
54492
- let cur = import_node_path31.default.resolve(startCwd);
54493
- const fsRoot = import_node_path31.default.parse(cur).root;
54978
+ let cur = import_node_path33.default.resolve(startCwd);
54979
+ const fsRoot = import_node_path33.default.parse(cur).root;
54494
54980
  while (true) {
54495
- scanAgentsDir(import_node_path31.default.join(cur, ".claude", "agents"), "project", seen, out);
54981
+ scanAgentsDir(import_node_path33.default.join(cur, ".claude", "agents"), "project", seen, out);
54496
54982
  let hasGit = false;
54497
54983
  try {
54498
- hasGit = import_node_fs29.default.existsSync(import_node_path31.default.join(cur, ".git"));
54984
+ hasGit = import_node_fs31.default.existsSync(import_node_path33.default.join(cur, ".git"));
54499
54985
  } catch {
54500
54986
  }
54501
54987
  if (hasGit) return;
54502
54988
  if (cur === home) return;
54503
54989
  if (cur === fsRoot) return;
54504
- const parent = import_node_path31.default.dirname(cur);
54990
+ const parent = import_node_path33.default.dirname(cur);
54505
54991
  if (parent === cur) return;
54506
54992
  cur = parent;
54507
54993
  }
@@ -54511,7 +54997,7 @@ var AgentsScanner = class {
54511
54997
  extraPluginRoots;
54512
54998
  policyDir;
54513
54999
  constructor(opts = {}) {
54514
- this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os9.default.homedir();
55000
+ this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os11.default.homedir();
54515
55001
  this.extraPluginRoots = opts.extraPluginRoots ?? [];
54516
55002
  if (opts.policyDir !== void 0) {
54517
55003
  this.policyDir = opts.policyDir;
@@ -54536,7 +55022,7 @@ var AgentsScanner = class {
54536
55022
  }
54537
55023
  const fsBlock = [];
54538
55024
  scanAgentsDir(
54539
- import_node_path31.default.join(this.home, ".claude", "agents"),
55025
+ import_node_path33.default.join(this.home, ".claude", "agents"),
54540
55026
  "global",
54541
55027
  seen,
54542
55028
  fsBlock
@@ -54550,7 +55036,7 @@ var AgentsScanner = class {
54550
55036
  ...this.extraPluginRoots
54551
55037
  ];
54552
55038
  for (const { name, root } of plugins) {
54553
- const agentsRoot = import_node_path31.default.join(root, "agents");
55039
+ const agentsRoot = import_node_path33.default.join(root, "agents");
54554
55040
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
54555
55041
  }
54556
55042
  return [...builtinBlock, ...fsBlock];
@@ -54558,28 +55044,28 @@ var AgentsScanner = class {
54558
55044
  };
54559
55045
 
54560
55046
  // src/observer/session-observer.ts
54561
- var import_node_fs31 = __toESM(require("fs"), 1);
54562
- var import_node_os11 = __toESM(require("os"), 1);
54563
- var import_node_path33 = __toESM(require("path"), 1);
55047
+ var import_node_fs33 = __toESM(require("fs"), 1);
55048
+ var import_node_os13 = __toESM(require("os"), 1);
55049
+ var import_node_path35 = __toESM(require("path"), 1);
54564
55050
  init_claude_history();
54565
55051
 
54566
55052
  // src/observer/subagent-meta-observer.ts
54567
- var import_node_fs30 = __toESM(require("fs"), 1);
54568
- var import_node_os10 = __toESM(require("os"), 1);
54569
- var import_node_path32 = __toESM(require("path"), 1);
55053
+ var import_node_fs32 = __toESM(require("fs"), 1);
55054
+ var import_node_os12 = __toESM(require("os"), 1);
55055
+ var import_node_path34 = __toESM(require("path"), 1);
54570
55056
  init_claude_history();
54571
55057
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
54572
55058
  var SubagentMetaObserver = class {
54573
55059
  constructor(opts) {
54574
55060
  this.opts = opts;
54575
- this.home = opts.home ?? import_node_os10.default.homedir();
55061
+ this.home = opts.home ?? import_node_os12.default.homedir();
54576
55062
  }
54577
55063
  opts;
54578
55064
  home;
54579
55065
  watches = /* @__PURE__ */ new Map();
54580
55066
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
54581
55067
  resolveSubagentDir(cwd, toolSessionId) {
54582
- return import_node_path32.default.join(
55068
+ return import_node_path34.default.join(
54583
55069
  this.home,
54584
55070
  ".claude",
54585
55071
  "projects",
@@ -54609,7 +55095,7 @@ var SubagentMetaObserver = class {
54609
55095
  attachWatcher(w2) {
54610
55096
  if (w2.watcher) return;
54611
55097
  try {
54612
- w2.watcher = import_node_fs30.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
55098
+ w2.watcher = import_node_fs32.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
54613
55099
  if (!name) return;
54614
55100
  const m2 = META_RE.exec(String(name));
54615
55101
  if (!m2) return;
@@ -54621,7 +55107,7 @@ var SubagentMetaObserver = class {
54621
55107
  scan(w2) {
54622
55108
  let entries;
54623
55109
  try {
54624
- entries = import_node_fs30.default.readdirSync(w2.dirPath);
55110
+ entries = import_node_fs32.default.readdirSync(w2.dirPath);
54625
55111
  } catch {
54626
55112
  return;
54627
55113
  }
@@ -54635,10 +55121,10 @@ var SubagentMetaObserver = class {
54635
55121
  if (!m2) return;
54636
55122
  const agentId = m2[1];
54637
55123
  if (w2.emitted.has(agentId)) return;
54638
- const file = import_node_path32.default.join(w2.dirPath, name);
55124
+ const file = import_node_path34.default.join(w2.dirPath, name);
54639
55125
  let raw;
54640
55126
  try {
54641
- raw = import_node_fs30.default.readFileSync(file, "utf8");
55127
+ raw = import_node_fs32.default.readFileSync(file, "utf8");
54642
55128
  } catch {
54643
55129
  return;
54644
55130
  }
@@ -54683,7 +55169,7 @@ var SubagentMetaObserver = class {
54683
55169
  var SessionObserver = class {
54684
55170
  constructor(opts) {
54685
55171
  this.opts = opts;
54686
- this.home = opts.home ?? import_node_os11.default.homedir();
55172
+ this.home = opts.home ?? import_node_os13.default.homedir();
54687
55173
  this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
54688
55174
  }
54689
55175
  opts;
@@ -54695,14 +55181,14 @@ var SessionObserver = class {
54695
55181
  metaObserver;
54696
55182
  resolveJsonlPath(cwd, toolSessionId, override) {
54697
55183
  if (override) return override;
54698
- return import_node_path33.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
55184
+ return import_node_path35.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
54699
55185
  }
54700
55186
  start(args) {
54701
55187
  this.stop(args.sessionId);
54702
55188
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
54703
55189
  let size = 0;
54704
55190
  try {
54705
- size = import_node_fs31.default.statSync(filePath).size;
55191
+ size = import_node_fs33.default.statSync(filePath).size;
54706
55192
  } catch {
54707
55193
  }
54708
55194
  const w2 = {
@@ -54715,16 +55201,16 @@ var SessionObserver = class {
54715
55201
  adapter: args.adapter,
54716
55202
  prevIsRejectSentinel: false,
54717
55203
  toolSessionId: args.toolSessionId,
54718
- sawFile: import_node_fs31.default.existsSync(filePath),
55204
+ sawFile: import_node_fs33.default.existsSync(filePath),
54719
55205
  lastRelocateScanMs: 0,
54720
55206
  pendingCwdDerive: false,
54721
55207
  lastDeriveMs: 0
54722
55208
  };
54723
55209
  try {
54724
- import_node_fs31.default.mkdirSync(import_node_path33.default.dirname(filePath), { recursive: true });
55210
+ import_node_fs33.default.mkdirSync(import_node_path35.default.dirname(filePath), { recursive: true });
54725
55211
  } catch {
54726
55212
  }
54727
- w2.watcher = import_node_fs31.default.watch(import_node_path33.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
55213
+ w2.watcher = import_node_fs33.default.watch(import_node_path35.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
54728
55214
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
54729
55215
  this.poll(w2);
54730
55216
  });
@@ -54747,7 +55233,7 @@ var SessionObserver = class {
54747
55233
  // 异常静默吞,不阻塞 watcher 启动
54748
55234
  hydrateMetaTail(w2, maxLines = 200) {
54749
55235
  try {
54750
- const raw = import_node_fs31.default.readFileSync(w2.filePath, "utf8");
55236
+ const raw = import_node_fs33.default.readFileSync(w2.filePath, "utf8");
54751
55237
  if (!raw) return;
54752
55238
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
54753
55239
  if (allLines.length === 0) return;
@@ -54771,7 +55257,7 @@ var SessionObserver = class {
54771
55257
  poll(w2) {
54772
55258
  let size = 0;
54773
55259
  try {
54774
- size = import_node_fs31.default.statSync(w2.filePath).size;
55260
+ size = import_node_fs33.default.statSync(w2.filePath).size;
54775
55261
  } catch {
54776
55262
  if (w2.sawFile) this.maybeRelocate(w2);
54777
55263
  return;
@@ -54782,11 +55268,11 @@ var SessionObserver = class {
54782
55268
  w2.buf = "";
54783
55269
  }
54784
55270
  if (size === w2.lastSize) return;
54785
- const fd = import_node_fs31.default.openSync(w2.filePath, "r");
55271
+ const fd = import_node_fs33.default.openSync(w2.filePath, "r");
54786
55272
  try {
54787
55273
  const len = size - w2.lastSize;
54788
55274
  const buf = Buffer.alloc(len);
54789
- import_node_fs31.default.readSync(fd, buf, 0, len, w2.lastSize);
55275
+ import_node_fs33.default.readSync(fd, buf, 0, len, w2.lastSize);
54790
55276
  w2.lastSize = size;
54791
55277
  w2.buf += buf.toString("utf8");
54792
55278
  let newlineIndex;
@@ -54809,7 +55295,7 @@ var SessionObserver = class {
54809
55295
  }
54810
55296
  }
54811
55297
  } finally {
54812
- import_node_fs31.default.closeSync(fd);
55298
+ import_node_fs33.default.closeSync(fd);
54813
55299
  }
54814
55300
  if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
54815
55301
  }
@@ -54821,7 +55307,7 @@ var SessionObserver = class {
54821
55307
  const now = Date.now();
54822
55308
  if (now - w2.lastRelocateScanMs < 1e3) return;
54823
55309
  w2.lastRelocateScanMs = now;
54824
- const projectsRoot = import_node_path33.default.join(this.home, ".claude", "projects");
55310
+ const projectsRoot = import_node_path35.default.join(this.home, ".claude", "projects");
54825
55311
  const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
54826
55312
  if (!found || found === w2.filePath) return;
54827
55313
  try {
@@ -54830,7 +55316,7 @@ var SessionObserver = class {
54830
55316
  }
54831
55317
  w2.filePath = found;
54832
55318
  try {
54833
- w2.watcher = import_node_fs31.default.watch(import_node_path33.default.dirname(found), { persistent: false }, (_event, changedName) => {
55319
+ w2.watcher = import_node_fs33.default.watch(import_node_path35.default.dirname(found), { persistent: false }, (_event, changedName) => {
54834
55320
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
54835
55321
  this.poll(w2);
54836
55322
  });
@@ -54949,149 +55435,6 @@ function listRegistered() {
54949
55435
  return [...registry.keys()];
54950
55436
  }
54951
55437
 
54952
- // src/tools/title-generator.ts
54953
- var import_node_child_process8 = require("child_process");
54954
- var import_node_fs32 = __toESM(require("fs"), 1);
54955
- var import_node_os12 = __toESM(require("os"), 1);
54956
- var import_node_path34 = __toESM(require("path"), 1);
54957
- var TITLE_GEN_DIR_NAME = "clawd-title-gen";
54958
- var TITLE_MODEL_BY_TOOL = {
54959
- claude: "haiku",
54960
- codex: "gpt-5.4-mini"
54961
- };
54962
- var TITLE_INPUT_MAX_CHARS = 400;
54963
- var DEFAULT_TITLE_GEN_TIMEOUT_MS = 45e3;
54964
- var outFileSeq = 0;
54965
- function buildTitlePrompt(firstMessage) {
54966
- const text = firstMessage.slice(0, TITLE_INPUT_MAX_CHARS);
54967
- return `\u4E3A\u4E0B\u9762\u8FD9\u6761\u7528\u6237\u6D88\u606F\u751F\u6210\u4E00\u4E2A\u7B80\u6D01\u7684\u4F1A\u8BDD\u6807\u9898\uFF1A\u4E0D\u8D85\u8FC7 20 \u4E2A\u5B57\uFF08\u82F1\u6587\u5219\u4E0D\u8D85\u8FC7 6 \u4E2A\u5355\u8BCD\uFF09\uFF0C\u4F7F\u7528\u4E0E\u6D88\u606F\u76F8\u540C\u7684\u8BED\u8A00\uFF0C\u53EA\u6982\u62EC\u6D88\u606F\u4E3B\u9898\u3002
54968
-
54969
- \u7528\u6237\u6D88\u606F\uFF1A
54970
- ${text}`;
54971
- }
54972
- function buildClaudeTitlePrompt(firstMessage) {
54973
- return buildTitlePrompt(firstMessage) + '\n\n\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u683C\u5F0F\uFF1A{"greeting":"\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC","title":"\u4F1A\u8BDD\u6807\u9898"}\uFF0C\u4E0D\u8981\u8F93\u51FA JSON \u4EE5\u5916\u7684\u4EFB\u4F55\u5185\u5BB9\u3002';
54974
- }
54975
- function sanitizeTitle(raw) {
54976
- const line = raw.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
54977
- if (!line) return null;
54978
- const stripped = line.replace(/^["'“”‘’「」《》\[\((]+/, "").replace(/["'“”‘’「」《》\]\))]+$/, "").replace(/[。..!!??]+$/, "").replace(/\s+/g, " ").trim();
54979
- if (!stripped) return null;
54980
- return stripped.slice(0, 60);
54981
- }
54982
- function buildClaudeTitleArgs(prompt) {
54983
- return ["-p", "--model", TITLE_MODEL_BY_TOOL.claude, prompt];
54984
- }
54985
- var CODEX_TITLE_SCHEMA = JSON.stringify({
54986
- type: "object",
54987
- properties: {
54988
- greeting: { type: "string", description: "\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC" },
54989
- title: { type: "string", description: "\u4F1A\u8BDD\u6807\u9898\uFF1A\u53EA\u542B\u6D88\u606F\u4E3B\u9898" }
54990
- },
54991
- required: ["greeting", "title"],
54992
- additionalProperties: false
54993
- });
54994
- function parseTitleJson(raw) {
54995
- const text = raw.trim().replace(/^```[a-zA-Z]*\s*/, "").replace(/```\s*$/, "").trim();
54996
- try {
54997
- const obj = JSON.parse(text);
54998
- if (typeof obj.title === "string") return sanitizeTitle(obj.title);
54999
- } catch {
55000
- }
55001
- return sanitizeTitle(text);
55002
- }
55003
- function buildCodexTitleArgs(prompt, outFile, schemaFile) {
55004
- return [
55005
- "exec",
55006
- "--ephemeral",
55007
- "--skip-git-repo-check",
55008
- "--output-schema",
55009
- schemaFile,
55010
- "-s",
55011
- "read-only",
55012
- "-m",
55013
- TITLE_MODEL_BY_TOOL.codex,
55014
- "--color",
55015
- "never",
55016
- "-o",
55017
- outFile,
55018
- prompt
55019
- ];
55020
- }
55021
- async function generateSessionTitle(tool, firstMessage, deps = {}) {
55022
- if (tool !== "claude" && tool !== "codex") return null;
55023
- const text = firstMessage.trim();
55024
- if (!text) return null;
55025
- const workDir = import_node_path34.default.join(import_node_os12.default.tmpdir(), TITLE_GEN_DIR_NAME);
55026
- try {
55027
- import_node_fs32.default.mkdirSync(workDir, { recursive: true });
55028
- } catch {
55029
- return null;
55030
- }
55031
- const outFile = import_node_path34.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
55032
- const schemaFile = import_node_path34.default.join(workDir, "title-schema.json");
55033
- if (tool === "codex") {
55034
- try {
55035
- import_node_fs32.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA, { flag: "wx" });
55036
- } catch (err) {
55037
- if (err.code !== "EEXIST") return null;
55038
- }
55039
- }
55040
- const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : process.env.CODEX_BIN ?? "codex";
55041
- const args = tool === "claude" ? buildClaudeTitleArgs(buildClaudeTitlePrompt(text)) : buildCodexTitleArgs(buildTitlePrompt(text), outFile, schemaFile);
55042
- const doSpawn = deps.spawnOverride ?? ((c, a, o) => (0, import_node_child_process8.spawn)(c, a, { ...o, stdio: ["ignore", "pipe", "pipe"] }));
55043
- const timeoutMs = deps.timeoutMs ?? DEFAULT_TITLE_GEN_TIMEOUT_MS;
55044
- return await new Promise((resolve7) => {
55045
- let proc;
55046
- try {
55047
- proc = doSpawn(cmd, args, { cwd: workDir });
55048
- } catch (err) {
55049
- deps.logger?.warn("title-gen spawn failed", { tool, message: err.message });
55050
- return resolve7(null);
55051
- }
55052
- let stdout = "";
55053
- let settled = false;
55054
- const finish = (title) => {
55055
- if (settled) return;
55056
- settled = true;
55057
- clearTimeout(timer);
55058
- if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGKILL");
55059
- try {
55060
- import_node_fs32.default.rmSync(outFile, { force: true });
55061
- } catch {
55062
- }
55063
- resolve7(title);
55064
- };
55065
- const timer = setTimeout(() => {
55066
- deps.logger?.warn("title-gen timed out", { tool, timeoutMs });
55067
- finish(null);
55068
- }, timeoutMs);
55069
- proc.stdout?.on("data", (c) => {
55070
- stdout += c.toString();
55071
- });
55072
- proc.stderr?.on("data", () => {
55073
- });
55074
- proc.on("error", (err) => {
55075
- deps.logger?.warn("title-gen proc error", { tool, message: err.message });
55076
- finish(null);
55077
- });
55078
- proc.on("close", (code) => {
55079
- if (code !== 0) {
55080
- deps.logger?.warn("title-gen exited non-zero", { tool, code });
55081
- return finish(null);
55082
- }
55083
- if (tool === "claude") return finish(parseTitleJson(stdout));
55084
- let fileText = "";
55085
- try {
55086
- fileText = import_node_fs32.default.readFileSync(outFile, "utf8");
55087
- } catch {
55088
- return finish(null);
55089
- }
55090
- finish(parseTitleJson(fileText));
55091
- });
55092
- });
55093
- }
55094
-
55095
55438
  // ../node_modules/.pnpm/ws@8.20.0/node_modules/ws/wrapper.mjs
55096
55439
  var import_stream = __toESM(require_stream(), 1);
55097
55440
  var import_extension2 = __toESM(require_extension(), 1);
@@ -55768,8 +56111,8 @@ async function authenticate(token, deps) {
55768
56111
  }
55769
56112
 
55770
56113
  // src/legacy-cleanup.ts
55771
- var fs39 = __toESM(require("fs/promises"), 1);
55772
- var path40 = __toESM(require("path"), 1);
56114
+ var fs40 = __toESM(require("fs/promises"), 1);
56115
+ var path41 = __toESM(require("path"), 1);
55773
56116
  var LEGACY_FILES = [
55774
56117
  "personal-capability.json",
55775
56118
  "received-capabilities.json",
@@ -55778,9 +56121,9 @@ var LEGACY_FILES = [
55778
56121
  async function cleanupLegacyCapabilityFiles(dataDir, logger) {
55779
56122
  const removed = [];
55780
56123
  for (const name of LEGACY_FILES) {
55781
- const p2 = path40.join(dataDir, name);
56124
+ const p2 = path41.join(dataDir, name);
55782
56125
  try {
55783
- await fs39.unlink(p2);
56126
+ await fs40.unlink(p2);
55784
56127
  removed.push(name);
55785
56128
  logger.debug("legacy capability file removed", { file: name });
55786
56129
  } catch (err) {
@@ -55792,13 +56135,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
55792
56135
  }
55793
56136
 
55794
56137
  // src/inbox/inbox-store.ts
55795
- var fs40 = __toESM(require("fs"), 1);
55796
- var path41 = __toESM(require("path"), 1);
56138
+ var fs41 = __toESM(require("fs"), 1);
56139
+ var path42 = __toESM(require("path"), 1);
55797
56140
  var INBOX_SUBDIR = "inbox";
55798
56141
  var InboxStore = class {
55799
56142
  constructor(dataDir) {
55800
56143
  this.dataDir = dataDir;
55801
- fs40.mkdirSync(this.dirPath(), { recursive: true });
56144
+ fs41.mkdirSync(this.dirPath(), { recursive: true });
55802
56145
  }
55803
56146
  dataDir;
55804
56147
  /**
@@ -55810,7 +56153,7 @@ var InboxStore = class {
55810
56153
  const file = this.filePath(peerDeviceId);
55811
56154
  let raw;
55812
56155
  try {
55813
- raw = fs40.readFileSync(file, "utf8");
56156
+ raw = fs41.readFileSync(file, "utf8");
55814
56157
  } catch (err) {
55815
56158
  if (err?.code === "ENOENT") return [];
55816
56159
  return [];
@@ -55826,7 +56169,7 @@ var InboxStore = class {
55826
56169
  const dir = this.dirPath();
55827
56170
  let entries;
55828
56171
  try {
55829
- entries = fs40.readdirSync(dir);
56172
+ entries = fs41.readdirSync(dir);
55830
56173
  } catch (err) {
55831
56174
  if (err?.code === "ENOENT") return [];
55832
56175
  return [];
@@ -55842,9 +56185,9 @@ var InboxStore = class {
55842
56185
  if (existing.some((m2) => m2.id === message.id)) return;
55843
56186
  const file = this.filePath(message.peerDeviceId);
55844
56187
  const line = JSON.stringify(message) + "\n";
55845
- fs40.appendFileSync(file, line, { mode: 384 });
56188
+ fs41.appendFileSync(file, line, { mode: 384 });
55846
56189
  try {
55847
- fs40.chmodSync(file, 384);
56190
+ fs41.chmodSync(file, 384);
55848
56191
  } catch {
55849
56192
  }
55850
56193
  }
@@ -55874,7 +56217,7 @@ var InboxStore = class {
55874
56217
  removeByPeerDeviceId(peerDeviceId) {
55875
56218
  const file = this.filePath(peerDeviceId);
55876
56219
  try {
55877
- fs40.unlinkSync(file);
56220
+ fs41.unlinkSync(file);
55878
56221
  } catch (err) {
55879
56222
  if (err?.code === "ENOENT") return;
55880
56223
  }
@@ -55883,18 +56226,18 @@ var InboxStore = class {
55883
56226
  const file = this.filePath(peerDeviceId);
55884
56227
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
55885
56228
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
55886
- fs40.writeFileSync(tmp, content, { mode: 384 });
55887
- fs40.renameSync(tmp, file);
56229
+ fs41.writeFileSync(tmp, content, { mode: 384 });
56230
+ fs41.renameSync(tmp, file);
55888
56231
  try {
55889
- fs40.chmodSync(file, 384);
56232
+ fs41.chmodSync(file, 384);
55890
56233
  } catch {
55891
56234
  }
55892
56235
  }
55893
56236
  dirPath() {
55894
- return path41.join(this.dataDir, INBOX_SUBDIR);
56237
+ return path42.join(this.dataDir, INBOX_SUBDIR);
55895
56238
  }
55896
56239
  filePath(peerDeviceId) {
55897
- return path41.join(this.dirPath(), `${peerDeviceId}.jsonl`);
56240
+ return path42.join(this.dirPath(), `${peerDeviceId}.jsonl`);
55898
56241
  }
55899
56242
  };
55900
56243
  function parseAllLines(raw) {
@@ -55982,8 +56325,8 @@ var InboxManager = class {
55982
56325
  };
55983
56326
 
55984
56327
  // src/state/contact-store.ts
55985
- var fs41 = __toESM(require("fs"), 1);
55986
- var path42 = __toESM(require("path"), 1);
56328
+ var fs42 = __toESM(require("fs"), 1);
56329
+ var path43 = __toESM(require("path"), 1);
55987
56330
  var FILE_NAME = "contacts.json";
55988
56331
  var ContactStore = class {
55989
56332
  constructor(dataDir) {
@@ -55993,10 +56336,10 @@ var ContactStore = class {
55993
56336
  contacts = /* @__PURE__ */ new Map();
55994
56337
  load() {
55995
56338
  this.contacts.clear();
55996
- const file = path42.join(this.dataDir, FILE_NAME);
56339
+ const file = path43.join(this.dataDir, FILE_NAME);
55997
56340
  let raw;
55998
56341
  try {
55999
- raw = fs41.readFileSync(file, "utf8");
56342
+ raw = fs42.readFileSync(file, "utf8");
56000
56343
  } catch (err) {
56001
56344
  if (err?.code !== "ENOENT") this.renameBak(file);
56002
56345
  return;
@@ -56065,20 +56408,20 @@ var ContactStore = class {
56065
56408
  return true;
56066
56409
  }
56067
56410
  flush() {
56068
- const file = path42.join(this.dataDir, FILE_NAME);
56411
+ const file = path43.join(this.dataDir, FILE_NAME);
56069
56412
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
56070
56413
  const content = JSON.stringify(
56071
56414
  { contacts: Array.from(this.contacts.values()) },
56072
56415
  null,
56073
56416
  2
56074
56417
  );
56075
- fs41.mkdirSync(this.dataDir, { recursive: true });
56076
- fs41.writeFileSync(tmp, content, { mode: 384 });
56077
- fs41.renameSync(tmp, file);
56418
+ fs42.mkdirSync(this.dataDir, { recursive: true });
56419
+ fs42.writeFileSync(tmp, content, { mode: 384 });
56420
+ fs42.renameSync(tmp, file);
56078
56421
  }
56079
56422
  renameBak(file) {
56080
56423
  try {
56081
- fs41.renameSync(file, `${file}.bak`);
56424
+ fs42.renameSync(file, `${file}.bak`);
56082
56425
  } catch {
56083
56426
  }
56084
56427
  }
@@ -56186,61 +56529,61 @@ async function connectRemote(args) {
56186
56529
  }
56187
56530
 
56188
56531
  // src/migrations/2026-05-20-flatten-sessions.ts
56189
- var fs42 = __toESM(require("fs"), 1);
56190
- var path43 = __toESM(require("path"), 1);
56532
+ var fs43 = __toESM(require("fs"), 1);
56533
+ var path44 = __toESM(require("path"), 1);
56191
56534
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
56192
56535
  function migrateFlattenSessions(opts) {
56193
56536
  const dataDir = opts.dataDir;
56194
56537
  const now = opts.now ?? Date.now;
56195
- const sessionsDir = path43.join(dataDir, "sessions");
56196
- const flagPath = path43.join(sessionsDir, MIGRATION_FLAG_NAME);
56538
+ const sessionsDir = path44.join(dataDir, "sessions");
56539
+ const flagPath = path44.join(sessionsDir, MIGRATION_FLAG_NAME);
56197
56540
  if (existsSync3(flagPath)) {
56198
56541
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
56199
56542
  }
56200
56543
  let movedBare = 0;
56201
56544
  let movedVmOwner = 0;
56202
56545
  let archivedListener = 0;
56203
- const defaultDir = path43.join(sessionsDir, "default");
56546
+ const defaultDir = path44.join(sessionsDir, "default");
56204
56547
  if (existsSync3(defaultDir)) {
56205
56548
  for (const entry of readdirSafe(defaultDir)) {
56206
56549
  if (!entry.endsWith(".json")) continue;
56207
- const src = path43.join(defaultDir, entry);
56208
- const dst = path43.join(sessionsDir, entry);
56209
- fs42.renameSync(src, dst);
56550
+ const src = path44.join(defaultDir, entry);
56551
+ const dst = path44.join(sessionsDir, entry);
56552
+ fs43.renameSync(src, dst);
56210
56553
  movedBare += 1;
56211
56554
  }
56212
56555
  rmdirIfEmpty(defaultDir);
56213
56556
  }
56214
56557
  for (const pid of readdirSafe(sessionsDir)) {
56215
- const personaDir = path43.join(sessionsDir, pid);
56216
- if (!isDir(personaDir)) continue;
56558
+ const personaDir = path44.join(sessionsDir, pid);
56559
+ if (!isDir2(personaDir)) continue;
56217
56560
  if (pid === "default") continue;
56218
- const ownerSrc = path43.join(personaDir, "owner");
56219
- if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
56220
- const ownerDst = path43.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
56221
- fs42.mkdirSync(ownerDst, { recursive: true });
56561
+ const ownerSrc = path44.join(personaDir, "owner");
56562
+ if (existsSync3(ownerSrc) && isDir2(ownerSrc)) {
56563
+ const ownerDst = path44.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
56564
+ fs43.mkdirSync(ownerDst, { recursive: true });
56222
56565
  for (const file of readdirSafe(ownerSrc)) {
56223
56566
  if (!file.endsWith(".json")) continue;
56224
- fs42.renameSync(path43.join(ownerSrc, file), path43.join(ownerDst, file));
56567
+ fs43.renameSync(path44.join(ownerSrc, file), path44.join(ownerDst, file));
56225
56568
  movedVmOwner += 1;
56226
56569
  }
56227
56570
  rmdirIfEmpty(ownerSrc);
56228
56571
  }
56229
- const listenerSrc = path43.join(personaDir, "listener");
56230
- if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
56231
- const archiveDst = path43.join(dataDir, ".legacy", `listener-${pid}`);
56232
- fs42.mkdirSync(archiveDst, { recursive: true });
56572
+ const listenerSrc = path44.join(personaDir, "listener");
56573
+ if (existsSync3(listenerSrc) && isDir2(listenerSrc)) {
56574
+ const archiveDst = path44.join(dataDir, ".legacy", `listener-${pid}`);
56575
+ fs43.mkdirSync(archiveDst, { recursive: true });
56233
56576
  for (const file of readdirSafe(listenerSrc)) {
56234
56577
  if (!file.endsWith(".json")) continue;
56235
- fs42.renameSync(path43.join(listenerSrc, file), path43.join(archiveDst, file));
56578
+ fs43.renameSync(path44.join(listenerSrc, file), path44.join(archiveDst, file));
56236
56579
  archivedListener += 1;
56237
56580
  }
56238
56581
  rmdirIfEmpty(listenerSrc);
56239
56582
  }
56240
56583
  rmdirIfEmpty(personaDir);
56241
56584
  }
56242
- fs42.mkdirSync(sessionsDir, { recursive: true });
56243
- fs42.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
56585
+ fs43.mkdirSync(sessionsDir, { recursive: true });
56586
+ fs43.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
56244
56587
  return {
56245
56588
  skipped: false,
56246
56589
  flagWritten: true,
@@ -56251,39 +56594,39 @@ function migrateFlattenSessions(opts) {
56251
56594
  }
56252
56595
  function existsSync3(p2) {
56253
56596
  try {
56254
- fs42.statSync(p2);
56597
+ fs43.statSync(p2);
56255
56598
  return true;
56256
56599
  } catch {
56257
56600
  return false;
56258
56601
  }
56259
56602
  }
56260
- function isDir(p2) {
56603
+ function isDir2(p2) {
56261
56604
  try {
56262
- return fs42.statSync(p2).isDirectory();
56605
+ return fs43.statSync(p2).isDirectory();
56263
56606
  } catch {
56264
56607
  return false;
56265
56608
  }
56266
56609
  }
56267
56610
  function readdirSafe(p2) {
56268
56611
  try {
56269
- return fs42.readdirSync(p2);
56612
+ return fs43.readdirSync(p2);
56270
56613
  } catch {
56271
56614
  return [];
56272
56615
  }
56273
56616
  }
56274
56617
  function rmdirIfEmpty(p2) {
56275
56618
  try {
56276
- fs42.rmdirSync(p2);
56619
+ fs43.rmdirSync(p2);
56277
56620
  } catch {
56278
56621
  }
56279
56622
  }
56280
56623
 
56281
56624
  // src/transport/http-router.ts
56282
- var import_node_fs34 = __toESM(require("fs"), 1);
56283
- var import_node_path38 = __toESM(require("path"), 1);
56625
+ var import_node_fs35 = __toESM(require("fs"), 1);
56626
+ var import_node_path39 = __toESM(require("path"), 1);
56284
56627
 
56285
56628
  // src/attachment/mime.ts
56286
- var import_node_path35 = __toESM(require("path"), 1);
56629
+ var import_node_path36 = __toESM(require("path"), 1);
56287
56630
  var TEXT_PLAIN = "text/plain; charset=utf-8";
56288
56631
  var EXT_TO_NATIVE_MIME = {
56289
56632
  // 图片
@@ -56390,7 +56733,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
56390
56733
  ".mk"
56391
56734
  ]);
56392
56735
  function lookupMime(filePathOrName) {
56393
- const ext = import_node_path35.default.extname(filePathOrName).toLowerCase();
56736
+ const ext = import_node_path36.default.extname(filePathOrName).toLowerCase();
56394
56737
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
56395
56738
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
56396
56739
  return "application/octet-stream";
@@ -56460,10 +56803,10 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
56460
56803
  }
56461
56804
 
56462
56805
  // src/attachment/upload.ts
56463
- var import_node_fs33 = __toESM(require("fs"), 1);
56464
- var import_node_path36 = __toESM(require("path"), 1);
56806
+ var import_node_fs34 = __toESM(require("fs"), 1);
56807
+ var import_node_path37 = __toESM(require("path"), 1);
56465
56808
  var import_node_crypto9 = __toESM(require("crypto"), 1);
56466
- var import_promises4 = require("stream/promises");
56809
+ var import_promises5 = require("stream/promises");
56467
56810
  var UploadError = class extends Error {
56468
56811
  constructor(code, message) {
56469
56812
  super(message);
@@ -56473,27 +56816,27 @@ var UploadError = class extends Error {
56473
56816
  code;
56474
56817
  };
56475
56818
  function assertValidFileName(fileName) {
56476
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path36.default.basename(fileName)) {
56819
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path37.default.basename(fileName)) {
56477
56820
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
56478
56821
  }
56479
56822
  }
56480
56823
  var HASH_PREFIX_LEN = 16;
56481
56824
  async function writeUploadedAttachment(args) {
56482
56825
  assertValidFileName(args.fileName);
56483
- const attachmentsRoot = import_node_path36.default.join(args.baseDir, ".attachments");
56826
+ const attachmentsRoot = import_node_path37.default.join(args.baseDir, ".attachments");
56484
56827
  try {
56485
- import_node_fs33.default.mkdirSync(attachmentsRoot, { recursive: true });
56828
+ import_node_fs34.default.mkdirSync(attachmentsRoot, { recursive: true });
56486
56829
  } catch (err) {
56487
56830
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
56488
56831
  }
56489
56832
  const hasher = import_node_crypto9.default.createHash("sha256");
56490
56833
  let actualSize = 0;
56491
- const tmpPath = import_node_path36.default.join(
56834
+ const tmpPath = import_node_path37.default.join(
56492
56835
  attachmentsRoot,
56493
56836
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto9.default.randomBytes(4).toString("hex")}`
56494
56837
  );
56495
56838
  try {
56496
- await (0, import_promises4.pipeline)(
56839
+ await (0, import_promises5.pipeline)(
56497
56840
  args.body,
56498
56841
  async function* (source) {
56499
56842
  for await (const chunk of source) {
@@ -56503,18 +56846,18 @@ async function writeUploadedAttachment(args) {
56503
56846
  yield buf;
56504
56847
  }
56505
56848
  },
56506
- import_node_fs33.default.createWriteStream(tmpPath, { mode: 384 })
56849
+ import_node_fs34.default.createWriteStream(tmpPath, { mode: 384 })
56507
56850
  );
56508
56851
  } catch (err) {
56509
56852
  try {
56510
- import_node_fs33.default.unlinkSync(tmpPath);
56853
+ import_node_fs34.default.unlinkSync(tmpPath);
56511
56854
  } catch {
56512
56855
  }
56513
56856
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
56514
56857
  }
56515
56858
  if (actualSize !== args.contentLength) {
56516
56859
  try {
56517
- import_node_fs33.default.unlinkSync(tmpPath);
56860
+ import_node_fs34.default.unlinkSync(tmpPath);
56518
56861
  } catch {
56519
56862
  }
56520
56863
  throw new UploadError(
@@ -56523,34 +56866,34 @@ async function writeUploadedAttachment(args) {
56523
56866
  );
56524
56867
  }
56525
56868
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
56526
- const hashDir = import_node_path36.default.join(attachmentsRoot, attachmentId);
56869
+ const hashDir = import_node_path37.default.join(attachmentsRoot, attachmentId);
56527
56870
  let finalFileName;
56528
56871
  let hashDirExists = false;
56529
56872
  try {
56530
- hashDirExists = import_node_fs33.default.statSync(hashDir).isDirectory();
56873
+ hashDirExists = import_node_fs34.default.statSync(hashDir).isDirectory();
56531
56874
  } catch {
56532
56875
  }
56533
56876
  if (hashDirExists) {
56534
- const existing = import_node_fs33.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
56877
+ const existing = import_node_fs34.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
56535
56878
  finalFileName = existing[0] ?? args.fileName;
56536
56879
  try {
56537
- import_node_fs33.default.unlinkSync(tmpPath);
56880
+ import_node_fs34.default.unlinkSync(tmpPath);
56538
56881
  } catch {
56539
56882
  }
56540
56883
  } else {
56541
56884
  try {
56542
- import_node_fs33.default.mkdirSync(hashDir, { recursive: true });
56885
+ import_node_fs34.default.mkdirSync(hashDir, { recursive: true });
56543
56886
  finalFileName = args.fileName;
56544
- import_node_fs33.default.renameSync(tmpPath, import_node_path36.default.join(hashDir, finalFileName));
56887
+ import_node_fs34.default.renameSync(tmpPath, import_node_path37.default.join(hashDir, finalFileName));
56545
56888
  } catch (err) {
56546
56889
  try {
56547
- import_node_fs33.default.unlinkSync(tmpPath);
56890
+ import_node_fs34.default.unlinkSync(tmpPath);
56548
56891
  } catch {
56549
56892
  }
56550
56893
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
56551
56894
  }
56552
56895
  }
56553
- const absPath = import_node_path36.default.join(hashDir, finalFileName);
56896
+ const absPath = import_node_path37.default.join(hashDir, finalFileName);
56554
56897
  const relPath = absPath;
56555
56898
  args.groupFileStore.upsert(args.scope, args.sessionId, {
56556
56899
  relPath: absPath,
@@ -56564,9 +56907,9 @@ async function writeUploadedAttachment(args) {
56564
56907
  }
56565
56908
 
56566
56909
  // src/extension/import.ts
56567
- var import_promises5 = __toESM(require("fs/promises"), 1);
56568
- var import_node_path37 = __toESM(require("path"), 1);
56569
- var import_node_os13 = __toESM(require("os"), 1);
56910
+ var import_promises6 = __toESM(require("fs/promises"), 1);
56911
+ var import_node_path38 = __toESM(require("path"), 1);
56912
+ var import_node_os14 = __toESM(require("os"), 1);
56570
56913
  var import_jszip = __toESM(require_lib3(), 1);
56571
56914
  var ImportError = class extends Error {
56572
56915
  constructor(code, message) {
@@ -56583,7 +56926,7 @@ async function importZip(buf, root) {
56583
56926
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56584
56927
  }
56585
56928
  for (const name of Object.keys(zip.files)) {
56586
- if (name.includes("..") || name.startsWith("/") || import_node_path37.default.isAbsolute(name)) {
56929
+ if (name.includes("..") || name.startsWith("/") || import_node_path38.default.isAbsolute(name)) {
56587
56930
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
56588
56931
  }
56589
56932
  }
@@ -56616,33 +56959,33 @@ async function importZip(buf, root) {
56616
56959
  );
56617
56960
  }
56618
56961
  }
56619
- const destDir = import_node_path37.default.join(root, manifest.id);
56962
+ const destDir = import_node_path38.default.join(root, manifest.id);
56620
56963
  let destExists = false;
56621
56964
  try {
56622
- await import_promises5.default.access(destDir);
56965
+ await import_promises6.default.access(destDir);
56623
56966
  destExists = true;
56624
56967
  } catch {
56625
56968
  }
56626
56969
  if (destExists) {
56627
56970
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
56628
56971
  }
56629
- const stage = await import_promises5.default.mkdtemp(import_node_path37.default.join(import_node_os13.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
56972
+ const stage = await import_promises6.default.mkdtemp(import_node_path38.default.join(import_node_os14.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
56630
56973
  try {
56631
56974
  for (const [name, entry] of Object.entries(zip.files)) {
56632
- const dest = import_node_path37.default.join(stage, name);
56975
+ const dest = import_node_path38.default.join(stage, name);
56633
56976
  if (entry.dir) {
56634
- await import_promises5.default.mkdir(dest, { recursive: true });
56977
+ await import_promises6.default.mkdir(dest, { recursive: true });
56635
56978
  continue;
56636
56979
  }
56637
- await import_promises5.default.mkdir(import_node_path37.default.dirname(dest), { recursive: true });
56980
+ await import_promises6.default.mkdir(import_node_path38.default.dirname(dest), { recursive: true });
56638
56981
  const content = await entry.async("nodebuffer");
56639
- await import_promises5.default.writeFile(dest, content);
56982
+ await import_promises6.default.writeFile(dest, content);
56640
56983
  }
56641
- await import_promises5.default.mkdir(root, { recursive: true });
56642
- await import_promises5.default.rename(stage, destDir);
56984
+ await import_promises6.default.mkdir(root, { recursive: true });
56985
+ await import_promises6.default.rename(stage, destDir);
56643
56986
  return { extId: manifest.id };
56644
56987
  } catch (e) {
56645
- await import_promises5.default.rm(stage, { recursive: true, force: true }).catch(() => {
56988
+ await import_promises6.default.rm(stage, { recursive: true, force: true }).catch(() => {
56646
56989
  });
56647
56990
  throw e;
56648
56991
  }
@@ -56664,7 +57007,7 @@ var SHARE_UI_ASSET_MIME = {
56664
57007
  ".wasm": "application/wasm"
56665
57008
  };
56666
57009
  function shareUiAssetMime(filePath) {
56667
- const ext = import_node_path38.default.extname(filePath).toLowerCase();
57010
+ const ext = import_node_path39.default.extname(filePath).toLowerCase();
56668
57011
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
56669
57012
  }
56670
57013
  var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
@@ -56763,7 +57106,7 @@ function isValidUploadFileName(fileName) {
56763
57106
  if (fileName === "." || fileName === "..") return false;
56764
57107
  if (fileName.startsWith(".")) return false;
56765
57108
  if (fileName.includes("/") || fileName.includes("\\")) return false;
56766
- return fileName === import_node_path38.default.basename(fileName);
57109
+ return fileName === import_node_path39.default.basename(fileName);
56767
57110
  }
56768
57111
  function createHttpRouter(deps) {
56769
57112
  return async (req, res) => {
@@ -56851,7 +57194,7 @@ function createHttpRouter(deps) {
56851
57194
  }
56852
57195
  let buf;
56853
57196
  try {
56854
- buf = await import_node_fs34.default.promises.readFile(abs);
57197
+ buf = await import_node_fs35.default.promises.readFile(abs);
56855
57198
  } catch {
56856
57199
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
56857
57200
  return true;
@@ -56999,7 +57342,7 @@ function createHttpRouter(deps) {
56999
57342
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
57000
57343
  return true;
57001
57344
  }
57002
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path38.default.basename(r.absPath)));
57345
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path39.default.basename(r.absPath)));
57003
57346
  return true;
57004
57347
  }
57005
57348
  const ctx = deps.authResolver.resolveFromHeader(
@@ -57120,7 +57463,7 @@ function createHttpRouter(deps) {
57120
57463
  return true;
57121
57464
  }
57122
57465
  let absPath;
57123
- if (import_node_path38.default.isAbsolute(pathParam)) {
57466
+ if (import_node_path39.default.isAbsolute(pathParam)) {
57124
57467
  absPath = pathParam;
57125
57468
  } else if (deps.sessionStore) {
57126
57469
  const file = deps.sessionStore.read(sid);
@@ -57128,7 +57471,7 @@ function createHttpRouter(deps) {
57128
57471
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
57129
57472
  return true;
57130
57473
  }
57131
- absPath = import_node_path38.default.join(file.cwd, pathParam);
57474
+ absPath = import_node_path39.default.join(file.cwd, pathParam);
57132
57475
  } else {
57133
57476
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
57134
57477
  return true;
@@ -57215,7 +57558,7 @@ function withCtx(ctx, body) {
57215
57558
  function streamFile(res, absPath, logger) {
57216
57559
  let stat;
57217
57560
  try {
57218
- stat = import_node_fs34.default.statSync(absPath);
57561
+ stat = import_node_fs35.default.statSync(absPath);
57219
57562
  } catch (err) {
57220
57563
  const code = err?.code;
57221
57564
  if (code === "ENOENT") {
@@ -57230,7 +57573,7 @@ function streamFile(res, absPath, logger) {
57230
57573
  return;
57231
57574
  }
57232
57575
  const mime = lookupMime(absPath);
57233
- const basename2 = import_node_path38.default.basename(absPath);
57576
+ const basename2 = import_node_path39.default.basename(absPath);
57234
57577
  res.writeHead(200, {
57235
57578
  "Content-Type": mime,
57236
57579
  "Content-Length": String(stat.size),
@@ -57238,7 +57581,7 @@ function streamFile(res, absPath, logger) {
57238
57581
  // 防止浏览器把任意 mime 当 html 渲染
57239
57582
  "X-Content-Type-Options": "nosniff"
57240
57583
  });
57241
- const stream = import_node_fs34.default.createReadStream(absPath);
57584
+ const stream = import_node_fs35.default.createReadStream(absPath);
57242
57585
  stream.on("error", (err) => {
57243
57586
  logger?.warn("streamFile read error", { absPath, err: err.message });
57244
57587
  res.destroy();
@@ -57247,8 +57590,8 @@ function streamFile(res, absPath, logger) {
57247
57590
  }
57248
57591
 
57249
57592
  // src/attachment/gc.ts
57250
- var import_node_fs35 = __toESM(require("fs"), 1);
57251
- var import_node_path39 = __toESM(require("path"), 1);
57593
+ var import_node_fs36 = __toESM(require("fs"), 1);
57594
+ var import_node_path40 = __toESM(require("path"), 1);
57252
57595
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
57253
57596
  function runAttachmentGc(args) {
57254
57597
  const now = (args.now ?? Date.now)();
@@ -57257,12 +57600,12 @@ function runAttachmentGc(args) {
57257
57600
  for (const { scope, sessionId } of args.sessionScopes) {
57258
57601
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
57259
57602
  if (entry.stale) continue;
57260
- if (import_node_path39.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
57603
+ if (import_node_path40.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
57261
57604
  }
57262
57605
  }
57263
57606
  const visited = /* @__PURE__ */ new Set();
57264
57607
  for (const { scope, sessionId } of args.sessionScopes) {
57265
- const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path39.default.join(
57608
+ const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path40.default.join(
57266
57609
  args.dataDir,
57267
57610
  "sessions",
57268
57611
  ...scopeSubPath(scope).map(safeFileName),
@@ -57275,28 +57618,28 @@ function runAttachmentGc(args) {
57275
57618
  return true;
57276
57619
  });
57277
57620
  for (const rootDir of roots) {
57278
- const attRoot = import_node_path39.default.join(rootDir, ".attachments");
57621
+ const attRoot = import_node_path40.default.join(rootDir, ".attachments");
57279
57622
  let hashDirs;
57280
57623
  try {
57281
- hashDirs = import_node_fs35.default.readdirSync(attRoot);
57624
+ hashDirs = import_node_fs36.default.readdirSync(attRoot);
57282
57625
  } catch (err) {
57283
57626
  if (err.code === "ENOENT") continue;
57284
57627
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
57285
57628
  continue;
57286
57629
  }
57287
57630
  for (const hashDir of hashDirs) {
57288
- const hashDirAbs = import_node_path39.default.join(attRoot, hashDir);
57631
+ const hashDirAbs = import_node_path40.default.join(attRoot, hashDir);
57289
57632
  let files;
57290
57633
  try {
57291
- files = import_node_fs35.default.readdirSync(hashDirAbs);
57634
+ files = import_node_fs36.default.readdirSync(hashDirAbs);
57292
57635
  } catch {
57293
57636
  continue;
57294
57637
  }
57295
57638
  for (const name of files) {
57296
- const file = import_node_path39.default.join(hashDirAbs, name);
57639
+ const file = import_node_path40.default.join(hashDirAbs, name);
57297
57640
  let stat;
57298
57641
  try {
57299
- stat = import_node_fs35.default.statSync(file);
57642
+ stat = import_node_fs36.default.statSync(file);
57300
57643
  } catch {
57301
57644
  continue;
57302
57645
  }
@@ -57305,18 +57648,18 @@ function runAttachmentGc(args) {
57305
57648
  if (age < ttlMs) continue;
57306
57649
  if (liveAbs.has(file)) continue;
57307
57650
  try {
57308
- import_node_fs35.default.unlinkSync(file);
57651
+ import_node_fs36.default.unlinkSync(file);
57309
57652
  } catch (err) {
57310
57653
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
57311
57654
  }
57312
57655
  }
57313
57656
  try {
57314
- if (import_node_fs35.default.readdirSync(hashDirAbs).length === 0) import_node_fs35.default.rmdirSync(hashDirAbs);
57657
+ if (import_node_fs36.default.readdirSync(hashDirAbs).length === 0) import_node_fs36.default.rmdirSync(hashDirAbs);
57315
57658
  } catch {
57316
57659
  }
57317
57660
  }
57318
57661
  try {
57319
- if (import_node_fs35.default.readdirSync(attRoot).length === 0) import_node_fs35.default.rmdirSync(attRoot);
57662
+ if (import_node_fs36.default.readdirSync(attRoot).length === 0) import_node_fs36.default.rmdirSync(attRoot);
57320
57663
  } catch {
57321
57664
  }
57322
57665
  }
@@ -57324,8 +57667,8 @@ function runAttachmentGc(args) {
57324
57667
  }
57325
57668
 
57326
57669
  // src/attachment/group.ts
57327
- var import_node_fs36 = __toESM(require("fs"), 1);
57328
- var import_node_path40 = __toESM(require("path"), 1);
57670
+ var import_node_fs37 = __toESM(require("fs"), 1);
57671
+ var import_node_path41 = __toESM(require("path"), 1);
57329
57672
  var import_node_crypto10 = __toESM(require("crypto"), 1);
57330
57673
  init_protocol();
57331
57674
  var GroupFileStore = class {
@@ -57337,11 +57680,11 @@ var GroupFileStore = class {
57337
57680
  this.logger = opts.logger;
57338
57681
  }
57339
57682
  rootForScope(scope) {
57340
- return import_node_path40.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
57683
+ return import_node_path41.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
57341
57684
  }
57342
57685
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
57343
57686
  filePath(scope, sessionId) {
57344
- return import_node_path40.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
57687
+ return import_node_path41.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
57345
57688
  }
57346
57689
  cacheKey(scope, sessionId) {
57347
57690
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -57350,7 +57693,7 @@ var GroupFileStore = class {
57350
57693
  readFile(scope, sessionId) {
57351
57694
  const file = this.filePath(scope, sessionId);
57352
57695
  try {
57353
- const raw = import_node_fs36.default.readFileSync(file, "utf8");
57696
+ const raw = import_node_fs37.default.readFileSync(file, "utf8");
57354
57697
  const parsed = JSON.parse(raw);
57355
57698
  if (!Array.isArray(parsed)) {
57356
57699
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -57376,10 +57719,10 @@ var GroupFileStore = class {
57376
57719
  }
57377
57720
  writeFile(scope, sessionId, entries) {
57378
57721
  const file = this.filePath(scope, sessionId);
57379
- import_node_fs36.default.mkdirSync(import_node_path40.default.dirname(file), { recursive: true });
57722
+ import_node_fs37.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
57380
57723
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
57381
- import_node_fs36.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
57382
- import_node_fs36.default.renameSync(tmp, file);
57724
+ import_node_fs37.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
57725
+ import_node_fs37.default.renameSync(tmp, file);
57383
57726
  }
57384
57727
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
57385
57728
  list(scope, sessionId) {
@@ -57465,10 +57808,10 @@ var GroupFileStore = class {
57465
57808
  };
57466
57809
 
57467
57810
  // src/discovery/state-file.ts
57468
- var import_node_fs37 = __toESM(require("fs"), 1);
57469
- var import_node_path41 = __toESM(require("path"), 1);
57811
+ var import_node_fs38 = __toESM(require("fs"), 1);
57812
+ var import_node_path42 = __toESM(require("path"), 1);
57470
57813
  function defaultStateFilePath(dataDir) {
57471
- return import_node_path41.default.join(dataDir, "state.json");
57814
+ return import_node_path42.default.join(dataDir, "state.json");
57472
57815
  }
57473
57816
  function isPidAlive(pid) {
57474
57817
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -57490,7 +57833,7 @@ var StateFileManager = class {
57490
57833
  }
57491
57834
  read() {
57492
57835
  try {
57493
- const raw = import_node_fs37.default.readFileSync(this.file, "utf8");
57836
+ const raw = import_node_fs38.default.readFileSync(this.file, "utf8");
57494
57837
  const parsed = JSON.parse(raw);
57495
57838
  return parsed;
57496
57839
  } catch {
@@ -57504,20 +57847,20 @@ var StateFileManager = class {
57504
57847
  return { status: "stale", existing };
57505
57848
  }
57506
57849
  write(state) {
57507
- import_node_fs37.default.mkdirSync(import_node_path41.default.dirname(this.file), { recursive: true });
57850
+ import_node_fs38.default.mkdirSync(import_node_path42.default.dirname(this.file), { recursive: true });
57508
57851
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
57509
- import_node_fs37.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
57510
- import_node_fs37.default.renameSync(tmp, this.file);
57852
+ import_node_fs38.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
57853
+ import_node_fs38.default.renameSync(tmp, this.file);
57511
57854
  if (process.platform !== "win32") {
57512
57855
  try {
57513
- import_node_fs37.default.chmodSync(this.file, 384);
57856
+ import_node_fs38.default.chmodSync(this.file, 384);
57514
57857
  } catch {
57515
57858
  }
57516
57859
  }
57517
57860
  }
57518
57861
  delete() {
57519
57862
  try {
57520
- import_node_fs37.default.unlinkSync(this.file);
57863
+ import_node_fs38.default.unlinkSync(this.file);
57521
57864
  } catch {
57522
57865
  }
57523
57866
  }
@@ -57531,14 +57874,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
57531
57874
  }
57532
57875
 
57533
57876
  // src/tunnel/tunnel-manager.ts
57534
- var import_node_fs41 = __toESM(require("fs"), 1);
57535
- var import_node_path45 = __toESM(require("path"), 1);
57877
+ var import_node_fs42 = __toESM(require("fs"), 1);
57878
+ var import_node_path46 = __toESM(require("path"), 1);
57536
57879
  var import_node_crypto11 = __toESM(require("crypto"), 1);
57537
- var import_node_child_process11 = require("child_process");
57880
+ var import_node_child_process12 = require("child_process");
57538
57881
 
57539
57882
  // src/tunnel/tunnel-store.ts
57540
- var import_node_fs38 = __toESM(require("fs"), 1);
57541
- var import_node_path42 = __toESM(require("path"), 1);
57883
+ var import_node_fs39 = __toESM(require("fs"), 1);
57884
+ var import_node_path43 = __toESM(require("path"), 1);
57542
57885
  var TunnelStore = class {
57543
57886
  constructor(filePath) {
57544
57887
  this.filePath = filePath;
@@ -57546,7 +57889,7 @@ var TunnelStore = class {
57546
57889
  filePath;
57547
57890
  async get() {
57548
57891
  try {
57549
- const raw = await import_node_fs38.default.promises.readFile(this.filePath, "utf8");
57892
+ const raw = await import_node_fs39.default.promises.readFile(this.filePath, "utf8");
57550
57893
  const obj = JSON.parse(raw);
57551
57894
  if (!isPersistedTunnel(obj)) return null;
57552
57895
  return obj;
@@ -57557,22 +57900,22 @@ var TunnelStore = class {
57557
57900
  }
57558
57901
  }
57559
57902
  async set(v2) {
57560
- const dir = import_node_path42.default.dirname(this.filePath);
57561
- await import_node_fs38.default.promises.mkdir(dir, { recursive: true });
57903
+ const dir = import_node_path43.default.dirname(this.filePath);
57904
+ await import_node_fs39.default.promises.mkdir(dir, { recursive: true });
57562
57905
  const data = JSON.stringify(v2, null, 2);
57563
57906
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
57564
- await import_node_fs38.default.promises.writeFile(tmp, data, { mode: 384 });
57907
+ await import_node_fs39.default.promises.writeFile(tmp, data, { mode: 384 });
57565
57908
  if (process.platform !== "win32") {
57566
57909
  try {
57567
- await import_node_fs38.default.promises.chmod(tmp, 384);
57910
+ await import_node_fs39.default.promises.chmod(tmp, 384);
57568
57911
  } catch {
57569
57912
  }
57570
57913
  }
57571
- await import_node_fs38.default.promises.rename(tmp, this.filePath);
57914
+ await import_node_fs39.default.promises.rename(tmp, this.filePath);
57572
57915
  }
57573
57916
  async clear() {
57574
57917
  try {
57575
- await import_node_fs38.default.promises.unlink(this.filePath);
57918
+ await import_node_fs39.default.promises.unlink(this.filePath);
57576
57919
  } catch (err) {
57577
57920
  const code = err?.code;
57578
57921
  if (code !== "ENOENT") throw err;
@@ -57667,12 +58010,12 @@ function escape(v2) {
57667
58010
  }
57668
58011
 
57669
58012
  // src/tunnel/frpc-binary.ts
57670
- var import_node_fs39 = __toESM(require("fs"), 1);
57671
- var import_node_os14 = __toESM(require("os"), 1);
57672
- var import_node_path43 = __toESM(require("path"), 1);
57673
- var import_node_child_process9 = require("child_process");
58013
+ var import_node_fs40 = __toESM(require("fs"), 1);
58014
+ var import_node_os15 = __toESM(require("os"), 1);
58015
+ var import_node_path44 = __toESM(require("path"), 1);
58016
+ var import_node_child_process10 = require("child_process");
57674
58017
  var import_node_stream3 = require("stream");
57675
- var import_promises6 = require("stream/promises");
58018
+ var import_promises7 = require("stream/promises");
57676
58019
  var FRPC_VERSION = "0.68.0";
57677
58020
  var UnsupportedPlatformError = class extends Error {
57678
58021
  constructor(platform, arch) {
@@ -57701,20 +58044,20 @@ function frpcDownloadUrl(version2, p2) {
57701
58044
  }
57702
58045
  async function ensureFrpcBinary(opts) {
57703
58046
  if (opts.override) {
57704
- if (!import_node_fs39.default.existsSync(opts.override)) {
58047
+ if (!import_node_fs40.default.existsSync(opts.override)) {
57705
58048
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
57706
58049
  }
57707
58050
  return opts.override;
57708
58051
  }
57709
58052
  const version2 = opts.version ?? FRPC_VERSION;
57710
58053
  const platform = opts.platform ?? detectPlatform();
57711
- const binDir = import_node_path43.default.join(opts.dataDir, "bin");
57712
- import_node_fs39.default.mkdirSync(binDir, { recursive: true });
58054
+ const binDir = import_node_path44.default.join(opts.dataDir, "bin");
58055
+ import_node_fs40.default.mkdirSync(binDir, { recursive: true });
57713
58056
  cleanupStaleArtifacts(binDir);
57714
- const stableBin = import_node_path43.default.join(binDir, "frpc");
57715
- if (import_node_fs39.default.existsSync(stableBin)) return stableBin;
58057
+ const stableBin = import_node_path44.default.join(binDir, "frpc");
58058
+ if (import_node_fs40.default.existsSync(stableBin)) return stableBin;
57716
58059
  const partialBin = `${stableBin}.partial`;
57717
- const tarballPath = import_node_path43.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
58060
+ const tarballPath = import_node_path44.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
57718
58061
  try {
57719
58062
  const url = frpcDownloadUrl(version2, platform);
57720
58063
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -57723,8 +58066,8 @@ async function ensureFrpcBinary(opts) {
57723
58066
  } else {
57724
58067
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
57725
58068
  }
57726
- import_node_fs39.default.chmodSync(partialBin, 493);
57727
- import_node_fs39.default.renameSync(partialBin, stableBin);
58069
+ import_node_fs40.default.chmodSync(partialBin, 493);
58070
+ import_node_fs40.default.renameSync(partialBin, stableBin);
57728
58071
  } finally {
57729
58072
  safeUnlink(tarballPath);
57730
58073
  safeUnlink(partialBin);
@@ -57734,15 +58077,15 @@ async function ensureFrpcBinary(opts) {
57734
58077
  function cleanupStaleArtifacts(binDir) {
57735
58078
  let entries;
57736
58079
  try {
57737
- entries = import_node_fs39.default.readdirSync(binDir);
58080
+ entries = import_node_fs40.default.readdirSync(binDir);
57738
58081
  } catch {
57739
58082
  return;
57740
58083
  }
57741
58084
  for (const name of entries) {
57742
58085
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
57743
- const full = import_node_path43.default.join(binDir, name);
58086
+ const full = import_node_path44.default.join(binDir, name);
57744
58087
  try {
57745
- import_node_fs39.default.rmSync(full, { recursive: true, force: true });
58088
+ import_node_fs40.default.rmSync(full, { recursive: true, force: true });
57746
58089
  } catch {
57747
58090
  }
57748
58091
  }
@@ -57750,7 +58093,7 @@ function cleanupStaleArtifacts(binDir) {
57750
58093
  }
57751
58094
  function safeUnlink(p2) {
57752
58095
  try {
57753
- import_node_fs39.default.unlinkSync(p2);
58096
+ import_node_fs40.default.unlinkSync(p2);
57754
58097
  } catch {
57755
58098
  }
57756
58099
  }
@@ -57761,46 +58104,46 @@ async function downloadToFile(url, dest, fetchImpl) {
57761
58104
  if (!res.ok || !res.body) {
57762
58105
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
57763
58106
  }
57764
- const out = import_node_fs39.default.createWriteStream(dest);
58107
+ const out = import_node_fs40.default.createWriteStream(dest);
57765
58108
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
57766
- await (0, import_promises6.pipeline)(nodeStream, out);
58109
+ await (0, import_promises7.pipeline)(nodeStream, out);
57767
58110
  }
57768
58111
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
57769
- const work = import_node_path43.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
57770
- import_node_fs39.default.mkdirSync(work, { recursive: true });
58112
+ const work = import_node_path44.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
58113
+ import_node_fs40.default.mkdirSync(work, { recursive: true });
57771
58114
  try {
57772
58115
  await new Promise((resolve7, reject) => {
57773
- const proc = (0, import_node_child_process9.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
58116
+ const proc = (0, import_node_child_process10.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
57774
58117
  proc.on("error", reject);
57775
58118
  proc.on("exit", (code) => code === 0 ? resolve7() : reject(new Error(`tar exited ${code}`)));
57776
58119
  });
57777
58120
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
57778
- const src = import_node_path43.default.join(work, dirName, "frpc");
57779
- if (!import_node_fs39.default.existsSync(src)) {
58121
+ const src = import_node_path44.default.join(work, dirName, "frpc");
58122
+ if (!import_node_fs40.default.existsSync(src)) {
57780
58123
  throw new Error(`frpc not found inside tarball at ${src}`);
57781
58124
  }
57782
- import_node_fs39.default.copyFileSync(src, destBin);
58125
+ import_node_fs40.default.copyFileSync(src, destBin);
57783
58126
  } finally {
57784
- import_node_fs39.default.rmSync(work, { recursive: true, force: true });
58127
+ import_node_fs40.default.rmSync(work, { recursive: true, force: true });
57785
58128
  }
57786
58129
  }
57787
58130
 
57788
58131
  // src/tunnel/frpc-process.ts
57789
- var import_node_fs40 = __toESM(require("fs"), 1);
57790
- var import_node_path44 = __toESM(require("path"), 1);
57791
- var import_node_child_process10 = require("child_process");
58132
+ var import_node_fs41 = __toESM(require("fs"), 1);
58133
+ var import_node_path45 = __toESM(require("path"), 1);
58134
+ var import_node_child_process11 = require("child_process");
57792
58135
  function frpcPidFilePath(dataDir) {
57793
- return import_node_path44.default.join(dataDir, "frpc.pid");
58136
+ return import_node_path45.default.join(dataDir, "frpc.pid");
57794
58137
  }
57795
58138
  function writeFrpcPid(dataDir, pid) {
57796
58139
  try {
57797
- import_node_fs40.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
58140
+ import_node_fs41.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
57798
58141
  } catch {
57799
58142
  }
57800
58143
  }
57801
58144
  function clearFrpcPid(dataDir) {
57802
58145
  try {
57803
- import_node_fs40.default.unlinkSync(frpcPidFilePath(dataDir));
58146
+ import_node_fs41.default.unlinkSync(frpcPidFilePath(dataDir));
57804
58147
  } catch {
57805
58148
  }
57806
58149
  }
@@ -57816,7 +58159,7 @@ function defaultIsPidAlive(pid) {
57816
58159
  }
57817
58160
  function defaultReadPidFile(file) {
57818
58161
  try {
57819
- return import_node_fs40.default.readFileSync(file, "utf8");
58162
+ return import_node_fs41.default.readFileSync(file, "utf8");
57820
58163
  } catch {
57821
58164
  return null;
57822
58165
  }
@@ -57832,7 +58175,7 @@ function defaultSleep2(ms) {
57832
58175
  }
57833
58176
  async function killStaleFrpc(deps) {
57834
58177
  const pidFile = frpcPidFilePath(deps.dataDir);
57835
- const tomlPath = import_node_path44.default.join(deps.dataDir, "frpc.toml");
58178
+ const tomlPath = import_node_path45.default.join(deps.dataDir, "frpc.toml");
57836
58179
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
57837
58180
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
57838
58181
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -57856,7 +58199,7 @@ async function killStaleFrpc(deps) {
57856
58199
  }
57857
58200
  if (victims.size === 0) {
57858
58201
  try {
57859
- import_node_fs40.default.unlinkSync(pidFile);
58202
+ import_node_fs41.default.unlinkSync(pidFile);
57860
58203
  } catch {
57861
58204
  }
57862
58205
  return;
@@ -57867,14 +58210,14 @@ async function killStaleFrpc(deps) {
57867
58210
  }
57868
58211
  await sleep2(deps.reapWaitMs ?? 300);
57869
58212
  try {
57870
- import_node_fs40.default.unlinkSync(pidFile);
58213
+ import_node_fs41.default.unlinkSync(pidFile);
57871
58214
  } catch {
57872
58215
  }
57873
58216
  }
57874
58217
  async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
57875
58218
  if (process.platform === "win32") return [];
57876
58219
  return new Promise((resolve7) => {
57877
- const ps = (0, import_node_child_process10.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
58220
+ const ps = (0, import_node_child_process11.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
57878
58221
  let buf = "";
57879
58222
  ps.stdout.on("data", (c) => {
57880
58223
  buf += c.toString();
@@ -57904,7 +58247,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
57904
58247
  var TunnelManager = class {
57905
58248
  constructor(deps) {
57906
58249
  this.deps = deps;
57907
- this.store = deps.store ?? new TunnelStore(import_node_path45.default.join(deps.dataDir, "tunnel.json"));
58250
+ this.store = deps.store ?? new TunnelStore(import_node_path46.default.join(deps.dataDir, "tunnel.json"));
57908
58251
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
57909
58252
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
57910
58253
  }
@@ -58031,7 +58374,7 @@ var TunnelManager = class {
58031
58374
  dataDir: this.deps.dataDir,
58032
58375
  override: this.deps.frpcBinaryOverride ?? void 0
58033
58376
  });
58034
- const tomlPath = import_node_path45.default.join(this.deps.dataDir, "frpc.toml");
58377
+ const tomlPath = import_node_path46.default.join(this.deps.dataDir, "frpc.toml");
58035
58378
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto11.default.randomBytes(3).toString("hex")}`;
58036
58379
  const toml = buildFrpcToml({
58037
58380
  serverAddr: t.frpsHost,
@@ -58042,14 +58385,14 @@ var TunnelManager = class {
58042
58385
  localPort,
58043
58386
  logLevel: "info"
58044
58387
  });
58045
- await import_node_fs41.default.promises.writeFile(tomlPath, toml, { mode: 384 });
58046
- const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(frpcBin, ["-c", tomlPath], {
58388
+ await import_node_fs42.default.promises.writeFile(tomlPath, toml, { mode: 384 });
58389
+ const proc = (this.deps.spawnImpl ?? import_node_child_process12.spawn)(frpcBin, ["-c", tomlPath], {
58047
58390
  stdio: ["ignore", "pipe", "pipe"]
58048
58391
  });
58049
- const logDir = import_node_path45.default.join(this.deps.dataDir, "log");
58050
- import_node_fs41.default.mkdirSync(logDir, { recursive: true });
58051
- const logFilePath = import_node_path45.default.join(logDir, "frpc.log");
58052
- const logStream = import_node_fs41.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
58392
+ const logDir = import_node_path46.default.join(this.deps.dataDir, "log");
58393
+ import_node_fs42.default.mkdirSync(logDir, { recursive: true });
58394
+ const logFilePath = import_node_path46.default.join(logDir, "frpc.log");
58395
+ const logStream = import_node_fs42.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
58053
58396
  logStream.on("error", () => {
58054
58397
  });
58055
58398
  const tee = (chunk) => {
@@ -58131,28 +58474,28 @@ async function waitForFrpcReady(proc, timeoutMs) {
58131
58474
  }
58132
58475
 
58133
58476
  // src/tunnel/device-key.ts
58134
- var import_node_os15 = __toESM(require("os"), 1);
58135
- var import_node_path46 = __toESM(require("path"), 1);
58477
+ var import_node_os16 = __toESM(require("os"), 1);
58478
+ var import_node_path47 = __toESM(require("path"), 1);
58136
58479
  var import_node_crypto12 = __toESM(require("crypto"), 1);
58137
58480
  var DERIVE_SALT = "clawd-tunnel-device-v1";
58138
58481
  function deriveStableDeviceKey(opts = {}) {
58139
- const hostname = opts.hostname ?? import_node_os15.default.hostname();
58140
- const uid = opts.uid ?? (typeof import_node_os15.default.userInfo === "function" ? import_node_os15.default.userInfo().uid : 0);
58141
- const home = opts.home ?? import_node_os15.default.homedir();
58142
- const defaultDataDir = import_node_path46.default.resolve(import_node_path46.default.join(home, ".clawd"));
58143
- const normalizedDataDir = opts.dataDir ? import_node_path46.default.resolve(opts.dataDir) : null;
58482
+ const hostname = opts.hostname ?? import_node_os16.default.hostname();
58483
+ const uid = opts.uid ?? (typeof import_node_os16.default.userInfo === "function" ? import_node_os16.default.userInfo().uid : 0);
58484
+ const home = opts.home ?? import_node_os16.default.homedir();
58485
+ const defaultDataDir = import_node_path47.default.resolve(import_node_path47.default.join(home, ".clawd"));
58486
+ const normalizedDataDir = opts.dataDir ? import_node_path47.default.resolve(opts.dataDir) : null;
58144
58487
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
58145
58488
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
58146
58489
  return import_node_crypto12.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
58147
58490
  }
58148
58491
 
58149
58492
  // src/auth-store.ts
58150
- var import_node_fs42 = __toESM(require("fs"), 1);
58151
- var import_node_path47 = __toESM(require("path"), 1);
58493
+ var import_node_fs43 = __toESM(require("fs"), 1);
58494
+ var import_node_path48 = __toESM(require("path"), 1);
58152
58495
  var import_node_crypto13 = __toESM(require("crypto"), 1);
58153
58496
  var AUTH_FILE_NAME = "auth.json";
58154
58497
  function authFilePath(dataDir) {
58155
- return import_node_path47.default.join(dataDir, AUTH_FILE_NAME);
58498
+ return import_node_path48.default.join(dataDir, AUTH_FILE_NAME);
58156
58499
  }
58157
58500
  function loadOrCreateAuthFile(opts) {
58158
58501
  const file = authFilePath(opts.dataDir);
@@ -58184,7 +58527,7 @@ function defaultGenerateOwnerPrincipalId() {
58184
58527
  }
58185
58528
  function readAuthFile(file) {
58186
58529
  try {
58187
- const raw = import_node_fs42.default.readFileSync(file, "utf8");
58530
+ const raw = import_node_fs43.default.readFileSync(file, "utf8");
58188
58531
  const parsed = JSON.parse(raw);
58189
58532
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
58190
58533
  return null;
@@ -58204,26 +58547,26 @@ function readAuthFile(file) {
58204
58547
  }
58205
58548
  }
58206
58549
  function writeAuthFile(file, content) {
58207
- import_node_fs42.default.mkdirSync(import_node_path47.default.dirname(file), { recursive: true });
58208
- import_node_fs42.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
58550
+ import_node_fs43.default.mkdirSync(import_node_path48.default.dirname(file), { recursive: true });
58551
+ import_node_fs43.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
58209
58552
  try {
58210
- import_node_fs42.default.chmodSync(file, 384);
58553
+ import_node_fs43.default.chmodSync(file, 384);
58211
58554
  } catch {
58212
58555
  }
58213
58556
  }
58214
58557
 
58215
58558
  // src/owner-profile.ts
58216
- var import_node_fs43 = __toESM(require("fs"), 1);
58217
- var import_node_os16 = __toESM(require("os"), 1);
58218
- var import_node_path48 = __toESM(require("path"), 1);
58559
+ var import_node_fs44 = __toESM(require("fs"), 1);
58560
+ var import_node_os17 = __toESM(require("os"), 1);
58561
+ var import_node_path49 = __toESM(require("path"), 1);
58219
58562
  var PROFILE_FILENAME = "profile.json";
58220
58563
  function profilePath(dataDir) {
58221
- return import_node_path48.default.join(dataDir, PROFILE_FILENAME);
58564
+ return import_node_path49.default.join(dataDir, PROFILE_FILENAME);
58222
58565
  }
58223
58566
  function loadOwnerProfile(dataDir) {
58224
58567
  let raw;
58225
58568
  try {
58226
- raw = import_node_fs43.default.readFileSync(profilePath(dataDir), "utf8");
58569
+ raw = import_node_fs44.default.readFileSync(profilePath(dataDir), "utf8");
58227
58570
  } catch {
58228
58571
  return {};
58229
58572
  }
@@ -58239,11 +58582,11 @@ function loadOwnerProfile(dataDir) {
58239
58582
  }
58240
58583
  function patchOwnerProfile(dataDir, patch) {
58241
58584
  const merged = { ...loadOwnerProfile(dataDir), ...patch };
58242
- import_node_fs43.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
58585
+ import_node_fs44.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
58243
58586
  return merged;
58244
58587
  }
58245
58588
  function loadOwnerDisplayName(dataDir) {
58246
- const fallback = import_node_os16.default.userInfo().username;
58589
+ const fallback = import_node_os17.default.userInfo().username;
58247
58590
  const displayName = loadOwnerProfile(dataDir).displayName;
58248
58591
  if (typeof displayName !== "string" || displayName.length === 0) {
58249
58592
  if (displayName !== void 0) {
@@ -58255,18 +58598,18 @@ function loadOwnerDisplayName(dataDir) {
58255
58598
  }
58256
58599
 
58257
58600
  // src/feishu-auth/owner-identity-store.ts
58258
- var import_node_fs44 = __toESM(require("fs"), 1);
58259
- var import_node_path49 = __toESM(require("path"), 1);
58601
+ var import_node_fs45 = __toESM(require("fs"), 1);
58602
+ var import_node_path50 = __toESM(require("path"), 1);
58260
58603
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
58261
58604
  var OwnerIdentityStore = class {
58262
58605
  file;
58263
58606
  constructor(dataDir) {
58264
- this.file = import_node_path49.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
58607
+ this.file = import_node_path50.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
58265
58608
  }
58266
58609
  read() {
58267
58610
  let raw;
58268
58611
  try {
58269
- raw = import_node_fs44.default.readFileSync(this.file, "utf8");
58612
+ raw = import_node_fs45.default.readFileSync(this.file, "utf8");
58270
58613
  } catch {
58271
58614
  return null;
58272
58615
  }
@@ -58294,16 +58637,16 @@ var OwnerIdentityStore = class {
58294
58637
  };
58295
58638
  }
58296
58639
  write(record3) {
58297
- import_node_fs44.default.mkdirSync(import_node_path49.default.dirname(this.file), { recursive: true });
58298
- import_node_fs44.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
58640
+ import_node_fs45.default.mkdirSync(import_node_path50.default.dirname(this.file), { recursive: true });
58641
+ import_node_fs45.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
58299
58642
  try {
58300
- import_node_fs44.default.chmodSync(this.file, 384);
58643
+ import_node_fs45.default.chmodSync(this.file, 384);
58301
58644
  } catch {
58302
58645
  }
58303
58646
  }
58304
58647
  clear() {
58305
58648
  try {
58306
- import_node_fs44.default.unlinkSync(this.file);
58649
+ import_node_fs45.default.unlinkSync(this.file);
58307
58650
  } catch (err) {
58308
58651
  const code = err?.code;
58309
58652
  if (code !== "ENOENT") throw err;
@@ -58636,8 +58979,8 @@ function verifyConnectToken(args) {
58636
58979
  }
58637
58980
 
58638
58981
  // src/feishu-auth/server-key.ts
58639
- var fs56 = __toESM(require("fs"), 1);
58640
- var path59 = __toESM(require("path"), 1);
58982
+ var fs57 = __toESM(require("fs"), 1);
58983
+ var path60 = __toESM(require("path"), 1);
58641
58984
  var FILE_NAME2 = "server-signing-key.json";
58642
58985
  var ServerKeyStore = class {
58643
58986
  constructor(dataDir) {
@@ -58645,12 +58988,12 @@ var ServerKeyStore = class {
58645
58988
  }
58646
58989
  dataDir;
58647
58990
  filePath() {
58648
- return path59.join(this.dataDir, FILE_NAME2);
58991
+ return path60.join(this.dataDir, FILE_NAME2);
58649
58992
  }
58650
58993
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
58651
58994
  read() {
58652
58995
  try {
58653
- const raw = fs56.readFileSync(this.filePath(), "utf8");
58996
+ const raw = fs57.readFileSync(this.filePath(), "utf8");
58654
58997
  const parsed = JSON.parse(raw);
58655
58998
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
58656
58999
  return parsed.publicKeyPem;
@@ -58665,12 +59008,12 @@ var ServerKeyStore = class {
58665
59008
  publicKeyPem,
58666
59009
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
58667
59010
  };
58668
- fs56.mkdirSync(this.dataDir, { recursive: true });
58669
- fs56.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
59011
+ fs57.mkdirSync(this.dataDir, { recursive: true });
59012
+ fs57.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
58670
59013
  }
58671
59014
  clear() {
58672
59015
  try {
58673
- fs56.unlinkSync(this.filePath());
59016
+ fs57.unlinkSync(this.filePath());
58674
59017
  } catch {
58675
59018
  }
58676
59019
  }
@@ -58683,12 +59026,12 @@ init_protocol();
58683
59026
  init_protocol();
58684
59027
 
58685
59028
  // src/session/fork.ts
58686
- var import_node_fs45 = __toESM(require("fs"), 1);
58687
- var import_node_os17 = __toESM(require("os"), 1);
58688
- var import_node_path50 = __toESM(require("path"), 1);
59029
+ var import_node_fs46 = __toESM(require("fs"), 1);
59030
+ var import_node_os18 = __toESM(require("os"), 1);
59031
+ var import_node_path51 = __toESM(require("path"), 1);
58689
59032
  init_claude_history();
58690
59033
  function readJsonlEntries(file) {
58691
- const raw = import_node_fs45.default.readFileSync(file, "utf8");
59034
+ const raw = import_node_fs46.default.readFileSync(file, "utf8");
58692
59035
  const out = [];
58693
59036
  for (const line of raw.split("\n")) {
58694
59037
  const t = line.trim();
@@ -58701,19 +59044,19 @@ function readJsonlEntries(file) {
58701
59044
  return out;
58702
59045
  }
58703
59046
  function forkSession(input) {
58704
- const baseDir = input.baseDir ?? import_node_path50.default.join(import_node_os17.default.homedir(), ".claude");
58705
- let projectDir = import_node_path50.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
58706
- let sourceFile = import_node_path50.default.join(projectDir, `${input.toolSessionId}.jsonl`);
58707
- if (!import_node_fs45.default.existsSync(sourceFile)) {
59047
+ const baseDir = input.baseDir ?? import_node_path51.default.join(import_node_os18.default.homedir(), ".claude");
59048
+ let projectDir = import_node_path51.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
59049
+ let sourceFile = import_node_path51.default.join(projectDir, `${input.toolSessionId}.jsonl`);
59050
+ if (!import_node_fs46.default.existsSync(sourceFile)) {
58708
59051
  const found = findTranscriptByToolSessionId(
58709
- import_node_path50.default.join(baseDir, "projects"),
59052
+ import_node_path51.default.join(baseDir, "projects"),
58710
59053
  input.toolSessionId
58711
59054
  );
58712
59055
  if (!found) {
58713
59056
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
58714
59057
  }
58715
59058
  sourceFile = found;
58716
- projectDir = import_node_path50.default.dirname(found);
59059
+ projectDir = import_node_path51.default.dirname(found);
58717
59060
  }
58718
59061
  const entries = readJsonlEntries(sourceFile);
58719
59062
  const mainEntries = entries.filter((e) => e.isSidechain !== true);
@@ -58742,313 +59085,13 @@ function forkSession(input) {
58742
59085
  }
58743
59086
  forkedLines.push(JSON.stringify(forked));
58744
59087
  }
58745
- const outDir = input.targetCwd ? import_node_path50.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
58746
- const forkedFilePath = import_node_path50.default.join(outDir, `${forkedToolSessionId}.jsonl`);
58747
- import_node_fs45.default.mkdirSync(outDir, { recursive: true });
58748
- import_node_fs45.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
59088
+ const outDir = input.targetCwd ? import_node_path51.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
59089
+ const forkedFilePath = import_node_path51.default.join(outDir, `${forkedToolSessionId}.jsonl`);
59090
+ import_node_fs46.default.mkdirSync(outDir, { recursive: true });
59091
+ import_node_fs46.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
58749
59092
  return { forkedToolSessionId, forkedFilePath };
58750
59093
  }
58751
59094
 
58752
- // src/session/external-scan.ts
58753
- var import_node_fs46 = __toESM(require("fs"), 1);
58754
- var import_promises7 = __toESM(require("fs/promises"), 1);
58755
- var import_node_os18 = __toESM(require("os"), 1);
58756
- var import_node_path51 = __toESM(require("path"), 1);
58757
- var import_node_module = require("module");
58758
- var import_node_child_process12 = require("child_process");
58759
- var import_meta4 = {};
58760
- function defaultRoots() {
58761
- const home = import_node_os18.default.homedir();
58762
- return {
58763
- claudeProjectsDir: import_node_path51.default.join(home, ".claude", "projects"),
58764
- codexDir: import_node_path51.default.join(home, ".codex"),
58765
- clawdDir: import_node_path51.default.join(home, ".clawd")
58766
- };
58767
- }
58768
- function width(s) {
58769
- let w2 = 0;
58770
- for (const ch of s) w2 += /[ᄀ-ᅟ⺀-꓏가-힣豈-﫿︰-﹏＀-⦆¢-₩]/.test(ch) ? 2 : 1;
58771
- return w2;
58772
- }
58773
- function clipW(text, n) {
58774
- const s = String(text ?? "").split(/\s+/).filter(Boolean).join(" ");
58775
- if (width(s) <= n) return s;
58776
- let out = "";
58777
- let w2 = 0;
58778
- for (const ch of s) {
58779
- const cw = width(ch);
58780
- if (w2 + cw > n - 1) break;
58781
- out += ch;
58782
- w2 += cw;
58783
- }
58784
- return out + "\u2026";
58785
- }
58786
- function toMs(v2) {
58787
- const n = Number(v2 || 0);
58788
- return n > 1e11 ? Math.round(n) : Math.round(n * 1e3);
58789
- }
58790
- function listFiles(dir, depth = 0, maxDepth = 8, out = []) {
58791
- let entries;
58792
- try {
58793
- entries = import_node_fs46.default.readdirSync(dir, { withFileTypes: true });
58794
- } catch {
58795
- return out;
58796
- }
58797
- for (const e of entries) {
58798
- const full = import_node_path51.default.join(dir, e.name);
58799
- if (e.isDirectory()) {
58800
- if (depth < maxDepth) listFiles(full, depth + 1, maxDepth, out);
58801
- } else if (e.isFile()) {
58802
- out.push(full);
58803
- }
58804
- }
58805
- return out;
58806
- }
58807
- async function* jsonLines(file) {
58808
- let raw;
58809
- try {
58810
- raw = await import_promises7.default.readFile(file, "utf8");
58811
- } catch {
58812
- return;
58813
- }
58814
- for (const line of raw.split("\n")) {
58815
- const t = line.trim();
58816
- if (!t) continue;
58817
- try {
58818
- yield JSON.parse(t);
58819
- } catch {
58820
- }
58821
- }
58822
- }
58823
- function userText(msg) {
58824
- const content = msg && typeof msg === "object" ? msg.content : null;
58825
- if (typeof content === "string") return content;
58826
- if (Array.isArray(content)) {
58827
- return content.map((b2) => b2 && b2.type === "text" ? String(b2.text ?? "") : "").join("");
58828
- }
58829
- return "";
58830
- }
58831
- function isDir2(p2) {
58832
- try {
58833
- return import_node_fs46.default.statSync(p2).isDirectory();
58834
- } catch {
58835
- return false;
58836
- }
58837
- }
58838
- async function scanClaude(roots) {
58839
- const out = [];
58840
- let dirs;
58841
- try {
58842
- dirs = import_node_fs46.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
58843
- } catch {
58844
- return out;
58845
- }
58846
- for (const d of dirs) {
58847
- if (!d.isDirectory()) continue;
58848
- let files;
58849
- try {
58850
- files = import_node_fs46.default.readdirSync(import_node_path51.default.join(roots.claudeProjectsDir, d.name));
58851
- } catch {
58852
- continue;
58853
- }
58854
- for (const name of files) {
58855
- if (!name.endsWith(".jsonl")) continue;
58856
- const file = import_node_path51.default.join(roots.claudeProjectsDir, d.name, name);
58857
- let st;
58858
- try {
58859
- st = import_node_fs46.default.statSync(file);
58860
- } catch {
58861
- continue;
58862
- }
58863
- let cwd = "";
58864
- let title = "";
58865
- let firstUser = "";
58866
- let turns = 0;
58867
- let firstTs = 0;
58868
- let lastTs = 0;
58869
- let hasMainLine = false;
58870
- for await (const rec4 of jsonLines(file)) {
58871
- if (!cwd && typeof rec4.cwd === "string") cwd = rec4.cwd;
58872
- if (typeof rec4.timestamp === "string") {
58873
- const t = Date.parse(rec4.timestamp);
58874
- if (Number.isFinite(t)) {
58875
- firstTs ||= t;
58876
- lastTs = t;
58877
- }
58878
- }
58879
- if (rec4.type === "ai-title" && rec4.aiTitle) {
58880
- title = String(rec4.aiTitle);
58881
- continue;
58882
- }
58883
- if (rec4.type !== "user" && rec4.type !== "assistant") continue;
58884
- if (!rec4.isSidechain) hasMainLine = true;
58885
- if (rec4.type !== "user" || rec4.isSidechain || rec4.isMeta) continue;
58886
- const text = userText(rec4.message || {});
58887
- if (!text.trim() || text.trimStart().startsWith("<")) continue;
58888
- turns += 1;
58889
- firstUser ||= text;
58890
- }
58891
- const cand = {
58892
- tool: "claude",
58893
- toolSessionId: name.slice(0, -".jsonl".length),
58894
- cwd,
58895
- label: clipW(title || firstUser, 56),
58896
- turns,
58897
- createdMs: firstTs || st.mtimeMs,
58898
- updatedMs: lastTs || st.mtimeMs,
58899
- skip: ""
58900
- };
58901
- if (!hasMainLine) cand.skip = "subagent \u652F\u7EBF";
58902
- else if (!cwd) cand.skip = "\u65E0 cwd";
58903
- else if (cwd.includes("clawd-title-gen")) cand.skip = "\u6807\u9898\u751F\u6210\u4E34\u65F6\u4F1A\u8BDD";
58904
- out.push(cand);
58905
- }
58906
- }
58907
- return out;
58908
- }
58909
- async function countCodexTurns(rolloutPath) {
58910
- if (!rolloutPath || !import_node_fs46.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
58911
- let turns = 0;
58912
- let first = "";
58913
- for await (const rec4 of jsonLines(rolloutPath)) {
58914
- const p2 = rec4.payload || {};
58915
- if (p2.type !== "message" || p2.role !== "user") continue;
58916
- const text = (p2.content || []).map((b2) => String(b2 && b2.text || "")).join("");
58917
- if (!text.trim() || text.trimStart().startsWith("<")) continue;
58918
- turns += 1;
58919
- first ||= text;
58920
- }
58921
- return { turns, first };
58922
- }
58923
- function readCodexThreads(db) {
58924
- const COLS = ["id", "cwd", "created_at", "updated_at", "name", "title", "preview", "first_user_message", "archived", "rollout_path"];
58925
- try {
58926
- const { DatabaseSync } = (0, import_node_module.createRequire)(import_meta4.url)("node:sqlite");
58927
- const conn = new DatabaseSync(db, { readOnly: true });
58928
- try {
58929
- const have = new Set(
58930
- conn.prepare("PRAGMA table_info(threads)").all().map((r) => r.name)
58931
- );
58932
- if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
58933
- const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
58934
- return conn.prepare(`SELECT ${sel} FROM threads`).all();
58935
- } finally {
58936
- conn.close();
58937
- }
58938
- } catch {
58939
- }
58940
- try {
58941
- const info = (0, import_node_child_process12.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
58942
- if (info.status !== 0) return null;
58943
- const have = new Set(
58944
- info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
58945
- );
58946
- if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
58947
- const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
58948
- const res = (0, import_node_child_process12.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
58949
- encoding: "utf8",
58950
- maxBuffer: 64 * 1024 * 1024
58951
- });
58952
- if (res.status !== 0 || !res.stdout.trim()) return null;
58953
- return JSON.parse(res.stdout);
58954
- } catch {
58955
- return null;
58956
- }
58957
- }
58958
- async function codexFromRows(rows) {
58959
- const out = [];
58960
- for (const r of rows) {
58961
- const updatedMs = toMs(r.updated_at);
58962
- const { turns, first } = await countCodexTurns(String(r.rollout_path || ""));
58963
- const label = clipW(r.name || r.title || r.preview || r.first_user_message || first, 56);
58964
- const cand = {
58965
- tool: "codex",
58966
- toolSessionId: String(r.id),
58967
- cwd: String(r.cwd || ""),
58968
- label,
58969
- turns,
58970
- createdMs: toMs(r.created_at) || updatedMs,
58971
- updatedMs,
58972
- skip: ""
58973
- };
58974
- if (r.archived) cand.skip = "\u5DF2\u5F52\u6863";
58975
- else if (!label) cand.skip = "\u7A7A\u4F1A\u8BDD";
58976
- out.push(cand);
58977
- }
58978
- return out;
58979
- }
58980
- async function scanCodexRollouts(roots) {
58981
- const out = [];
58982
- for (const file of listFiles(import_node_path51.default.join(roots.codexDir, "sessions"))) {
58983
- if (!file.endsWith(".jsonl")) continue;
58984
- let st;
58985
- try {
58986
- st = import_node_fs46.default.statSync(file);
58987
- } catch {
58988
- continue;
58989
- }
58990
- let meta = null;
58991
- for await (const rec4 of jsonLines(file)) {
58992
- if (rec4.type === "session_meta") {
58993
- meta = rec4.payload || {};
58994
- break;
58995
- }
58996
- }
58997
- const tid = meta && (meta.session_id || meta.id);
58998
- if (!tid) continue;
58999
- const { turns, first } = await countCodexTurns(file);
59000
- const cand = {
59001
- tool: "codex",
59002
- toolSessionId: String(tid),
59003
- cwd: String(meta?.cwd || ""),
59004
- label: clipW(first, 56),
59005
- turns,
59006
- createdMs: st.mtimeMs,
59007
- updatedMs: st.mtimeMs,
59008
- skip: ""
59009
- };
59010
- if (!cand.cwd) cand.skip = "\u65E0 cwd";
59011
- out.push(cand);
59012
- }
59013
- return out;
59014
- }
59015
- async function scanCodex(roots) {
59016
- let dbs = [];
59017
- try {
59018
- dbs = import_node_fs46.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path51.default.join(roots.codexDir, n));
59019
- } catch {
59020
- }
59021
- if (dbs.length) {
59022
- const rows = readCodexThreads(dbs[dbs.length - 1]);
59023
- if (rows) return codexFromRows(rows);
59024
- }
59025
- return scanCodexRollouts(roots);
59026
- }
59027
- async function scanExternalSessions(rootsIn) {
59028
- const roots = { ...defaultRoots(), ...rootsIn };
59029
- const personaRoot = import_node_path51.default.join(roots.clawdDir, "personas");
59030
- const all = [...await scanClaude(roots), ...await scanCodex(roots)];
59031
- const out = [];
59032
- for (const c of all) {
59033
- if (c.skip) continue;
59034
- if (c.turns < 1) continue;
59035
- if (!c.cwd || !isDir2(c.cwd)) continue;
59036
- if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path51.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path51.default.sep)) {
59037
- continue;
59038
- }
59039
- out.push({
59040
- tool: c.tool,
59041
- cwd: c.cwd,
59042
- toolSessionId: c.toolSessionId,
59043
- ...c.label ? { label: c.label } : {},
59044
- createdAt: new Date(c.createdMs).toISOString(),
59045
- updatedAt: new Date(c.updatedMs).toISOString(),
59046
- turns: c.turns
59047
- });
59048
- }
59049
- return out;
59050
- }
59051
-
59052
59095
  // src/session/import-ledger.ts
59053
59096
  var import_node_fs47 = __toESM(require("fs"), 1);
59054
59097
  var import_node_path52 = __toESM(require("path"), 1);
@@ -59607,8 +59650,8 @@ function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userW
59607
59650
  if (target === u || target.startsWith(u + usep)) return true;
59608
59651
  }
59609
59652
  const root = path63.resolve(personaRoot);
59610
- const sep3 = root.endsWith(path63.sep) ? "" : path63.sep;
59611
- if (!target.startsWith(root + sep3)) return false;
59653
+ const sep4 = root.endsWith(path63.sep) ? "" : path63.sep;
59654
+ if (!target.startsWith(root + sep4)) return false;
59612
59655
  const rel = path63.relative(root, target);
59613
59656
  if (!rel || rel.startsWith("..")) return false;
59614
59657
  const personaId2 = rel.split(path63.sep)[0];
@@ -59620,8 +59663,8 @@ function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userW
59620
59663
  function personaIdFromPath(absPath, personaRoot) {
59621
59664
  const root = path63.resolve(personaRoot);
59622
59665
  const target = path63.resolve(absPath);
59623
- const sep3 = root.endsWith(path63.sep) ? "" : path63.sep;
59624
- if (!target.startsWith(root + sep3)) return null;
59666
+ const sep4 = root.endsWith(path63.sep) ? "" : path63.sep;
59667
+ if (!target.startsWith(root + sep4)) return null;
59625
59668
  const rel = path63.relative(root, target);
59626
59669
  if (!rel || rel.startsWith("..")) return null;
59627
59670
  const id = rel.split(path63.sep)[0];
@@ -59630,8 +59673,8 @@ function personaIdFromPath(absPath, personaRoot) {
59630
59673
  function isPathWithin(dir, absPath) {
59631
59674
  const d = path63.resolve(dir);
59632
59675
  const t = path63.resolve(absPath);
59633
- const sep3 = d.endsWith(path63.sep) ? "" : path63.sep;
59634
- return t === d || t.startsWith(d + sep3);
59676
+ const sep4 = d.endsWith(path63.sep) ? "" : path63.sep;
59677
+ return t === d || t.startsWith(d + sep4);
59635
59678
  }
59636
59679
  function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
59637
59680
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
@@ -60894,7 +60937,7 @@ function computeMethodAccess(args) {
60894
60937
  }
60895
60938
 
60896
60939
  // src/version.ts
60897
- var version = "0.2.367".length > 0 ? "0.2.367" : "dev";
60940
+ var version = "0.2.368".length > 0 ? "0.2.368" : "dev";
60898
60941
 
60899
60942
  // src/cli-probe/probe.ts
60900
60943
  var fs62 = __toESM(require("fs"), 1);
@@ -64826,6 +64869,13 @@ async function startDaemon(config) {
64826
64869
  projectsStore.seedFromSessions(
64827
64870
  manager.list().response.sessions
64828
64871
  );
64872
+ void scanExternalSessions().then((candidates) => {
64873
+ projectsStore.seedFromExternal(candidates);
64874
+ logger.info("projects.seed-external", {
64875
+ candidates: candidates.length,
64876
+ total: projectsStore.list().length
64877
+ });
64878
+ }).catch((err) => logger.warn("projects.seed-external failed", { err: String(err) }));
64829
64879
  const observer = new SessionObserver({
64830
64880
  // TUI 模式 pty 跑 CC 不发 SDK system.task_started 帧 → UI pending 期 progress.agentId
64831
64881
  // 永远 undefined,子 agent 调用过程没有抽屉入口。开 meta observer 后从 subagents 目录