@clawos-dev/clawd 0.2.227 → 0.2.229

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -6136,7 +6136,12 @@ var init_dispatch = __esm({
6136
6136
  prompt: external_exports.string(),
6137
6137
  // 跨设备 dispatch:非空 = A 角色,转发到该 contact deviceId 的 peer daemon;
6138
6138
  // 省略 = 本地 dispatch / B 角色本地执行。A 转发给 B 时 body 不带此字段。
6139
- targetDeviceId: external_exports.string().min(1).optional()
6139
+ targetDeviceId: external_exports.string().min(1).optional(),
6140
+ // 可选:override B session 使用的 claude 模型。缺省 = 用 persona 默认。
6141
+ // 合法值集与 claude adapter capabilities.models[].id 一致(见 daemon
6142
+ // tools/claude.ts CLAUDE_MODEL_IDS);handler 层做二次校验,非法值 fail-fast。
6143
+ // protocol 层保持 string 便于未来跨 tool 扩展(届时 union 收合法字面量)。
6144
+ model: external_exports.string().min(1).optional()
6140
6145
  });
6141
6146
  DispatchCompleteArgsSchema = external_exports.object({
6142
6147
  dispatchId: external_exports.string().min(1),
@@ -7405,7 +7410,7 @@ var require_atomic_sleep = __commonJS({
7405
7410
  var require_sonic_boom = __commonJS({
7406
7411
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
7407
7412
  "use strict";
7408
- var fs70 = require("fs");
7413
+ var fs71 = require("fs");
7409
7414
  var EventEmitter3 = require("events");
7410
7415
  var inherits = require("util").inherits;
7411
7416
  var path77 = require("path");
@@ -7462,20 +7467,20 @@ var require_sonic_boom = __commonJS({
7462
7467
  const mode = sonic.mode;
7463
7468
  if (sonic.sync) {
7464
7469
  try {
7465
- if (sonic.mkdir) fs70.mkdirSync(path77.dirname(file), { recursive: true });
7466
- const fd = fs70.openSync(file, flags, mode);
7470
+ if (sonic.mkdir) fs71.mkdirSync(path77.dirname(file), { recursive: true });
7471
+ const fd = fs71.openSync(file, flags, mode);
7467
7472
  fileOpened(null, fd);
7468
7473
  } catch (err) {
7469
7474
  fileOpened(err);
7470
7475
  throw err;
7471
7476
  }
7472
7477
  } else if (sonic.mkdir) {
7473
- fs70.mkdir(path77.dirname(file), { recursive: true }, (err) => {
7478
+ fs71.mkdir(path77.dirname(file), { recursive: true }, (err) => {
7474
7479
  if (err) return fileOpened(err);
7475
- fs70.open(file, flags, mode, fileOpened);
7480
+ fs71.open(file, flags, mode, fileOpened);
7476
7481
  });
7477
7482
  } else {
7478
- fs70.open(file, flags, mode, fileOpened);
7483
+ fs71.open(file, flags, mode, fileOpened);
7479
7484
  }
7480
7485
  }
7481
7486
  function SonicBoom(opts) {
@@ -7516,8 +7521,8 @@ var require_sonic_boom = __commonJS({
7516
7521
  this.flush = flushBuffer;
7517
7522
  this.flushSync = flushBufferSync;
7518
7523
  this._actualWrite = actualWriteBuffer;
7519
- fsWriteSync = () => fs70.writeSync(this.fd, this._writingBuf);
7520
- fsWrite = () => fs70.write(this.fd, this._writingBuf, this.release);
7524
+ fsWriteSync = () => fs71.writeSync(this.fd, this._writingBuf);
7525
+ fsWrite = () => fs71.write(this.fd, this._writingBuf, this.release);
7521
7526
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
7522
7527
  this._writingBuf = "";
7523
7528
  this.write = write;
@@ -7526,15 +7531,15 @@ var require_sonic_boom = __commonJS({
7526
7531
  this._actualWrite = actualWrite;
7527
7532
  fsWriteSync = () => {
7528
7533
  if (Buffer.isBuffer(this._writingBuf)) {
7529
- return fs70.writeSync(this.fd, this._writingBuf);
7534
+ return fs71.writeSync(this.fd, this._writingBuf);
7530
7535
  }
7531
- return fs70.writeSync(this.fd, this._writingBuf, "utf8");
7536
+ return fs71.writeSync(this.fd, this._writingBuf, "utf8");
7532
7537
  };
7533
7538
  fsWrite = () => {
7534
7539
  if (Buffer.isBuffer(this._writingBuf)) {
7535
- return fs70.write(this.fd, this._writingBuf, this.release);
7540
+ return fs71.write(this.fd, this._writingBuf, this.release);
7536
7541
  }
7537
- return fs70.write(this.fd, this._writingBuf, "utf8", this.release);
7542
+ return fs71.write(this.fd, this._writingBuf, "utf8", this.release);
7538
7543
  };
7539
7544
  } else {
7540
7545
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -7591,7 +7596,7 @@ var require_sonic_boom = __commonJS({
7591
7596
  }
7592
7597
  }
7593
7598
  if (this._fsync) {
7594
- fs70.fsyncSync(this.fd);
7599
+ fs71.fsyncSync(this.fd);
7595
7600
  }
7596
7601
  const len = this._len;
7597
7602
  if (this._reopening) {
@@ -7705,7 +7710,7 @@ var require_sonic_boom = __commonJS({
7705
7710
  const onDrain = () => {
7706
7711
  if (!this._fsync) {
7707
7712
  try {
7708
- fs70.fsync(this.fd, (err) => {
7713
+ fs71.fsync(this.fd, (err) => {
7709
7714
  this._flushPending = false;
7710
7715
  cb(err);
7711
7716
  });
@@ -7807,7 +7812,7 @@ var require_sonic_boom = __commonJS({
7807
7812
  const fd = this.fd;
7808
7813
  this.once("ready", () => {
7809
7814
  if (fd !== this.fd) {
7810
- fs70.close(fd, (err) => {
7815
+ fs71.close(fd, (err) => {
7811
7816
  if (err) {
7812
7817
  return this.emit("error", err);
7813
7818
  }
@@ -7856,7 +7861,7 @@ var require_sonic_boom = __commonJS({
7856
7861
  buf = this._bufs[0];
7857
7862
  }
7858
7863
  try {
7859
- const n = Buffer.isBuffer(buf) ? fs70.writeSync(this.fd, buf) : fs70.writeSync(this.fd, buf, "utf8");
7864
+ const n = Buffer.isBuffer(buf) ? fs71.writeSync(this.fd, buf) : fs71.writeSync(this.fd, buf, "utf8");
7860
7865
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
7861
7866
  buf = releasedBufObj.writingBuf;
7862
7867
  this._len = releasedBufObj.len;
@@ -7872,7 +7877,7 @@ var require_sonic_boom = __commonJS({
7872
7877
  }
7873
7878
  }
7874
7879
  try {
7875
- fs70.fsyncSync(this.fd);
7880
+ fs71.fsyncSync(this.fd);
7876
7881
  } catch {
7877
7882
  }
7878
7883
  }
@@ -7893,7 +7898,7 @@ var require_sonic_boom = __commonJS({
7893
7898
  buf = mergeBuf(this._bufs[0], this._lens[0]);
7894
7899
  }
7895
7900
  try {
7896
- const n = fs70.writeSync(this.fd, buf);
7901
+ const n = fs71.writeSync(this.fd, buf);
7897
7902
  buf = buf.subarray(n);
7898
7903
  this._len = Math.max(this._len - n, 0);
7899
7904
  if (buf.length <= 0) {
@@ -7921,13 +7926,13 @@ var require_sonic_boom = __commonJS({
7921
7926
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
7922
7927
  if (this.sync) {
7923
7928
  try {
7924
- const written = Buffer.isBuffer(this._writingBuf) ? fs70.writeSync(this.fd, this._writingBuf) : fs70.writeSync(this.fd, this._writingBuf, "utf8");
7929
+ const written = Buffer.isBuffer(this._writingBuf) ? fs71.writeSync(this.fd, this._writingBuf) : fs71.writeSync(this.fd, this._writingBuf, "utf8");
7925
7930
  release(null, written);
7926
7931
  } catch (err) {
7927
7932
  release(err);
7928
7933
  }
7929
7934
  } else {
7930
- fs70.write(this.fd, this._writingBuf, release);
7935
+ fs71.write(this.fd, this._writingBuf, release);
7931
7936
  }
7932
7937
  }
7933
7938
  function actualWriteBuffer() {
@@ -7936,7 +7941,7 @@ var require_sonic_boom = __commonJS({
7936
7941
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
7937
7942
  if (this.sync) {
7938
7943
  try {
7939
- const written = fs70.writeSync(this.fd, this._writingBuf);
7944
+ const written = fs71.writeSync(this.fd, this._writingBuf);
7940
7945
  release(null, written);
7941
7946
  } catch (err) {
7942
7947
  release(err);
@@ -7945,7 +7950,7 @@ var require_sonic_boom = __commonJS({
7945
7950
  if (kCopyBuffer) {
7946
7951
  this._writingBuf = Buffer.from(this._writingBuf);
7947
7952
  }
7948
- fs70.write(this.fd, this._writingBuf, release);
7953
+ fs71.write(this.fd, this._writingBuf, release);
7949
7954
  }
7950
7955
  }
7951
7956
  function actualClose(sonic) {
@@ -7961,12 +7966,12 @@ var require_sonic_boom = __commonJS({
7961
7966
  sonic._lens = [];
7962
7967
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
7963
7968
  try {
7964
- fs70.fsync(sonic.fd, closeWrapped);
7969
+ fs71.fsync(sonic.fd, closeWrapped);
7965
7970
  } catch {
7966
7971
  }
7967
7972
  function closeWrapped() {
7968
7973
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7969
- fs70.close(sonic.fd, done);
7974
+ fs71.close(sonic.fd, done);
7970
7975
  } else {
7971
7976
  done();
7972
7977
  }
@@ -11359,7 +11364,7 @@ function newestSubagentMtimeMs(projectsRoot, cwd, toolSessionId) {
11359
11364
  const dir = import_node_path5.default.join(projectsRoot, cwdToHashDir(cwd), toolSessionId, "subagents");
11360
11365
  let entries;
11361
11366
  try {
11362
- entries = import_node_fs5.default.readdirSync(dir, { withFileTypes: true });
11367
+ entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
11363
11368
  } catch {
11364
11369
  return null;
11365
11370
  }
@@ -11368,7 +11373,7 @@ function newestSubagentMtimeMs(projectsRoot, cwd, toolSessionId) {
11368
11373
  if (!e.isFile()) continue;
11369
11374
  if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
11370
11375
  try {
11371
- const m2 = import_node_fs5.default.statSync(import_node_path5.default.join(dir, e.name)).mtimeMs;
11376
+ const m2 = import_node_fs6.default.statSync(import_node_path5.default.join(dir, e.name)).mtimeMs;
11372
11377
  if (newest === null || m2 > newest) newest = m2;
11373
11378
  } catch {
11374
11379
  }
@@ -11382,7 +11387,7 @@ function hashDirToCwd(hash) {
11382
11387
  function findTranscriptByToolSessionId(projectsRoot, toolSessionId) {
11383
11388
  let entries;
11384
11389
  try {
11385
- entries = import_node_fs5.default.readdirSync(projectsRoot, { withFileTypes: true });
11390
+ entries = import_node_fs6.default.readdirSync(projectsRoot, { withFileTypes: true });
11386
11391
  } catch {
11387
11392
  return null;
11388
11393
  }
@@ -11391,7 +11396,7 @@ function findTranscriptByToolSessionId(projectsRoot, toolSessionId) {
11391
11396
  if (!ent.isDirectory()) continue;
11392
11397
  const candidate = import_node_path5.default.join(projectsRoot, ent.name, `${toolSessionId}.jsonl`);
11393
11398
  try {
11394
- const st = import_node_fs5.default.statSync(candidate);
11399
+ const st = import_node_fs6.default.statSync(candidate);
11395
11400
  if (!best || st.mtimeMs > best.mtime) best = { p: candidate, mtime: st.mtimeMs };
11396
11401
  } catch {
11397
11402
  }
@@ -11402,7 +11407,7 @@ function deriveCwdFromTranscript(filePath) {
11402
11407
  const dirName = import_node_path5.default.basename(import_node_path5.default.dirname(filePath));
11403
11408
  let raw;
11404
11409
  try {
11405
- raw = import_node_fs5.default.readFileSync(filePath, "utf8");
11410
+ raw = import_node_fs6.default.readFileSync(filePath, "utf8");
11406
11411
  } catch {
11407
11412
  return null;
11408
11413
  }
@@ -11420,7 +11425,7 @@ function deriveCwdFromTranscript(filePath) {
11420
11425
  }
11421
11426
  function safeStatMtime(p2) {
11422
11427
  try {
11423
- return import_node_fs5.default.statSync(p2).mtimeMs;
11428
+ return import_node_fs6.default.statSync(p2).mtimeMs;
11424
11429
  } catch {
11425
11430
  return 0;
11426
11431
  }
@@ -11428,7 +11433,7 @@ function safeStatMtime(p2) {
11428
11433
  function readJsonlLines(file) {
11429
11434
  let raw;
11430
11435
  try {
11431
- raw = import_node_fs5.default.readFileSync(file, "utf8");
11436
+ raw = import_node_fs6.default.readFileSync(file, "utf8");
11432
11437
  } catch (err) {
11433
11438
  if (err.code === "ENOENT") return [];
11434
11439
  throw err;
@@ -11659,7 +11664,7 @@ function attachmentDeferredToolsText(a) {
11659
11664
  function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
11660
11665
  if (backupFileName === null) return null;
11661
11666
  try {
11662
- return import_node_fs5.default.readFileSync(
11667
+ return import_node_fs6.default.readFileSync(
11663
11668
  import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
11664
11669
  "utf8"
11665
11670
  );
@@ -11669,17 +11674,17 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
11669
11674
  }
11670
11675
  function readCurrentContent(filePath) {
11671
11676
  try {
11672
- return import_node_fs5.default.readFileSync(filePath, "utf8");
11677
+ return import_node_fs6.default.readFileSync(filePath, "utf8");
11673
11678
  } catch (err) {
11674
11679
  if (err.code === "ENOENT") return null;
11675
11680
  return null;
11676
11681
  }
11677
11682
  }
11678
- var import_node_fs5, import_node_os3, import_node_path5, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11683
+ var import_node_fs6, import_node_os3, import_node_path5, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11679
11684
  var init_claude_history = __esm({
11680
11685
  "src/tools/claude-history.ts"() {
11681
11686
  "use strict";
11682
- import_node_fs5 = __toESM(require("fs"), 1);
11687
+ import_node_fs6 = __toESM(require("fs"), 1);
11683
11688
  import_node_os3 = __toESM(require("os"), 1);
11684
11689
  import_node_path5 = __toESM(require("path"), 1);
11685
11690
  init_lib();
@@ -11712,7 +11717,7 @@ var init_claude_history = __esm({
11712
11717
  async listProjects() {
11713
11718
  let entries;
11714
11719
  try {
11715
- entries = import_node_fs5.default.readdirSync(this.projectsRoot, { withFileTypes: true });
11720
+ entries = import_node_fs6.default.readdirSync(this.projectsRoot, { withFileTypes: true });
11716
11721
  } catch (err) {
11717
11722
  if (err.code === "ENOENT") return [];
11718
11723
  throw err;
@@ -11721,7 +11726,7 @@ var init_claude_history = __esm({
11721
11726
  for (const ent of entries) {
11722
11727
  if (!ent.isDirectory()) continue;
11723
11728
  const dir = import_node_path5.default.join(this.projectsRoot, ent.name);
11724
- const files = import_node_fs5.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11729
+ const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11725
11730
  const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path5.default.join(dir, f))), 0);
11726
11731
  out.push({
11727
11732
  projectPath: hashDirToCwd(ent.name),
@@ -11737,7 +11742,7 @@ var init_claude_history = __esm({
11737
11742
  const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
11738
11743
  let files;
11739
11744
  try {
11740
- files = import_node_fs5.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11745
+ files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11741
11746
  } catch (err) {
11742
11747
  if (err.code === "ENOENT") return [];
11743
11748
  throw err;
@@ -11844,7 +11849,7 @@ var init_claude_history = __esm({
11844
11849
  );
11845
11850
  let entries;
11846
11851
  try {
11847
- entries = import_node_fs5.default.readdirSync(dir, { withFileTypes: true });
11852
+ entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
11848
11853
  } catch (err) {
11849
11854
  if (err.code === "ENOENT") return null;
11850
11855
  return null;
@@ -11915,7 +11920,7 @@ var init_claude_history = __esm({
11915
11920
  );
11916
11921
  let exists = false;
11917
11922
  try {
11918
- exists = import_node_fs5.default.statSync(file).isFile();
11923
+ exists = import_node_fs6.default.statSync(file).isFile();
11919
11924
  } catch {
11920
11925
  return null;
11921
11926
  }
@@ -12091,13 +12096,13 @@ var init_claude_history = __esm({
12091
12096
  function probeViaWhich() {
12092
12097
  try {
12093
12098
  const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
12094
- if (out && import_node_fs15.default.existsSync(out)) return out;
12099
+ if (out && import_node_fs16.default.existsSync(out)) return out;
12095
12100
  } catch {
12096
12101
  }
12097
12102
  return null;
12098
12103
  }
12099
12104
  async function probeClaude(env = process.env) {
12100
- if (env.CLAUDE_BIN && import_node_fs15.default.existsSync(env.CLAUDE_BIN)) {
12105
+ if (env.CLAUDE_BIN && import_node_fs16.default.existsSync(env.CLAUDE_BIN)) {
12101
12106
  return { available: true, path: env.CLAUDE_BIN };
12102
12107
  }
12103
12108
  const w2 = probeViaWhich();
@@ -12542,13 +12547,13 @@ function encodeClaudeStdin(text) {
12542
12547
  };
12543
12548
  return JSON.stringify(frame) + "\n";
12544
12549
  }
12545
- var import_node_child_process, import_node_child_process2, import_node_fs15, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
12550
+ 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;
12546
12551
  var init_claude = __esm({
12547
12552
  "src/tools/claude.ts"() {
12548
12553
  "use strict";
12549
12554
  import_node_child_process = require("child_process");
12550
12555
  import_node_child_process2 = require("child_process");
12551
- import_node_fs15 = __toESM(require("fs"), 1);
12556
+ import_node_fs16 = __toESM(require("fs"), 1);
12552
12557
  init_protocol();
12553
12558
  init_claude_history();
12554
12559
  init_tool_result_extra();
@@ -12568,13 +12573,17 @@ var init_claude = __esm({
12568
12573
  gif: "image/gif",
12569
12574
  webp: "image/webp"
12570
12575
  };
12576
+ CLAUDE_MODEL_IDS = ["opus", "fable", "sonnet", "haiku"];
12571
12577
  CLAUDE_MODELS = [
12572
- { id: "", label: "Default", description: "CLI default model", contextWindowSize: 2e5, default: true },
12578
+ { id: "", label: "Default", description: "CLI default model", contextWindowSize: 1e6, default: true },
12573
12579
  { id: "opus", label: "Opus", description: "Most capable", contextWindowSize: 1e6 },
12574
- { id: "fable", label: "Fable", contextWindowSize: 2e5 },
12575
- { id: "sonnet", label: "Sonnet", description: "Fast, balanced", contextWindowSize: 2e5 },
12576
- { id: "haiku", label: "Haiku", description: "Fastest, lightest", contextWindowSize: 2e5 }
12580
+ { id: "fable", label: "Fable", contextWindowSize: 1e6 },
12581
+ { id: "sonnet", label: "Sonnet", description: "Fast, balanced", contextWindowSize: 1e6 },
12582
+ { id: "haiku", label: "Haiku", description: "Fastest, lightest", contextWindowSize: 1e6 }
12577
12583
  ];
12584
+ _assertModelIdsAligned = CLAUDE_MODELS.filter(
12585
+ (m2) => m2.id !== ""
12586
+ ).map((m2) => m2.id);
12578
12587
  CLAUDE_PERMISSION_MODES = [
12579
12588
  { id: "", label: "Default", description: "Ask for every tool call" },
12580
12589
  { id: "plan", label: "Plan", description: "Read-only, no code changes" },
@@ -40301,8 +40310,8 @@ function startRunCaseRecorder(opts) {
40301
40310
  });
40302
40311
  const ensureStream = () => {
40303
40312
  if (stream) return stream;
40304
- import_node_fs52.default.mkdirSync(dir, { recursive: true });
40305
- stream = import_node_fs52.default.createWriteStream(opts.recordPath, { flags: "a" });
40313
+ import_node_fs53.default.mkdirSync(dir, { recursive: true });
40314
+ stream = import_node_fs53.default.createWriteStream(opts.recordPath, { flags: "a" });
40306
40315
  stream.on("close", () => closedResolve());
40307
40316
  return stream;
40308
40317
  };
@@ -40327,11 +40336,11 @@ function startRunCaseRecorder(opts) {
40327
40336
  };
40328
40337
  return { tap, close, closed };
40329
40338
  }
40330
- var import_node_fs52, import_node_path65;
40339
+ var import_node_fs53, import_node_path65;
40331
40340
  var init_recorder = __esm({
40332
40341
  "src/run-case/recorder.ts"() {
40333
40342
  "use strict";
40334
- import_node_fs52 = __toESM(require("fs"), 1);
40343
+ import_node_fs53 = __toESM(require("fs"), 1);
40335
40344
  import_node_path65 = __toESM(require("path"), 1);
40336
40345
  }
40337
40346
  });
@@ -40375,7 +40384,7 @@ var init_wire = __esm({
40375
40384
  // src/run-case/controller.ts
40376
40385
  async function runController(opts) {
40377
40386
  const now = opts.now ?? Date.now;
40378
- const cwd = opts.cwd ?? (0, import_node_fs53.mkdtempSync)(import_node_path66.default.join(import_node_os22.default.tmpdir(), "clawd-runcase-"));
40387
+ const cwd = opts.cwd ?? (0, import_node_fs54.mkdtempSync)(import_node_path66.default.join(import_node_os22.default.tmpdir(), "clawd-runcase-"));
40379
40388
  const ownsCwd = opts.cwd === void 0;
40380
40389
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
40381
40390
  const spawnCtx = { cwd };
@@ -40536,17 +40545,17 @@ async function runController(opts) {
40536
40545
  if (sigintHandler) process.off("SIGINT", sigintHandler);
40537
40546
  if (ownsCwd) {
40538
40547
  try {
40539
- (0, import_node_fs53.rmSync)(cwd, { recursive: true, force: true });
40548
+ (0, import_node_fs54.rmSync)(cwd, { recursive: true, force: true });
40540
40549
  } catch {
40541
40550
  }
40542
40551
  }
40543
40552
  return exitCode ?? 0;
40544
40553
  }
40545
- var import_node_fs53, import_node_os22, import_node_path66;
40554
+ var import_node_fs54, import_node_os22, import_node_path66;
40546
40555
  var init_controller = __esm({
40547
40556
  "src/run-case/controller.ts"() {
40548
40557
  "use strict";
40549
- import_node_fs53 = require("fs");
40558
+ import_node_fs54 = require("fs");
40550
40559
  import_node_os22 = __toESM(require("os"), 1);
40551
40560
  import_node_path66 = __toESM(require("path"), 1);
40552
40561
  init_claude();
@@ -40943,7 +40952,7 @@ Env (advanced):
40943
40952
 
40944
40953
  // src/index.ts
40945
40954
  var import_node_path64 = __toESM(require("path"), 1);
40946
- var import_node_fs51 = __toESM(require("fs"), 1);
40955
+ var import_node_fs52 = __toESM(require("fs"), 1);
40947
40956
  var import_node_os21 = __toESM(require("os"), 1);
40948
40957
 
40949
40958
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
@@ -41084,6 +41093,35 @@ function pinoLevelToString(n) {
41084
41093
  return null;
41085
41094
  }
41086
41095
 
41096
+ // src/log-size-cap.ts
41097
+ var import_node_fs3 = __toESM(require("fs"), 1);
41098
+ function truncateLogFileToTail(file, maxBytes, keepBytes) {
41099
+ let size;
41100
+ try {
41101
+ size = import_node_fs3.default.statSync(file).size;
41102
+ } catch {
41103
+ return;
41104
+ }
41105
+ if (size <= maxBytes) return;
41106
+ let fd;
41107
+ try {
41108
+ fd = import_node_fs3.default.openSync(file, "r");
41109
+ } catch {
41110
+ return;
41111
+ }
41112
+ try {
41113
+ const buf = Buffer.allocUnsafe(keepBytes);
41114
+ import_node_fs3.default.readSync(fd, buf, 0, keepBytes, size - keepBytes);
41115
+ import_node_fs3.default.writeFileSync(file, buf);
41116
+ } catch {
41117
+ } finally {
41118
+ try {
41119
+ import_node_fs3.default.closeSync(fd);
41120
+ } catch {
41121
+ }
41122
+ }
41123
+ }
41124
+
41087
41125
  // ../log-client/dist/index.js
41088
41126
  var DEFAULT_BATCH = {
41089
41127
  maxRecords: 100,
@@ -41364,7 +41402,7 @@ function buildRecord(input, identity, source, homeDir, now) {
41364
41402
  var path5 = __toESM(require("path"), 1);
41365
41403
 
41366
41404
  // src/session/store.ts
41367
- var import_node_fs3 = __toESM(require("fs"), 1);
41405
+ var import_node_fs4 = __toESM(require("fs"), 1);
41368
41406
  var import_node_path3 = __toESM(require("path"), 1);
41369
41407
  init_protocol();
41370
41408
 
@@ -41453,11 +41491,11 @@ var SessionStore = class {
41453
41491
  return import_node_path3.default.join(this.root, `${safeFileName(sessionId)}.json`);
41454
41492
  }
41455
41493
  ensureDir() {
41456
- import_node_fs3.default.mkdirSync(this.root, { recursive: true });
41494
+ import_node_fs4.default.mkdirSync(this.root, { recursive: true });
41457
41495
  }
41458
41496
  read(sessionId) {
41459
41497
  try {
41460
- const raw = import_node_fs3.default.readFileSync(this.filePath(sessionId), "utf8");
41498
+ const raw = import_node_fs4.default.readFileSync(this.filePath(sessionId), "utf8");
41461
41499
  const parsed = JSON.parse(raw);
41462
41500
  return SessionFileSchema.parse(parsed);
41463
41501
  } catch (err) {
@@ -41471,13 +41509,13 @@ var SessionStore = class {
41471
41509
  this.ensureDir();
41472
41510
  const target = this.filePath(validated.sessionId);
41473
41511
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
41474
- import_node_fs3.default.writeFileSync(tmp, JSON.stringify(validated, null, 2), { encoding: "utf8", mode: 384 });
41475
- import_node_fs3.default.renameSync(tmp, target);
41512
+ import_node_fs4.default.writeFileSync(tmp, JSON.stringify(validated, null, 2), { encoding: "utf8", mode: 384 });
41513
+ import_node_fs4.default.renameSync(tmp, target);
41476
41514
  return validated;
41477
41515
  }
41478
41516
  delete(sessionId) {
41479
41517
  try {
41480
- import_node_fs3.default.unlinkSync(this.filePath(sessionId));
41518
+ import_node_fs4.default.unlinkSync(this.filePath(sessionId));
41481
41519
  return true;
41482
41520
  } catch (err) {
41483
41521
  const code = err?.code;
@@ -41488,7 +41526,7 @@ var SessionStore = class {
41488
41526
  list() {
41489
41527
  let entries;
41490
41528
  try {
41491
- entries = import_node_fs3.default.readdirSync(this.root);
41529
+ entries = import_node_fs4.default.readdirSync(this.root);
41492
41530
  } catch (err) {
41493
41531
  const code = err?.code;
41494
41532
  if (code === "ENOENT") return [];
@@ -41500,7 +41538,7 @@ var SessionStore = class {
41500
41538
  if (name.includes(".tmp-")) continue;
41501
41539
  const full = import_node_path3.default.join(this.root, name);
41502
41540
  try {
41503
- const raw = import_node_fs3.default.readFileSync(full, "utf8");
41541
+ const raw = import_node_fs4.default.readFileSync(full, "utf8");
41504
41542
  const parsed = JSON.parse(raw);
41505
41543
  const validated = SessionFileSchema.parse(parsed);
41506
41544
  out.push(validated);
@@ -41573,7 +41611,7 @@ var SessionStoreFactory = class {
41573
41611
  };
41574
41612
 
41575
41613
  // src/session/manager.ts
41576
- var import_node_fs8 = __toESM(require("fs"), 1);
41614
+ var import_node_fs9 = __toESM(require("fs"), 1);
41577
41615
  var import_node_path9 = __toESM(require("path"), 1);
41578
41616
  var import_node_os5 = __toESM(require("os"), 1);
41579
41617
  init_protocol();
@@ -41665,13 +41703,13 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
41665
41703
  }
41666
41704
 
41667
41705
  // src/tools/owner-credentials.ts
41668
- var import_node_fs4 = __toESM(require("fs"), 1);
41706
+ var import_node_fs5 = __toESM(require("fs"), 1);
41669
41707
  var import_node_path4 = __toESM(require("path"), 1);
41670
41708
  function readOwnerCredentials(homeDir, logger) {
41671
41709
  const settingsPath = import_node_path4.default.join(homeDir, ".claude", "settings.json");
41672
41710
  let raw;
41673
41711
  try {
41674
- raw = import_node_fs4.default.readFileSync(settingsPath, "utf8");
41712
+ raw = import_node_fs5.default.readFileSync(settingsPath, "utf8");
41675
41713
  } catch (err) {
41676
41714
  const code = err.code;
41677
41715
  if (code === "ENOENT") return null;
@@ -42715,7 +42753,7 @@ init_permission_stdio();
42715
42753
  init_claude_history();
42716
42754
 
42717
42755
  // src/ipc-recorder.ts
42718
- var import_node_fs6 = __toESM(require("fs"), 1);
42756
+ var import_node_fs7 = __toESM(require("fs"), 1);
42719
42757
  var import_node_path6 = __toESM(require("path"), 1);
42720
42758
  function tsForFilename(ms) {
42721
42759
  return new Date(ms).toISOString().replace(/[:.]/g, "-");
@@ -42737,8 +42775,8 @@ function startRecorder(opts) {
42737
42775
  let exited = false;
42738
42776
  const ensureStream = () => {
42739
42777
  if (stream) return stream;
42740
- import_node_fs6.default.mkdirSync(dir, { recursive: true });
42741
- stream = import_node_fs6.default.createWriteStream(filePath, { flags: "a" });
42778
+ import_node_fs7.default.mkdirSync(dir, { recursive: true });
42779
+ stream = import_node_fs7.default.createWriteStream(filePath, { flags: "a" });
42742
42780
  stream.on("close", () => closedResolve());
42743
42781
  return stream;
42744
42782
  };
@@ -43206,7 +43244,7 @@ function extractEditPath(input) {
43206
43244
  }
43207
43245
 
43208
43246
  // src/debug/pty-probe.ts
43209
- var import_node_fs7 = __toESM(require("fs"), 1);
43247
+ var import_node_fs8 = __toESM(require("fs"), 1);
43210
43248
  var import_node_path8 = __toESM(require("path"), 1);
43211
43249
  var PROBE_DIR = "/tmp/clawd-probe";
43212
43250
  var EVENTS_FILE = import_node_path8.default.join(PROBE_DIR, "events.jsonl");
@@ -43214,7 +43252,7 @@ var inited = false;
43214
43252
  function ensureDir() {
43215
43253
  if (inited) return true;
43216
43254
  try {
43217
- import_node_fs7.default.mkdirSync(PROBE_DIR, { recursive: true });
43255
+ import_node_fs8.default.mkdirSync(PROBE_DIR, { recursive: true });
43218
43256
  inited = true;
43219
43257
  return true;
43220
43258
  } catch {
@@ -43225,7 +43263,7 @@ function probeEvent(event, data = {}) {
43225
43263
  try {
43226
43264
  if (!ensureDir()) return;
43227
43265
  const line = JSON.stringify({ ts: Date.now(), event, ...data }) + "\n";
43228
- import_node_fs7.default.appendFileSync(EVENTS_FILE, line);
43266
+ import_node_fs8.default.appendFileSync(EVENTS_FILE, line);
43229
43267
  } catch {
43230
43268
  }
43231
43269
  }
@@ -43233,7 +43271,7 @@ function probeDumpReplay(sessionId, payload) {
43233
43271
  try {
43234
43272
  if (!ensureDir()) return "";
43235
43273
  const file = import_node_path8.default.join(PROBE_DIR, `replay-${sessionId}-${Date.now()}.ans`);
43236
- import_node_fs7.default.writeFileSync(file, payload, "utf8");
43274
+ import_node_fs8.default.writeFileSync(file, payload, "utf8");
43237
43275
  return file;
43238
43276
  } catch {
43239
43277
  return "";
@@ -43481,7 +43519,7 @@ var SessionManager = class {
43481
43519
  const root = this.deps.storeFactory ? import_node_path9.default.join(this.deps.dataDir, "personas") : import_node_path9.default.join(this.deps.dataDir, "sessions");
43482
43520
  let entries;
43483
43521
  try {
43484
- entries = import_node_fs8.default.readdirSync(root, { withFileTypes: true });
43522
+ entries = import_node_fs9.default.readdirSync(root, { withFileTypes: true });
43485
43523
  } catch (err) {
43486
43524
  const code = err?.code;
43487
43525
  if (code === "ENOENT") return [];
@@ -43504,7 +43542,7 @@ var SessionManager = class {
43504
43542
  );
43505
43543
  let entries;
43506
43544
  try {
43507
- entries = import_node_fs8.default.readdirSync(root, { withFileTypes: true });
43545
+ entries = import_node_fs9.default.readdirSync(root, { withFileTypes: true });
43508
43546
  } catch (err) {
43509
43547
  const code = err?.code;
43510
43548
  if (code === "ENOENT") return [];
@@ -43623,7 +43661,7 @@ var SessionManager = class {
43623
43661
  callerDisplayName
43624
43662
  );
43625
43663
  if (subSessionMeta?.userWorkDir) {
43626
- import_node_fs8.default.mkdirSync(subSessionMeta.userWorkDir, { recursive: true });
43664
+ import_node_fs9.default.mkdirSync(subSessionMeta.userWorkDir, { recursive: true });
43627
43665
  }
43628
43666
  if (scope.kind === "persona" && scope.mode === "guest") {
43629
43667
  if (!this.deps.personaRoot || !subSessionMeta?.userWorkDir) {
@@ -43805,7 +43843,7 @@ var SessionManager = class {
43805
43843
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "cwd required when ownerPersonaId is absent");
43806
43844
  }
43807
43845
  try {
43808
- const stat = import_node_fs8.default.statSync(cwd);
43846
+ const stat = import_node_fs9.default.statSync(cwd);
43809
43847
  if (!stat.isDirectory()) throw new Error("not dir");
43810
43848
  } catch {
43811
43849
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${cwd}`);
@@ -44368,7 +44406,7 @@ var SessionManager = class {
44368
44406
  */
44369
44407
  createForScope(args) {
44370
44408
  try {
44371
- const stat = import_node_fs8.default.statSync(args.cwd);
44409
+ const stat = import_node_fs9.default.statSync(args.cwd);
44372
44410
  if (!stat.isDirectory()) throw new Error("not dir");
44373
44411
  } catch {
44374
44412
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
@@ -44602,6 +44640,8 @@ var SessionManager = class {
44602
44640
  creatorPrincipalId: args.guestPrincipalId,
44603
44641
  ...args.guestDisplayName ? { creatorDisplayName: args.guestDisplayName } : {}
44604
44642
  } : {},
44643
+ // T-20:dispatch model override 落盘(reducer spawn 路径读 SessionFile.model 生成 --model flag)
44644
+ ...args.model ? { model: args.model } : {},
44605
44645
  createdAt: now,
44606
44646
  updatedAt: now
44607
44647
  };
@@ -45171,13 +45211,13 @@ var SessionManager = class {
45171
45211
  };
45172
45212
 
45173
45213
  // src/persona/store.ts
45174
- var fs9 = __toESM(require("fs"), 1);
45214
+ var fs10 = __toESM(require("fs"), 1);
45175
45215
  var path12 = __toESM(require("path"), 1);
45176
45216
  init_protocol();
45177
45217
  var PersonaStore = class {
45178
45218
  constructor(root) {
45179
45219
  this.root = root;
45180
- fs9.mkdirSync(root, { recursive: true });
45220
+ fs10.mkdirSync(root, { recursive: true });
45181
45221
  }
45182
45222
  root;
45183
45223
  personaDir(personaId) {
@@ -45205,7 +45245,7 @@ var PersonaStore = class {
45205
45245
  }
45206
45246
  write(persona, personality) {
45207
45247
  const dir = this.personaDir(persona.personaId);
45208
- fs9.mkdirSync(path12.join(dir, ".clawd"), { recursive: true });
45248
+ fs10.mkdirSync(path12.join(dir, ".clawd"), { recursive: true });
45209
45249
  this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
45210
45250
  this.atomicWrite(this.agentsMdPath(persona.personaId), personality);
45211
45251
  this.writeSandboxSettings(persona.personaId, buildGuestSettingsV1());
@@ -45224,9 +45264,9 @@ var PersonaStore = class {
45224
45264
  ensureAgentsMirror(personaId) {
45225
45265
  const claudeMd = this.claudeMdPath(personaId);
45226
45266
  const agentsMd = this.agentsMdPath(personaId);
45227
- if (!fs9.existsSync(claudeMd)) return false;
45228
- if (fs9.existsSync(agentsMd)) return false;
45229
- this.atomicWrite(agentsMd, fs9.readFileSync(claudeMd, "utf8"));
45267
+ if (!fs10.existsSync(claudeMd)) return false;
45268
+ if (fs10.existsSync(agentsMd)) return false;
45269
+ this.atomicWrite(agentsMd, fs10.readFileSync(claudeMd, "utf8"));
45230
45270
  return true;
45231
45271
  }
45232
45272
  /**
@@ -45255,9 +45295,9 @@ var PersonaStore = class {
45255
45295
  /** 读 codex-sandbox.json;不存在/损坏 → null。 */
45256
45296
  readCodexSandboxSettings(personaId) {
45257
45297
  const p2 = this.codexSandboxSettingsPath(personaId);
45258
- if (!fs9.existsSync(p2)) return null;
45298
+ if (!fs10.existsSync(p2)) return null;
45259
45299
  try {
45260
- return CodexSandboxSettingsSchema.parse(JSON.parse(fs9.readFileSync(p2, "utf8")));
45300
+ return CodexSandboxSettingsSchema.parse(JSON.parse(fs10.readFileSync(p2, "utf8")));
45261
45301
  } catch {
45262
45302
  return null;
45263
45303
  }
@@ -45265,7 +45305,7 @@ var PersonaStore = class {
45265
45305
  /** 覆盖写 codex-sandbox.json(seed/migrate 用)。 */
45266
45306
  writeCodexSandboxSettings(personaId, settings) {
45267
45307
  const dir = path12.join(this.personaDir(personaId), ".clawd");
45268
- fs9.mkdirSync(dir, { recursive: true });
45308
+ fs10.mkdirSync(dir, { recursive: true });
45269
45309
  this.atomicWrite(this.codexSandboxSettingsPath(personaId), JSON.stringify(settings, null, 2));
45270
45310
  }
45271
45311
  writeMeta(persona) {
@@ -45273,8 +45313,8 @@ var PersonaStore = class {
45273
45313
  }
45274
45314
  read(personaId) {
45275
45315
  const p2 = this.metaPath(personaId);
45276
- if (!fs9.existsSync(p2)) return null;
45277
- const raw = JSON.parse(fs9.readFileSync(p2, "utf8"));
45316
+ if (!fs10.existsSync(p2)) return null;
45317
+ const raw = JSON.parse(fs10.readFileSync(p2, "utf8"));
45278
45318
  if (raw && typeof raw === "object" && "tokenMap" in raw) {
45279
45319
  delete raw.tokenMap;
45280
45320
  this.atomicWrite(p2, JSON.stringify(raw, null, 2));
@@ -45282,13 +45322,13 @@ var PersonaStore = class {
45282
45322
  return PersonaFileSchema.parse(raw);
45283
45323
  }
45284
45324
  has(personaId) {
45285
- return fs9.existsSync(this.metaPath(personaId));
45325
+ return fs10.existsSync(this.metaPath(personaId));
45286
45326
  }
45287
45327
  readPersonality(personaId) {
45288
45328
  const claudeMd = this.claudeMdPath(personaId);
45289
- if (fs9.existsSync(claudeMd)) return fs9.readFileSync(claudeMd, "utf8");
45329
+ if (fs10.existsSync(claudeMd)) return fs10.readFileSync(claudeMd, "utf8");
45290
45330
  const agentsMd = this.agentsMdPath(personaId);
45291
- if (fs9.existsSync(agentsMd)) return fs9.readFileSync(agentsMd, "utf8");
45331
+ if (fs10.existsSync(agentsMd)) return fs10.readFileSync(agentsMd, "utf8");
45292
45332
  return null;
45293
45333
  }
45294
45334
  /**
@@ -45297,9 +45337,9 @@ var PersonaStore = class {
45297
45337
  */
45298
45338
  readSandboxSettings(personaId) {
45299
45339
  const p2 = this.sandboxSettingsPath(personaId);
45300
- if (!fs9.existsSync(p2)) return null;
45340
+ if (!fs10.existsSync(p2)) return null;
45301
45341
  try {
45302
- return JSON.parse(fs9.readFileSync(p2, "utf8"));
45342
+ return JSON.parse(fs10.readFileSync(p2, "utf8"));
45303
45343
  } catch {
45304
45344
  return null;
45305
45345
  }
@@ -45328,10 +45368,10 @@ var PersonaStore = class {
45328
45368
  */
45329
45369
  readEnabledPlugins(personaId) {
45330
45370
  const p2 = this.claudeSettingsPath(personaId);
45331
- if (!fs9.existsSync(p2)) return [];
45371
+ if (!fs10.existsSync(p2)) return [];
45332
45372
  let raw;
45333
45373
  try {
45334
- raw = JSON.parse(fs9.readFileSync(p2, "utf8"));
45374
+ raw = JSON.parse(fs10.readFileSync(p2, "utf8"));
45335
45375
  } catch {
45336
45376
  return [];
45337
45377
  }
@@ -45345,22 +45385,22 @@ var PersonaStore = class {
45345
45385
  return out;
45346
45386
  }
45347
45387
  list() {
45348
- if (!fs9.existsSync(this.root)) return [];
45349
- return fs9.readdirSync(this.root).filter((name) => {
45350
- return fs9.existsSync(path12.join(this.root, name, ".clawd", "persona.json"));
45388
+ if (!fs10.existsSync(this.root)) return [];
45389
+ return fs10.readdirSync(this.root).filter((name) => {
45390
+ return fs10.existsSync(path12.join(this.root, name, ".clawd", "persona.json"));
45351
45391
  });
45352
45392
  }
45353
45393
  remove(personaId) {
45354
45394
  const dir = this.personaDir(personaId);
45355
- if (fs9.existsSync(dir)) fs9.rmSync(dir, { recursive: true, force: true });
45395
+ if (fs10.existsSync(dir)) fs10.rmSync(dir, { recursive: true, force: true });
45356
45396
  }
45357
45397
  personaDirPath(personaId) {
45358
45398
  return this.personaDir(personaId);
45359
45399
  }
45360
45400
  atomicWrite(file, content) {
45361
45401
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
45362
- fs9.writeFileSync(tmp, content, { mode: 384 });
45363
- fs9.renameSync(tmp, file);
45402
+ fs10.writeFileSync(tmp, content, { mode: 384 });
45403
+ fs10.renameSync(tmp, file);
45364
45404
  }
45365
45405
  };
45366
45406
 
@@ -45406,7 +45446,7 @@ var PersonaRegistry = class {
45406
45446
  var import_node_crypto3 = __toESM(require("crypto"), 1);
45407
45447
 
45408
45448
  // src/skills/scanner.ts
45409
- var import_node_fs9 = __toESM(require("fs"), 1);
45449
+ var import_node_fs10 = __toESM(require("fs"), 1);
45410
45450
  var import_node_os6 = __toESM(require("os"), 1);
45411
45451
  var import_node_path10 = __toESM(require("path"), 1);
45412
45452
 
@@ -45517,7 +45557,7 @@ function parseDescription(content) {
45517
45557
  }
45518
45558
  function isDirLikeSync(p2) {
45519
45559
  try {
45520
- return import_node_fs9.default.statSync(p2).isDirectory();
45560
+ return import_node_fs10.default.statSync(p2).isDirectory();
45521
45561
  } catch {
45522
45562
  return false;
45523
45563
  }
@@ -45525,7 +45565,7 @@ function isDirLikeSync(p2) {
45525
45565
  function scanSkillDir(dir, source, seen, out, pluginName) {
45526
45566
  let entries;
45527
45567
  try {
45528
- entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
45568
+ entries = import_node_fs10.default.readdirSync(dir, { withFileTypes: true });
45529
45569
  } catch {
45530
45570
  return;
45531
45571
  }
@@ -45534,10 +45574,10 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
45534
45574
  if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
45535
45575
  let content;
45536
45576
  try {
45537
- content = import_node_fs9.default.readFileSync(import_node_path10.default.join(entryPath, "SKILL.md"), "utf8");
45577
+ content = import_node_fs10.default.readFileSync(import_node_path10.default.join(entryPath, "SKILL.md"), "utf8");
45538
45578
  } catch {
45539
45579
  try {
45540
- content = import_node_fs9.default.readFileSync(import_node_path10.default.join(entryPath, "skill.md"), "utf8");
45580
+ content = import_node_fs10.default.readFileSync(import_node_path10.default.join(entryPath, "skill.md"), "utf8");
45541
45581
  } catch {
45542
45582
  continue;
45543
45583
  }
@@ -45561,7 +45601,7 @@ function listSkillsForDir(dir, source) {
45561
45601
  function scanCommandDir(dir, source, seen, out, pluginName) {
45562
45602
  let entries;
45563
45603
  try {
45564
- entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
45604
+ entries = import_node_fs10.default.readdirSync(dir, { withFileTypes: true });
45565
45605
  } catch {
45566
45606
  return;
45567
45607
  }
@@ -45571,7 +45611,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
45571
45611
  const ns = ent.name;
45572
45612
  let subEntries;
45573
45613
  try {
45574
- subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
45614
+ subEntries = import_node_fs10.default.readdirSync(entryPath, { withFileTypes: true });
45575
45615
  } catch {
45576
45616
  continue;
45577
45617
  }
@@ -45580,7 +45620,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
45580
45620
  const sePath = import_node_path10.default.join(entryPath, se.name);
45581
45621
  let content;
45582
45622
  try {
45583
- content = import_node_fs9.default.readFileSync(sePath, "utf8");
45623
+ content = import_node_fs10.default.readFileSync(sePath, "utf8");
45584
45624
  } catch {
45585
45625
  continue;
45586
45626
  }
@@ -45597,7 +45637,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
45597
45637
  } else if (ent.name.endsWith(".md")) {
45598
45638
  let content;
45599
45639
  try {
45600
- content = import_node_fs9.default.readFileSync(entryPath, "utf8");
45640
+ content = import_node_fs10.default.readFileSync(entryPath, "utf8");
45601
45641
  } catch {
45602
45642
  continue;
45603
45643
  }
@@ -45616,7 +45656,7 @@ function readInstalledPlugins(home) {
45616
45656
  const file = import_node_path10.default.join(home, ".claude", "plugins", "installed_plugins.json");
45617
45657
  let raw;
45618
45658
  try {
45619
- raw = import_node_fs9.default.readFileSync(file, "utf8");
45659
+ raw = import_node_fs10.default.readFileSync(file, "utf8");
45620
45660
  } catch {
45621
45661
  return [];
45622
45662
  }
@@ -45777,7 +45817,7 @@ var PersonaManager = class {
45777
45817
  };
45778
45818
 
45779
45819
  // src/persona/seed.ts
45780
- var fs11 = __toESM(require("fs"), 1);
45820
+ var fs12 = __toESM(require("fs"), 1);
45781
45821
  var path14 = __toESM(require("path"), 1);
45782
45822
  var import_node_url = require("url");
45783
45823
  var import_meta = {};
@@ -45948,7 +45988,7 @@ function bundleSiblingFromArgv(argv1, sibling) {
45948
45988
  if (!argv1) return null;
45949
45989
  let real = argv1;
45950
45990
  try {
45951
- real = fs11.realpathSync(argv1);
45991
+ real = fs12.realpathSync(argv1);
45952
45992
  } catch {
45953
45993
  }
45954
45994
  return path14.resolve(path14.dirname(real), sibling);
@@ -45965,7 +46005,7 @@ function findDefaultsRoot(logger) {
45965
46005
  if (fromArgv) candidates.push(fromArgv);
45966
46006
  for (const c of candidates) {
45967
46007
  try {
45968
- if (fs11.statSync(c).isDirectory()) {
46008
+ if (fs12.statSync(c).isDirectory()) {
45969
46009
  logger?.info("persona.defaults-root.resolved", { root: c });
45970
46010
  return c;
45971
46011
  }
@@ -45983,7 +46023,7 @@ function seedDefaultPersonas(args) {
45983
46023
  continue;
45984
46024
  }
45985
46025
  const bundleDir = path14.join(args.defaultsRoot, entry.personaId);
45986
- if (!fs11.existsSync(bundleDir)) {
46026
+ if (!fs12.existsSync(bundleDir)) {
45987
46027
  args.logger.warn("persona.seed.skip", {
45988
46028
  personaId: entry.personaId,
45989
46029
  reason: "bundle-missing",
@@ -45992,7 +46032,7 @@ function seedDefaultPersonas(args) {
45992
46032
  continue;
45993
46033
  }
45994
46034
  const claudeMdPath = path14.join(bundleDir, "CLAUDE.md");
45995
- if (!fs11.existsSync(claudeMdPath)) {
46035
+ if (!fs12.existsSync(claudeMdPath)) {
45996
46036
  args.logger.warn("persona.seed.skip", {
45997
46037
  personaId: entry.personaId,
45998
46038
  reason: "no-CLAUDE.md",
@@ -46000,7 +46040,7 @@ function seedDefaultPersonas(args) {
46000
46040
  });
46001
46041
  continue;
46002
46042
  }
46003
- const personality = fs11.readFileSync(claudeMdPath, "utf8");
46043
+ const personality = fs12.readFileSync(claudeMdPath, "utf8");
46004
46044
  const now = Date.now();
46005
46045
  const persona = {
46006
46046
  personaId: entry.personaId,
@@ -46029,14 +46069,14 @@ function skipNodeModulesUnder(srcRoot) {
46029
46069
  return (src) => !path14.relative(srcRoot, src).split(path14.sep).includes("node_modules");
46030
46070
  }
46031
46071
  function copyBundleExtras(srcDir, dstDir) {
46032
- for (const entry of fs11.readdirSync(srcDir, { withFileTypes: true })) {
46072
+ for (const entry of fs12.readdirSync(srcDir, { withFileTypes: true })) {
46033
46073
  if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
46034
46074
  const srcPath = path14.join(srcDir, entry.name);
46035
46075
  const dstPath = path14.join(dstDir, entry.name);
46036
46076
  if (entry.isDirectory()) {
46037
- fs11.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46077
+ fs12.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46038
46078
  } else if (entry.isFile()) {
46039
- fs11.copyFileSync(srcPath, dstPath);
46079
+ fs12.copyFileSync(srcPath, dstPath);
46040
46080
  }
46041
46081
  }
46042
46082
  }
@@ -46045,15 +46085,15 @@ function refreshDaemonManagedDirs(args) {
46045
46085
  const entries = args.entries ?? DEFAULT_PERSONAS;
46046
46086
  for (const entry of entries) {
46047
46087
  const bundleDir = path14.join(args.defaultsRoot, entry.personaId);
46048
- if (!fs11.existsSync(bundleDir)) continue;
46088
+ if (!fs12.existsSync(bundleDir)) continue;
46049
46089
  const personaDir = args.store.personaDirPath(entry.personaId);
46050
- if (!fs11.existsSync(personaDir)) continue;
46090
+ if (!fs12.existsSync(personaDir)) continue;
46051
46091
  for (const relPath of DAEMON_MANAGED_PATHS) {
46052
46092
  const srcPath = path14.join(bundleDir, relPath);
46053
- if (!fs11.existsSync(srcPath)) continue;
46093
+ if (!fs12.existsSync(srcPath)) continue;
46054
46094
  const dstPath = path14.join(personaDir, relPath);
46055
46095
  try {
46056
- fs11.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46096
+ fs12.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46057
46097
  args.logger.info("persona.refresh.synced", {
46058
46098
  personaId: entry.personaId,
46059
46099
  path: relPath
@@ -46121,7 +46161,7 @@ function findDeployKitRoot(logger) {
46121
46161
  if (fromArgv) candidates.push(fromArgv);
46122
46162
  for (const c of candidates) {
46123
46163
  try {
46124
- if (fs11.statSync(c).isDirectory()) {
46164
+ if (fs12.statSync(c).isDirectory()) {
46125
46165
  logger?.info("persona.deploy-kit-root.resolved", { root: c });
46126
46166
  return c;
46127
46167
  }
@@ -46133,7 +46173,7 @@ function findDeployKitRoot(logger) {
46133
46173
  }
46134
46174
  function seedDeployKit(args) {
46135
46175
  const dst = path14.join(args.dataDir, "deploy-kit");
46136
- fs11.cpSync(args.deployKitBundleRoot, dst, {
46176
+ fs12.cpSync(args.deployKitBundleRoot, dst, {
46137
46177
  recursive: true,
46138
46178
  dereference: true,
46139
46179
  force: false,
@@ -46143,34 +46183,34 @@ function seedDeployKit(args) {
46143
46183
  }
46144
46184
  function refreshDeployKit(args) {
46145
46185
  const dst = path14.join(args.dataDir, "deploy-kit");
46146
- if (!fs11.existsSync(dst)) {
46186
+ if (!fs12.existsSync(dst)) {
46147
46187
  seedDeployKit(args);
46148
46188
  return;
46149
46189
  }
46150
46190
  for (const sub of ["scripts", "contract"]) {
46151
46191
  const s = path14.join(args.deployKitBundleRoot, sub);
46152
- if (fs11.existsSync(s)) {
46153
- fs11.cpSync(s, path14.join(dst, sub), { recursive: true, force: true, dereference: true });
46192
+ if (fs12.existsSync(s)) {
46193
+ fs12.cpSync(s, path14.join(dst, sub), { recursive: true, force: true, dereference: true });
46154
46194
  }
46155
46195
  }
46156
46196
  const secretsSrc = path14.join(args.deployKitBundleRoot, ".secrets");
46157
- if (fs11.existsSync(secretsSrc)) {
46158
- fs11.mkdirSync(path14.join(dst, ".secrets"), { recursive: true });
46159
- for (const f of fs11.readdirSync(secretsSrc)) {
46197
+ if (fs12.existsSync(secretsSrc)) {
46198
+ fs12.mkdirSync(path14.join(dst, ".secrets"), { recursive: true });
46199
+ for (const f of fs12.readdirSync(secretsSrc)) {
46160
46200
  if (f.endsWith(".local")) continue;
46161
- fs11.copyFileSync(path14.join(secretsSrc, f), path14.join(dst, ".secrets", f));
46201
+ fs12.copyFileSync(path14.join(secretsSrc, f), path14.join(dst, ".secrets", f));
46162
46202
  }
46163
46203
  }
46164
46204
  args.logger.info("deploy-kit.refresh.done", { dst });
46165
46205
  }
46166
46206
 
46167
46207
  // src/share-md-viewer/load.ts
46168
- var import_node_fs11 = __toESM(require("fs"), 1);
46208
+ var import_node_fs12 = __toESM(require("fs"), 1);
46169
46209
  var import_node_path11 = __toESM(require("path"), 1);
46170
46210
  var import_node_url2 = require("url");
46171
46211
 
46172
46212
  // src/share-md-viewer/asset-loader.ts
46173
- var import_node_fs10 = __toESM(require("fs"), 1);
46213
+ var import_node_fs11 = __toESM(require("fs"), 1);
46174
46214
  function htmlEscape(s) {
46175
46215
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
46176
46216
  }
@@ -46178,12 +46218,12 @@ function createViewerAssetLoader(opts) {
46178
46218
  let viewerTemplate;
46179
46219
  let errorTemplate;
46180
46220
  try {
46181
- viewerTemplate = import_node_fs10.default.readFileSync(opts.viewerHtmlPath, "utf8");
46221
+ viewerTemplate = import_node_fs11.default.readFileSync(opts.viewerHtmlPath, "utf8");
46182
46222
  } catch (err) {
46183
46223
  throw new Error(`viewer asset not found at ${opts.viewerHtmlPath}: ${err.message}`);
46184
46224
  }
46185
46225
  try {
46186
- errorTemplate = import_node_fs10.default.readFileSync(opts.errorHtmlPath, "utf8");
46226
+ errorTemplate = import_node_fs11.default.readFileSync(opts.errorHtmlPath, "utf8");
46187
46227
  } catch (err) {
46188
46228
  throw new Error(`viewer error asset not found at ${opts.errorHtmlPath}: ${err.message}`);
46189
46229
  }
@@ -46211,7 +46251,7 @@ function tryLoadViewerAssets(logger) {
46211
46251
  if (process.argv[1]) {
46212
46252
  let real = process.argv[1];
46213
46253
  try {
46214
- real = import_node_fs11.default.realpathSync(process.argv[1]);
46254
+ real = import_node_fs12.default.realpathSync(process.argv[1]);
46215
46255
  } catch {
46216
46256
  }
46217
46257
  candidates.push(import_node_path11.default.dirname(real));
@@ -46220,7 +46260,7 @@ function tryLoadViewerAssets(logger) {
46220
46260
  const viewerHtmlPath = import_node_path11.default.join(root, "share-md-viewer.html");
46221
46261
  const errorHtmlPath = import_node_path11.default.join(root, "share-md-viewer-error.html");
46222
46262
  try {
46223
- if (import_node_fs11.default.statSync(viewerHtmlPath).isFile() && import_node_fs11.default.statSync(errorHtmlPath).isFile()) {
46263
+ if (import_node_fs12.default.statSync(viewerHtmlPath).isFile() && import_node_fs12.default.statSync(errorHtmlPath).isFile()) {
46224
46264
  logger?.info("share-md-viewer.assets-root.resolved", { root });
46225
46265
  return createViewerAssetLoader({ viewerHtmlPath, errorHtmlPath });
46226
46266
  }
@@ -46235,17 +46275,17 @@ function tryLoadViewerAssets(logger) {
46235
46275
  }
46236
46276
 
46237
46277
  // src/share-ui/load.ts
46238
- var import_node_fs13 = __toESM(require("fs"), 1);
46278
+ var import_node_fs14 = __toESM(require("fs"), 1);
46239
46279
  var import_node_path13 = __toESM(require("path"), 1);
46240
46280
  var import_node_url3 = require("url");
46241
46281
 
46242
46282
  // src/share-ui/asset-loader.ts
46243
- var import_node_fs12 = __toESM(require("fs"), 1);
46283
+ var import_node_fs13 = __toESM(require("fs"), 1);
46244
46284
  var import_node_path12 = __toESM(require("path"), 1);
46245
46285
  function createShareUiAssetLoader(opts) {
46246
46286
  let indexHtml;
46247
46287
  try {
46248
- indexHtml = import_node_fs12.default.readFileSync(opts.indexHtmlPath, "utf8");
46288
+ indexHtml = import_node_fs13.default.readFileSync(opts.indexHtmlPath, "utf8");
46249
46289
  } catch (err) {
46250
46290
  throw new Error(`share-ui index.html not found at ${opts.indexHtmlPath}: ${err.message}`);
46251
46291
  }
@@ -46258,7 +46298,7 @@ function createShareUiAssetLoader(opts) {
46258
46298
  const resolved = import_node_path12.default.resolve(assetsDir, rel);
46259
46299
  if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path12.default.sep)) return null;
46260
46300
  try {
46261
- if (import_node_fs12.default.statSync(resolved).isFile()) return resolved;
46301
+ if (import_node_fs13.default.statSync(resolved).isFile()) return resolved;
46262
46302
  } catch {
46263
46303
  }
46264
46304
  return null;
@@ -46272,7 +46312,7 @@ function bundleDirFromArgv(argv1) {
46272
46312
  if (!argv1) return null;
46273
46313
  let real = argv1;
46274
46314
  try {
46275
- real = import_node_fs13.default.realpathSync(argv1);
46315
+ real = import_node_fs14.default.realpathSync(argv1);
46276
46316
  } catch {
46277
46317
  }
46278
46318
  return import_node_path13.default.dirname(real);
@@ -46293,7 +46333,7 @@ function tryLoadShareUi(logger) {
46293
46333
  const indexHtmlPath = import_node_path13.default.join(shareUiDir, "guest.html");
46294
46334
  const assetsDir = import_node_path13.default.join(shareUiDir, "assets");
46295
46335
  try {
46296
- if (import_node_fs13.default.statSync(indexHtmlPath).isFile() && import_node_fs13.default.statSync(assetsDir).isDirectory()) {
46336
+ if (import_node_fs14.default.statSync(indexHtmlPath).isFile() && import_node_fs14.default.statSync(assetsDir).isDirectory()) {
46297
46337
  logger?.info("share-ui.assets-root.resolved", { root: shareUiDir });
46298
46338
  return createShareUiAssetLoader({ indexHtmlPath, assetsDir });
46299
46339
  }
@@ -46375,20 +46415,20 @@ function buildVisitorLogin(deps) {
46375
46415
  }
46376
46416
 
46377
46417
  // src/visitor/visitor-store.ts
46378
- var import_node_fs14 = __toESM(require("fs"), 1);
46418
+ var import_node_fs15 = __toESM(require("fs"), 1);
46379
46419
  var import_node_path14 = __toESM(require("path"), 1);
46380
46420
  function createVisitorStore(opts) {
46381
46421
  const file = import_node_path14.default.join(opts.dir, "visitors.json");
46382
46422
  const read = () => {
46383
46423
  try {
46384
- return JSON.parse(import_node_fs14.default.readFileSync(file, "utf8"));
46424
+ return JSON.parse(import_node_fs15.default.readFileSync(file, "utf8"));
46385
46425
  } catch {
46386
46426
  return [];
46387
46427
  }
46388
46428
  };
46389
46429
  const write = (rows) => {
46390
- import_node_fs14.default.mkdirSync(opts.dir, { recursive: true });
46391
- import_node_fs14.default.writeFileSync(file, JSON.stringify(rows, null, 2));
46430
+ import_node_fs15.default.mkdirSync(opts.dir, { recursive: true });
46431
+ import_node_fs15.default.writeFileSync(file, JSON.stringify(rows, null, 2));
46392
46432
  };
46393
46433
  return {
46394
46434
  upsert(r) {
@@ -46422,7 +46462,7 @@ init_claude();
46422
46462
 
46423
46463
  // src/tools/codex.ts
46424
46464
  var import_node_child_process4 = require("child_process");
46425
- var import_node_fs16 = __toESM(require("fs"), 1);
46465
+ var import_node_fs17 = __toESM(require("fs"), 1);
46426
46466
 
46427
46467
  // src/tools/codex-session.ts
46428
46468
  var import_node_child_process3 = require("child_process");
@@ -46855,10 +46895,10 @@ function sanitizeCodexModel(model) {
46855
46895
  return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
46856
46896
  }
46857
46897
  async function probeCodex(env = process.env) {
46858
- if (env.CODEX_BIN && import_node_fs16.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
46898
+ if (env.CODEX_BIN && import_node_fs17.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
46859
46899
  try {
46860
46900
  const out = (0, import_node_child_process4.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
46861
- if (out && import_node_fs16.default.existsSync(out)) return { available: true, path: out };
46901
+ if (out && import_node_fs17.default.existsSync(out)) return { available: true, path: out };
46862
46902
  } catch {
46863
46903
  }
46864
46904
  return { available: false };
@@ -46904,7 +46944,7 @@ var CodexAdapter = class {
46904
46944
 
46905
46945
  // src/tools/claude-tui.ts
46906
46946
  var import_node_crypto5 = require("crypto");
46907
- var import_node_fs17 = __toESM(require("fs"), 1);
46947
+ var import_node_fs18 = __toESM(require("fs"), 1);
46908
46948
  var import_node_os7 = __toESM(require("os"), 1);
46909
46949
  var import_node_path15 = __toESM(require("path"), 1);
46910
46950
  var import_headless = __toESM(require_xterm_headless(), 1);
@@ -48150,7 +48190,7 @@ function jsonlExistsForCtx(ctx) {
48150
48190
  const home = import_node_os7.default.homedir();
48151
48191
  const file = import_node_path15.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
48152
48192
  try {
48153
- return import_node_fs17.default.statSync(file).isFile();
48193
+ return import_node_fs18.default.statSync(file).isFile();
48154
48194
  } catch {
48155
48195
  return false;
48156
48196
  }
@@ -48219,7 +48259,7 @@ var PersonaDispatchManager = class {
48219
48259
  };
48220
48260
 
48221
48261
  // src/dispatch/mcp-config.ts
48222
- var import_node_fs18 = __toESM(require("fs"), 1);
48262
+ var import_node_fs19 = __toESM(require("fs"), 1);
48223
48263
  var import_node_path16 = __toESM(require("path"), 1);
48224
48264
  function dispatchMcpConfigPath(dataDir) {
48225
48265
  return import_node_path16.default.join(dataDir, "dispatch.mcp.json");
@@ -48237,13 +48277,13 @@ function writeDispatchMcpConfig(args) {
48237
48277
  }
48238
48278
  }
48239
48279
  };
48240
- import_node_fs18.default.mkdirSync(args.dataDir, { recursive: true });
48241
- import_node_fs18.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48280
+ import_node_fs19.default.mkdirSync(args.dataDir, { recursive: true });
48281
+ import_node_fs19.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48242
48282
  return cfgPath;
48243
48283
  }
48244
48284
 
48245
48285
  // src/ticket/mcp-config.ts
48246
- var import_node_fs19 = __toESM(require("fs"), 1);
48286
+ var import_node_fs20 = __toESM(require("fs"), 1);
48247
48287
  var import_node_path17 = __toESM(require("path"), 1);
48248
48288
  function ticketMcpConfigPath(dataDir) {
48249
48289
  return import_node_path17.default.join(dataDir, "ticket.mcp.json");
@@ -48266,13 +48306,13 @@ function writeTicketMcpConfig(args) {
48266
48306
  }
48267
48307
  }
48268
48308
  };
48269
- import_node_fs19.default.mkdirSync(args.dataDir, { recursive: true });
48270
- import_node_fs19.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48309
+ import_node_fs20.default.mkdirSync(args.dataDir, { recursive: true });
48310
+ import_node_fs20.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48271
48311
  return cfgPath;
48272
48312
  }
48273
48313
 
48274
48314
  // src/shift/mcp-config.ts
48275
- var import_node_fs20 = __toESM(require("fs"), 1);
48315
+ var import_node_fs21 = __toESM(require("fs"), 1);
48276
48316
  var import_node_path18 = __toESM(require("path"), 1);
48277
48317
  function shiftMcpConfigPath(dataDir) {
48278
48318
  return import_node_path18.default.join(dataDir, "shift.mcp.json");
@@ -48290,13 +48330,13 @@ async function writeShiftMcpConfig(args) {
48290
48330
  }
48291
48331
  }
48292
48332
  };
48293
- await import_node_fs20.default.promises.mkdir(args.dataDir, { recursive: true });
48294
- await import_node_fs20.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48333
+ await import_node_fs21.default.promises.mkdir(args.dataDir, { recursive: true });
48334
+ await import_node_fs21.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48295
48335
  return cfgPath;
48296
48336
  }
48297
48337
 
48298
48338
  // src/inbox/mcp-config.ts
48299
- var import_node_fs21 = __toESM(require("fs"), 1);
48339
+ var import_node_fs22 = __toESM(require("fs"), 1);
48300
48340
  var import_node_path19 = __toESM(require("path"), 1);
48301
48341
  function inboxMcpConfigPath(dataDir) {
48302
48342
  return import_node_path19.default.join(dataDir, "inbox.mcp.json");
@@ -48314,8 +48354,8 @@ async function writeInboxMcpConfig(args) {
48314
48354
  }
48315
48355
  }
48316
48356
  };
48317
- await import_node_fs21.default.promises.mkdir(args.dataDir, { recursive: true });
48318
- await import_node_fs21.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48357
+ await import_node_fs22.default.promises.mkdir(args.dataDir, { recursive: true });
48358
+ await import_node_fs22.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48319
48359
  return cfgPath;
48320
48360
  }
48321
48361
 
@@ -48819,12 +48859,19 @@ function canAccessPersona(grants, personaId, action) {
48819
48859
  }
48820
48860
 
48821
48861
  // src/handlers/persona-dispatch.ts
48862
+ init_claude();
48822
48863
  function buildPersonaDispatchHandlers(deps) {
48823
48864
  const { personaDispatchManager: mgr, spawnB, logger } = deps;
48824
48865
  const run = async (frame, _client, ctx) => {
48825
48866
  const { type: _t, requestId: _r, ...rest } = frame;
48826
48867
  const sourceSessionId = typeof rest.sessionId === "string" ? rest.sessionId : void 0;
48827
48868
  const args = DispatchRunArgsSchema.parse(rest);
48869
+ if (args.model !== void 0 && !CLAUDE_MODEL_IDS.includes(args.model)) {
48870
+ throw new ClawdError(
48871
+ ERROR_CODES.INVALID_PARAM,
48872
+ `model '${args.model}' not supported; allowed: ${CLAUDE_MODEL_IDS.join(", ")}`
48873
+ );
48874
+ }
48828
48875
  if (args.targetDeviceId) {
48829
48876
  if (ctx?.principal.kind === "guest") {
48830
48877
  throw new ClawdError(
@@ -48842,7 +48889,8 @@ function buildPersonaDispatchHandlers(deps) {
48842
48889
  const outcome2 = await deps.forwardToPeer({
48843
48890
  targetDeviceId: args.targetDeviceId,
48844
48891
  targetPersona: args.targetPersona,
48845
- prompt: args.prompt
48892
+ prompt: args.prompt,
48893
+ ...args.model ? { model: args.model } : {}
48846
48894
  });
48847
48895
  return {
48848
48896
  response: { type: "personaDispatch:run:ok", outcome: outcome2 }
@@ -48872,7 +48920,8 @@ function buildPersonaDispatchHandlers(deps) {
48872
48920
  targetPersona: args.targetPersona,
48873
48921
  prompt: args.prompt,
48874
48922
  guestPrincipalId: ctx.principal.id,
48875
- guestDisplayName: ctx.principal.displayName
48923
+ guestDisplayName: ctx.principal.displayName,
48924
+ ...args.model ? { model: args.model } : {}
48876
48925
  }).then(() => logger?.info("dispatch.spawnB.ok", { dispatchId: dispatchId2 })).catch((err) => {
48877
48926
  const reason = err instanceof Error ? err.message : String(err);
48878
48927
  logger?.warn("dispatch.spawnB.failed", { dispatchId: dispatchId2, reason });
@@ -48905,7 +48954,8 @@ function buildPersonaDispatchHandlers(deps) {
48905
48954
  dispatchId,
48906
48955
  sourceSessionId,
48907
48956
  targetPersona: args.targetPersona,
48908
- prompt: args.prompt
48957
+ prompt: args.prompt,
48958
+ ...args.model ? { model: args.model } : {}
48909
48959
  }).then(() => {
48910
48960
  logger?.info("dispatch.spawnB.ok", { dispatchId });
48911
48961
  }).catch((err) => {
@@ -48963,7 +49013,12 @@ async function forwardDispatchToPeer(args) {
48963
49013
  authorization: `Bearer ${args.contact.connectToken}`
48964
49014
  },
48965
49015
  // 注意:不带 targetDeviceId —— B 端据此判定为本地执行(B 角色)。
48966
- body: JSON.stringify({ targetPersona: args.targetPersona, prompt: args.prompt })
49016
+ body: JSON.stringify({
49017
+ targetPersona: args.targetPersona,
49018
+ prompt: args.prompt,
49019
+ // T-20: 条件展开防 undefined 污染 JSON。远端 daemon handler 会再校验一次 model 合法性。
49020
+ ...args.model ? { model: args.model } : {}
49021
+ })
48967
49022
  });
48968
49023
  } catch (err) {
48969
49024
  const msg = err instanceof Error ? err.message : String(err);
@@ -49285,7 +49340,7 @@ async function listCodexSkills(cwd, deps = {}) {
49285
49340
  }
49286
49341
 
49287
49342
  // src/workspace/browser.ts
49288
- var import_node_fs22 = __toESM(require("fs"), 1);
49343
+ var import_node_fs23 = __toESM(require("fs"), 1);
49289
49344
  var import_node_os8 = __toESM(require("os"), 1);
49290
49345
  var import_node_path21 = __toESM(require("path"), 1);
49291
49346
  init_protocol();
@@ -49301,7 +49356,7 @@ function resolveInsideCwd(cwd, subpath) {
49301
49356
  }
49302
49357
  function ensureCwd(cwd) {
49303
49358
  try {
49304
- const stat = import_node_fs22.default.statSync(cwd);
49359
+ const stat = import_node_fs23.default.statSync(cwd);
49305
49360
  if (!stat.isDirectory()) {
49306
49361
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
49307
49362
  }
@@ -49315,7 +49370,7 @@ var WorkspaceBrowser = class {
49315
49370
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
49316
49371
  ensureCwd(cwd);
49317
49372
  const full = resolveInsideCwd(cwd, args.path);
49318
- const dirents = import_node_fs22.default.readdirSync(full, { withFileTypes: true });
49373
+ const dirents = import_node_fs23.default.readdirSync(full, { withFileTypes: true });
49319
49374
  const entries = [];
49320
49375
  for (const d of dirents) {
49321
49376
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -49325,7 +49380,7 @@ var WorkspaceBrowser = class {
49325
49380
  mtime: ""
49326
49381
  };
49327
49382
  try {
49328
- const st = import_node_fs22.default.statSync(import_node_path21.default.join(full, d.name));
49383
+ const st = import_node_fs23.default.statSync(import_node_path21.default.join(full, d.name));
49329
49384
  entry.mtime = new Date(st.mtimeMs).toISOString();
49330
49385
  if (d.isFile()) entry.size = st.size;
49331
49386
  } catch {
@@ -49341,14 +49396,14 @@ var WorkspaceBrowser = class {
49341
49396
  read(args) {
49342
49397
  ensureCwd(args.cwd);
49343
49398
  const full = resolveInsideCwd(args.cwd, args.path);
49344
- const st = import_node_fs22.default.statSync(full);
49399
+ const st = import_node_fs23.default.statSync(full);
49345
49400
  if (!st.isFile()) {
49346
49401
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
49347
49402
  }
49348
49403
  if (st.size > MAX_FILE_BYTES) {
49349
49404
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
49350
49405
  }
49351
- const buf = import_node_fs22.default.readFileSync(full);
49406
+ const buf = import_node_fs23.default.readFileSync(full);
49352
49407
  const isBinary = buf.includes(0);
49353
49408
  if (isBinary) {
49354
49409
  return {
@@ -49370,20 +49425,20 @@ var WorkspaceBrowser = class {
49370
49425
  };
49371
49426
 
49372
49427
  // src/skills/agents-scanner.ts
49373
- var import_node_fs23 = __toESM(require("fs"), 1);
49428
+ var import_node_fs24 = __toESM(require("fs"), 1);
49374
49429
  var import_node_os9 = __toESM(require("os"), 1);
49375
49430
  var import_node_path22 = __toESM(require("path"), 1);
49376
49431
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
49377
49432
  function isDirLikeSync2(p2) {
49378
49433
  try {
49379
- return import_node_fs23.default.statSync(p2).isDirectory();
49434
+ return import_node_fs24.default.statSync(p2).isDirectory();
49380
49435
  } catch {
49381
49436
  return false;
49382
49437
  }
49383
49438
  }
49384
49439
  function fileExistsSync(p2) {
49385
49440
  try {
49386
- return import_node_fs23.default.statSync(p2).isFile();
49441
+ return import_node_fs24.default.statSync(p2).isFile();
49387
49442
  } catch {
49388
49443
  return false;
49389
49444
  }
@@ -49391,7 +49446,7 @@ function fileExistsSync(p2) {
49391
49446
  function parseAgentFile(filePath) {
49392
49447
  let content;
49393
49448
  try {
49394
- content = import_node_fs23.default.readFileSync(filePath, "utf8");
49449
+ content = import_node_fs24.default.readFileSync(filePath, "utf8");
49395
49450
  } catch {
49396
49451
  return {};
49397
49452
  }
@@ -49404,7 +49459,7 @@ function parseAgentFile(filePath) {
49404
49459
  function scanAgentsDir(dir, source, seen, out) {
49405
49460
  let entries;
49406
49461
  try {
49407
- entries = import_node_fs23.default.readdirSync(dir, { withFileTypes: true });
49462
+ entries = import_node_fs24.default.readdirSync(dir, { withFileTypes: true });
49408
49463
  } catch {
49409
49464
  return;
49410
49465
  }
@@ -49431,7 +49486,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
49431
49486
  function walk2(dir, namespaces) {
49432
49487
  let entries;
49433
49488
  try {
49434
- entries = import_node_fs23.default.readdirSync(dir, { withFileTypes: true });
49489
+ entries = import_node_fs24.default.readdirSync(dir, { withFileTypes: true });
49435
49490
  } catch {
49436
49491
  return;
49437
49492
  }
@@ -49467,7 +49522,7 @@ function readInstalledPlugins2(home) {
49467
49522
  let raw = null;
49468
49523
  for (const candidate of [v2, v1]) {
49469
49524
  try {
49470
- raw = import_node_fs23.default.readFileSync(candidate, "utf8");
49525
+ raw = import_node_fs24.default.readFileSync(candidate, "utf8");
49471
49526
  break;
49472
49527
  } catch {
49473
49528
  }
@@ -49498,7 +49553,7 @@ function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
49498
49553
  scanAgentsDir(import_node_path22.default.join(cur, ".claude", "agents"), "project", seen, out);
49499
49554
  let hasGit = false;
49500
49555
  try {
49501
- hasGit = import_node_fs23.default.existsSync(import_node_path22.default.join(cur, ".git"));
49556
+ hasGit = import_node_fs24.default.existsSync(import_node_path22.default.join(cur, ".git"));
49502
49557
  } catch {
49503
49558
  }
49504
49559
  if (hasGit) return;
@@ -49561,13 +49616,13 @@ var AgentsScanner = class {
49561
49616
  };
49562
49617
 
49563
49618
  // src/observer/session-observer.ts
49564
- var import_node_fs25 = __toESM(require("fs"), 1);
49619
+ var import_node_fs26 = __toESM(require("fs"), 1);
49565
49620
  var import_node_os11 = __toESM(require("os"), 1);
49566
49621
  var import_node_path24 = __toESM(require("path"), 1);
49567
49622
  init_claude_history();
49568
49623
 
49569
49624
  // src/observer/subagent-meta-observer.ts
49570
- var import_node_fs24 = __toESM(require("fs"), 1);
49625
+ var import_node_fs25 = __toESM(require("fs"), 1);
49571
49626
  var import_node_os10 = __toESM(require("os"), 1);
49572
49627
  var import_node_path23 = __toESM(require("path"), 1);
49573
49628
  init_claude_history();
@@ -49612,7 +49667,7 @@ var SubagentMetaObserver = class {
49612
49667
  attachWatcher(w2) {
49613
49668
  if (w2.watcher) return;
49614
49669
  try {
49615
- w2.watcher = import_node_fs24.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
49670
+ w2.watcher = import_node_fs25.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
49616
49671
  if (!name) return;
49617
49672
  const m2 = META_RE.exec(String(name));
49618
49673
  if (!m2) return;
@@ -49624,7 +49679,7 @@ var SubagentMetaObserver = class {
49624
49679
  scan(w2) {
49625
49680
  let entries;
49626
49681
  try {
49627
- entries = import_node_fs24.default.readdirSync(w2.dirPath);
49682
+ entries = import_node_fs25.default.readdirSync(w2.dirPath);
49628
49683
  } catch {
49629
49684
  return;
49630
49685
  }
@@ -49641,7 +49696,7 @@ var SubagentMetaObserver = class {
49641
49696
  const file = import_node_path23.default.join(w2.dirPath, name);
49642
49697
  let raw;
49643
49698
  try {
49644
- raw = import_node_fs24.default.readFileSync(file, "utf8");
49699
+ raw = import_node_fs25.default.readFileSync(file, "utf8");
49645
49700
  } catch {
49646
49701
  return;
49647
49702
  }
@@ -49705,7 +49760,7 @@ var SessionObserver = class {
49705
49760
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
49706
49761
  let size = 0;
49707
49762
  try {
49708
- size = import_node_fs25.default.statSync(filePath).size;
49763
+ size = import_node_fs26.default.statSync(filePath).size;
49709
49764
  } catch {
49710
49765
  }
49711
49766
  const w2 = {
@@ -49718,16 +49773,16 @@ var SessionObserver = class {
49718
49773
  adapter: args.adapter,
49719
49774
  prevIsRejectSentinel: false,
49720
49775
  toolSessionId: args.toolSessionId,
49721
- sawFile: import_node_fs25.default.existsSync(filePath),
49776
+ sawFile: import_node_fs26.default.existsSync(filePath),
49722
49777
  lastRelocateScanMs: 0,
49723
49778
  pendingCwdDerive: false,
49724
49779
  lastDeriveMs: 0
49725
49780
  };
49726
49781
  try {
49727
- import_node_fs25.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
49782
+ import_node_fs26.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
49728
49783
  } catch {
49729
49784
  }
49730
- w2.watcher = import_node_fs25.default.watch(import_node_path24.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
49785
+ w2.watcher = import_node_fs26.default.watch(import_node_path24.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
49731
49786
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
49732
49787
  this.poll(w2);
49733
49788
  });
@@ -49750,7 +49805,7 @@ var SessionObserver = class {
49750
49805
  // 异常静默吞,不阻塞 watcher 启动
49751
49806
  hydrateMetaTail(w2, maxLines = 200) {
49752
49807
  try {
49753
- const raw = import_node_fs25.default.readFileSync(w2.filePath, "utf8");
49808
+ const raw = import_node_fs26.default.readFileSync(w2.filePath, "utf8");
49754
49809
  if (!raw) return;
49755
49810
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
49756
49811
  if (allLines.length === 0) return;
@@ -49774,7 +49829,7 @@ var SessionObserver = class {
49774
49829
  poll(w2) {
49775
49830
  let size = 0;
49776
49831
  try {
49777
- size = import_node_fs25.default.statSync(w2.filePath).size;
49832
+ size = import_node_fs26.default.statSync(w2.filePath).size;
49778
49833
  } catch {
49779
49834
  if (w2.sawFile) this.maybeRelocate(w2);
49780
49835
  return;
@@ -49785,11 +49840,11 @@ var SessionObserver = class {
49785
49840
  w2.buf = "";
49786
49841
  }
49787
49842
  if (size === w2.lastSize) return;
49788
- const fd = import_node_fs25.default.openSync(w2.filePath, "r");
49843
+ const fd = import_node_fs26.default.openSync(w2.filePath, "r");
49789
49844
  try {
49790
49845
  const len = size - w2.lastSize;
49791
49846
  const buf = Buffer.alloc(len);
49792
- import_node_fs25.default.readSync(fd, buf, 0, len, w2.lastSize);
49847
+ import_node_fs26.default.readSync(fd, buf, 0, len, w2.lastSize);
49793
49848
  w2.lastSize = size;
49794
49849
  w2.buf += buf.toString("utf8");
49795
49850
  let newlineIndex;
@@ -49812,7 +49867,7 @@ var SessionObserver = class {
49812
49867
  }
49813
49868
  }
49814
49869
  } finally {
49815
- import_node_fs25.default.closeSync(fd);
49870
+ import_node_fs26.default.closeSync(fd);
49816
49871
  }
49817
49872
  if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
49818
49873
  }
@@ -49833,7 +49888,7 @@ var SessionObserver = class {
49833
49888
  }
49834
49889
  w2.filePath = found;
49835
49890
  try {
49836
- w2.watcher = import_node_fs25.default.watch(import_node_path24.default.dirname(found), { persistent: false }, (_event, changedName) => {
49891
+ w2.watcher = import_node_fs26.default.watch(import_node_path24.default.dirname(found), { persistent: false }, (_event, changedName) => {
49837
49892
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
49838
49893
  this.poll(w2);
49839
49894
  });
@@ -50684,14 +50739,14 @@ async function authenticate(token, deps) {
50684
50739
  }
50685
50740
 
50686
50741
  // src/permission/capability-store.ts
50687
- var fs29 = __toESM(require("fs"), 1);
50742
+ var fs30 = __toESM(require("fs"), 1);
50688
50743
  var path29 = __toESM(require("path"), 1);
50689
50744
  var CAPABILITIES_FILE_NAME = "capabilities.json";
50690
50745
  var FILE_VERSION = 1;
50691
50746
  var CapabilityStore = class {
50692
50747
  constructor(dataDir) {
50693
50748
  this.dataDir = dataDir;
50694
- fs29.mkdirSync(dataDir, { recursive: true });
50749
+ fs30.mkdirSync(dataDir, { recursive: true });
50695
50750
  this.cache = this.readFromDisk();
50696
50751
  }
50697
50752
  dataDir;
@@ -50721,7 +50776,7 @@ var CapabilityStore = class {
50721
50776
  const file = this.filePath();
50722
50777
  let raw;
50723
50778
  try {
50724
- raw = fs29.readFileSync(file, "utf8");
50779
+ raw = fs30.readFileSync(file, "utf8");
50725
50780
  } catch (err) {
50726
50781
  if (err?.code === "ENOENT") return [];
50727
50782
  return [];
@@ -50749,10 +50804,10 @@ var CapabilityStore = class {
50749
50804
  }
50750
50805
  atomicWrite(file, content) {
50751
50806
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
50752
- fs29.writeFileSync(tmp, content, { mode: 384 });
50753
- fs29.renameSync(tmp, file);
50807
+ fs30.writeFileSync(tmp, content, { mode: 384 });
50808
+ fs30.renameSync(tmp, file);
50754
50809
  try {
50755
- fs29.chmodSync(file, 384);
50810
+ fs30.chmodSync(file, 384);
50756
50811
  } catch {
50757
50812
  }
50758
50813
  }
@@ -50845,14 +50900,14 @@ var CapabilityManager = class {
50845
50900
  };
50846
50901
 
50847
50902
  // src/permission/cleanup.ts
50848
- var fs30 = __toESM(require("fs"), 1);
50903
+ var fs31 = __toESM(require("fs"), 1);
50849
50904
  function cleanupGuestSessionsForCapability(cap, factory) {
50850
50905
  const removed = [];
50851
50906
  for (const g2 of cap.grants) {
50852
50907
  if (g2.resource.type !== "persona") continue;
50853
50908
  const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
50854
50909
  try {
50855
- fs30.rmSync(dir, { recursive: true, force: true });
50910
+ fs31.rmSync(dir, { recursive: true, force: true });
50856
50911
  removed.push(dir);
50857
50912
  } catch {
50858
50913
  }
@@ -50861,13 +50916,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
50861
50916
  }
50862
50917
 
50863
50918
  // src/inbox/inbox-store.ts
50864
- var fs31 = __toESM(require("fs"), 1);
50919
+ var fs32 = __toESM(require("fs"), 1);
50865
50920
  var path30 = __toESM(require("path"), 1);
50866
50921
  var INBOX_SUBDIR = "inbox";
50867
50922
  var InboxStore = class {
50868
50923
  constructor(dataDir) {
50869
50924
  this.dataDir = dataDir;
50870
- fs31.mkdirSync(this.dirPath(), { recursive: true });
50925
+ fs32.mkdirSync(this.dirPath(), { recursive: true });
50871
50926
  }
50872
50927
  dataDir;
50873
50928
  /**
@@ -50879,7 +50934,7 @@ var InboxStore = class {
50879
50934
  const file = this.filePath(peerDeviceId);
50880
50935
  let raw;
50881
50936
  try {
50882
- raw = fs31.readFileSync(file, "utf8");
50937
+ raw = fs32.readFileSync(file, "utf8");
50883
50938
  } catch (err) {
50884
50939
  if (err?.code === "ENOENT") return [];
50885
50940
  return [];
@@ -50895,7 +50950,7 @@ var InboxStore = class {
50895
50950
  const dir = this.dirPath();
50896
50951
  let entries;
50897
50952
  try {
50898
- entries = fs31.readdirSync(dir);
50953
+ entries = fs32.readdirSync(dir);
50899
50954
  } catch (err) {
50900
50955
  if (err?.code === "ENOENT") return [];
50901
50956
  return [];
@@ -50911,9 +50966,9 @@ var InboxStore = class {
50911
50966
  if (existing.some((m2) => m2.id === message.id)) return;
50912
50967
  const file = this.filePath(message.peerDeviceId);
50913
50968
  const line = JSON.stringify(message) + "\n";
50914
- fs31.appendFileSync(file, line, { mode: 384 });
50969
+ fs32.appendFileSync(file, line, { mode: 384 });
50915
50970
  try {
50916
- fs31.chmodSync(file, 384);
50971
+ fs32.chmodSync(file, 384);
50917
50972
  } catch {
50918
50973
  }
50919
50974
  }
@@ -50943,7 +50998,7 @@ var InboxStore = class {
50943
50998
  removeByPeerDeviceId(peerDeviceId) {
50944
50999
  const file = this.filePath(peerDeviceId);
50945
51000
  try {
50946
- fs31.unlinkSync(file);
51001
+ fs32.unlinkSync(file);
50947
51002
  } catch (err) {
50948
51003
  if (err?.code === "ENOENT") return;
50949
51004
  }
@@ -50952,10 +51007,10 @@ var InboxStore = class {
50952
51007
  const file = this.filePath(peerDeviceId);
50953
51008
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
50954
51009
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
50955
- fs31.writeFileSync(tmp, content, { mode: 384 });
50956
- fs31.renameSync(tmp, file);
51010
+ fs32.writeFileSync(tmp, content, { mode: 384 });
51011
+ fs32.renameSync(tmp, file);
50957
51012
  try {
50958
- fs31.chmodSync(file, 384);
51013
+ fs32.chmodSync(file, 384);
50959
51014
  } catch {
50960
51015
  }
50961
51016
  }
@@ -51051,7 +51106,7 @@ var InboxManager = class {
51051
51106
  };
51052
51107
 
51053
51108
  // src/state/contact-store.ts
51054
- var fs32 = __toESM(require("fs"), 1);
51109
+ var fs33 = __toESM(require("fs"), 1);
51055
51110
  var path31 = __toESM(require("path"), 1);
51056
51111
  var FILE_NAME = "contacts.json";
51057
51112
  var ContactStore = class {
@@ -51065,7 +51120,7 @@ var ContactStore = class {
51065
51120
  const file = path31.join(this.dataDir, FILE_NAME);
51066
51121
  let raw;
51067
51122
  try {
51068
- raw = fs32.readFileSync(file, "utf8");
51123
+ raw = fs33.readFileSync(file, "utf8");
51069
51124
  } catch (err) {
51070
51125
  if (err?.code !== "ENOENT") this.renameBak(file);
51071
51126
  return;
@@ -51144,13 +51199,13 @@ var ContactStore = class {
51144
51199
  null,
51145
51200
  2
51146
51201
  );
51147
- fs32.mkdirSync(this.dataDir, { recursive: true });
51148
- fs32.writeFileSync(tmp, content, { mode: 384 });
51149
- fs32.renameSync(tmp, file);
51202
+ fs33.mkdirSync(this.dataDir, { recursive: true });
51203
+ fs33.writeFileSync(tmp, content, { mode: 384 });
51204
+ fs33.renameSync(tmp, file);
51150
51205
  }
51151
51206
  renameBak(file) {
51152
51207
  try {
51153
- fs32.renameSync(file, `${file}.bak`);
51208
+ fs33.renameSync(file, `${file}.bak`);
51154
51209
  } catch {
51155
51210
  }
51156
51211
  }
@@ -51304,7 +51359,7 @@ async function autoReverseContact(args) {
51304
51359
  }
51305
51360
 
51306
51361
  // src/migrations/2026-05-20-flatten-sessions.ts
51307
- var fs33 = __toESM(require("fs"), 1);
51362
+ var fs34 = __toESM(require("fs"), 1);
51308
51363
  var path32 = __toESM(require("path"), 1);
51309
51364
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
51310
51365
  function migrateFlattenSessions(opts) {
@@ -51324,7 +51379,7 @@ function migrateFlattenSessions(opts) {
51324
51379
  if (!entry.endsWith(".json")) continue;
51325
51380
  const src = path32.join(defaultDir, entry);
51326
51381
  const dst = path32.join(sessionsDir, entry);
51327
- fs33.renameSync(src, dst);
51382
+ fs34.renameSync(src, dst);
51328
51383
  movedBare += 1;
51329
51384
  }
51330
51385
  rmdirIfEmpty(defaultDir);
@@ -51336,10 +51391,10 @@ function migrateFlattenSessions(opts) {
51336
51391
  const ownerSrc = path32.join(personaDir, "owner");
51337
51392
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
51338
51393
  const ownerDst = path32.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
51339
- fs33.mkdirSync(ownerDst, { recursive: true });
51394
+ fs34.mkdirSync(ownerDst, { recursive: true });
51340
51395
  for (const file of readdirSafe(ownerSrc)) {
51341
51396
  if (!file.endsWith(".json")) continue;
51342
- fs33.renameSync(path32.join(ownerSrc, file), path32.join(ownerDst, file));
51397
+ fs34.renameSync(path32.join(ownerSrc, file), path32.join(ownerDst, file));
51343
51398
  movedVmOwner += 1;
51344
51399
  }
51345
51400
  rmdirIfEmpty(ownerSrc);
@@ -51347,18 +51402,18 @@ function migrateFlattenSessions(opts) {
51347
51402
  const listenerSrc = path32.join(personaDir, "listener");
51348
51403
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
51349
51404
  const archiveDst = path32.join(dataDir, ".legacy", `listener-${pid}`);
51350
- fs33.mkdirSync(archiveDst, { recursive: true });
51405
+ fs34.mkdirSync(archiveDst, { recursive: true });
51351
51406
  for (const file of readdirSafe(listenerSrc)) {
51352
51407
  if (!file.endsWith(".json")) continue;
51353
- fs33.renameSync(path32.join(listenerSrc, file), path32.join(archiveDst, file));
51408
+ fs34.renameSync(path32.join(listenerSrc, file), path32.join(archiveDst, file));
51354
51409
  archivedListener += 1;
51355
51410
  }
51356
51411
  rmdirIfEmpty(listenerSrc);
51357
51412
  }
51358
51413
  rmdirIfEmpty(personaDir);
51359
51414
  }
51360
- fs33.mkdirSync(sessionsDir, { recursive: true });
51361
- fs33.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
51415
+ fs34.mkdirSync(sessionsDir, { recursive: true });
51416
+ fs34.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
51362
51417
  return {
51363
51418
  skipped: false,
51364
51419
  flagWritten: true,
@@ -51369,7 +51424,7 @@ function migrateFlattenSessions(opts) {
51369
51424
  }
51370
51425
  function existsSync3(p2) {
51371
51426
  try {
51372
- fs33.statSync(p2);
51427
+ fs34.statSync(p2);
51373
51428
  return true;
51374
51429
  } catch {
51375
51430
  return false;
@@ -51377,27 +51432,27 @@ function existsSync3(p2) {
51377
51432
  }
51378
51433
  function isDir(p2) {
51379
51434
  try {
51380
- return fs33.statSync(p2).isDirectory();
51435
+ return fs34.statSync(p2).isDirectory();
51381
51436
  } catch {
51382
51437
  return false;
51383
51438
  }
51384
51439
  }
51385
51440
  function readdirSafe(p2) {
51386
51441
  try {
51387
- return fs33.readdirSync(p2);
51442
+ return fs34.readdirSync(p2);
51388
51443
  } catch {
51389
51444
  return [];
51390
51445
  }
51391
51446
  }
51392
51447
  function rmdirIfEmpty(p2) {
51393
51448
  try {
51394
- fs33.rmdirSync(p2);
51449
+ fs34.rmdirSync(p2);
51395
51450
  } catch {
51396
51451
  }
51397
51452
  }
51398
51453
 
51399
51454
  // src/transport/http-router.ts
51400
- var import_node_fs27 = __toESM(require("fs"), 1);
51455
+ var import_node_fs28 = __toESM(require("fs"), 1);
51401
51456
  var import_node_path28 = __toESM(require("path"), 1);
51402
51457
 
51403
51458
  // src/attachment/mime.ts
@@ -51577,7 +51632,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
51577
51632
  }
51578
51633
 
51579
51634
  // src/attachment/upload.ts
51580
- var import_node_fs26 = __toESM(require("fs"), 1);
51635
+ var import_node_fs27 = __toESM(require("fs"), 1);
51581
51636
  var import_node_path26 = __toESM(require("path"), 1);
51582
51637
  var import_node_crypto8 = __toESM(require("crypto"), 1);
51583
51638
  var import_promises2 = require("stream/promises");
@@ -51599,7 +51654,7 @@ async function writeUploadedAttachment(args) {
51599
51654
  assertValidFileName(args.fileName);
51600
51655
  const attachmentsRoot = import_node_path26.default.join(args.sessionDir, ".attachments");
51601
51656
  try {
51602
- import_node_fs26.default.mkdirSync(attachmentsRoot, { recursive: true });
51657
+ import_node_fs27.default.mkdirSync(attachmentsRoot, { recursive: true });
51603
51658
  } catch (err) {
51604
51659
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
51605
51660
  }
@@ -51620,18 +51675,18 @@ async function writeUploadedAttachment(args) {
51620
51675
  yield buf;
51621
51676
  }
51622
51677
  },
51623
- import_node_fs26.default.createWriteStream(tmpPath, { mode: 384 })
51678
+ import_node_fs27.default.createWriteStream(tmpPath, { mode: 384 })
51624
51679
  );
51625
51680
  } catch (err) {
51626
51681
  try {
51627
- import_node_fs26.default.unlinkSync(tmpPath);
51682
+ import_node_fs27.default.unlinkSync(tmpPath);
51628
51683
  } catch {
51629
51684
  }
51630
51685
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
51631
51686
  }
51632
51687
  if (actualSize !== args.contentLength) {
51633
51688
  try {
51634
- import_node_fs26.default.unlinkSync(tmpPath);
51689
+ import_node_fs27.default.unlinkSync(tmpPath);
51635
51690
  } catch {
51636
51691
  }
51637
51692
  throw new UploadError(
@@ -51644,24 +51699,24 @@ async function writeUploadedAttachment(args) {
51644
51699
  let finalFileName;
51645
51700
  let hashDirExists = false;
51646
51701
  try {
51647
- hashDirExists = import_node_fs26.default.statSync(hashDir).isDirectory();
51702
+ hashDirExists = import_node_fs27.default.statSync(hashDir).isDirectory();
51648
51703
  } catch {
51649
51704
  }
51650
51705
  if (hashDirExists) {
51651
- const existing = import_node_fs26.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
51706
+ const existing = import_node_fs27.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
51652
51707
  finalFileName = existing[0] ?? args.fileName;
51653
51708
  try {
51654
- import_node_fs26.default.unlinkSync(tmpPath);
51709
+ import_node_fs27.default.unlinkSync(tmpPath);
51655
51710
  } catch {
51656
51711
  }
51657
51712
  } else {
51658
51713
  try {
51659
- import_node_fs26.default.mkdirSync(hashDir, { recursive: true });
51714
+ import_node_fs27.default.mkdirSync(hashDir, { recursive: true });
51660
51715
  finalFileName = args.fileName;
51661
- import_node_fs26.default.renameSync(tmpPath, import_node_path26.default.join(hashDir, finalFileName));
51716
+ import_node_fs27.default.renameSync(tmpPath, import_node_path26.default.join(hashDir, finalFileName));
51662
51717
  } catch (err) {
51663
51718
  try {
51664
- import_node_fs26.default.unlinkSync(tmpPath);
51719
+ import_node_fs27.default.unlinkSync(tmpPath);
51665
51720
  } catch {
51666
51721
  }
51667
51722
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
@@ -51941,7 +51996,7 @@ function createHttpRouter(deps) {
51941
51996
  }
51942
51997
  let buf;
51943
51998
  try {
51944
- buf = await import_node_fs27.default.promises.readFile(abs);
51999
+ buf = await import_node_fs28.default.promises.readFile(abs);
51945
52000
  } catch {
51946
52001
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
51947
52002
  return true;
@@ -52381,7 +52436,7 @@ function withCtx(ctx, body) {
52381
52436
  function streamFile(res, absPath, logger) {
52382
52437
  let stat;
52383
52438
  try {
52384
- stat = import_node_fs27.default.statSync(absPath);
52439
+ stat = import_node_fs28.default.statSync(absPath);
52385
52440
  } catch (err) {
52386
52441
  const code = err?.code;
52387
52442
  if (code === "ENOENT") {
@@ -52404,7 +52459,7 @@ function streamFile(res, absPath, logger) {
52404
52459
  // 防止浏览器把任意 mime 当 html 渲染
52405
52460
  "X-Content-Type-Options": "nosniff"
52406
52461
  });
52407
- const stream = import_node_fs27.default.createReadStream(absPath);
52462
+ const stream = import_node_fs28.default.createReadStream(absPath);
52408
52463
  stream.on("error", (err) => {
52409
52464
  logger?.warn("streamFile read error", { absPath, err: err.message });
52410
52465
  res.destroy();
@@ -52413,7 +52468,7 @@ function streamFile(res, absPath, logger) {
52413
52468
  }
52414
52469
 
52415
52470
  // src/attachment/gc.ts
52416
- var import_node_fs28 = __toESM(require("fs"), 1);
52471
+ var import_node_fs29 = __toESM(require("fs"), 1);
52417
52472
  var import_node_path29 = __toESM(require("path"), 1);
52418
52473
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
52419
52474
  function runAttachmentGc(args) {
@@ -52436,7 +52491,7 @@ function runAttachmentGc(args) {
52436
52491
  const attRoot = import_node_path29.default.join(sessionDir, ".attachments");
52437
52492
  let hashDirs;
52438
52493
  try {
52439
- hashDirs = import_node_fs28.default.readdirSync(attRoot);
52494
+ hashDirs = import_node_fs29.default.readdirSync(attRoot);
52440
52495
  } catch (err) {
52441
52496
  if (err.code === "ENOENT") continue;
52442
52497
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
@@ -52446,7 +52501,7 @@ function runAttachmentGc(args) {
52446
52501
  const hashDirAbs = import_node_path29.default.join(attRoot, hashDir);
52447
52502
  let files;
52448
52503
  try {
52449
- files = import_node_fs28.default.readdirSync(hashDirAbs);
52504
+ files = import_node_fs29.default.readdirSync(hashDirAbs);
52450
52505
  } catch {
52451
52506
  continue;
52452
52507
  }
@@ -52454,7 +52509,7 @@ function runAttachmentGc(args) {
52454
52509
  const file = import_node_path29.default.join(hashDirAbs, name);
52455
52510
  let stat;
52456
52511
  try {
52457
- stat = import_node_fs28.default.statSync(file);
52512
+ stat = import_node_fs29.default.statSync(file);
52458
52513
  } catch {
52459
52514
  continue;
52460
52515
  }
@@ -52463,25 +52518,25 @@ function runAttachmentGc(args) {
52463
52518
  if (age < ttlMs) continue;
52464
52519
  if (liveAbs.has(file)) continue;
52465
52520
  try {
52466
- import_node_fs28.default.unlinkSync(file);
52521
+ import_node_fs29.default.unlinkSync(file);
52467
52522
  } catch (err) {
52468
52523
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
52469
52524
  }
52470
52525
  }
52471
52526
  try {
52472
- if (import_node_fs28.default.readdirSync(hashDirAbs).length === 0) import_node_fs28.default.rmdirSync(hashDirAbs);
52527
+ if (import_node_fs29.default.readdirSync(hashDirAbs).length === 0) import_node_fs29.default.rmdirSync(hashDirAbs);
52473
52528
  } catch {
52474
52529
  }
52475
52530
  }
52476
52531
  try {
52477
- if (import_node_fs28.default.readdirSync(attRoot).length === 0) import_node_fs28.default.rmdirSync(attRoot);
52532
+ if (import_node_fs29.default.readdirSync(attRoot).length === 0) import_node_fs29.default.rmdirSync(attRoot);
52478
52533
  } catch {
52479
52534
  }
52480
52535
  }
52481
52536
  }
52482
52537
 
52483
52538
  // src/attachment/group.ts
52484
- var import_node_fs29 = __toESM(require("fs"), 1);
52539
+ var import_node_fs30 = __toESM(require("fs"), 1);
52485
52540
  var import_node_path30 = __toESM(require("path"), 1);
52486
52541
  var import_node_crypto9 = __toESM(require("crypto"), 1);
52487
52542
  init_protocol();
@@ -52507,7 +52562,7 @@ var GroupFileStore = class {
52507
52562
  readFile(scope, sessionId) {
52508
52563
  const file = this.filePath(scope, sessionId);
52509
52564
  try {
52510
- const raw = import_node_fs29.default.readFileSync(file, "utf8");
52565
+ const raw = import_node_fs30.default.readFileSync(file, "utf8");
52511
52566
  const parsed = JSON.parse(raw);
52512
52567
  if (!Array.isArray(parsed)) {
52513
52568
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -52533,10 +52588,10 @@ var GroupFileStore = class {
52533
52588
  }
52534
52589
  writeFile(scope, sessionId, entries) {
52535
52590
  const file = this.filePath(scope, sessionId);
52536
- import_node_fs29.default.mkdirSync(import_node_path30.default.dirname(file), { recursive: true });
52591
+ import_node_fs30.default.mkdirSync(import_node_path30.default.dirname(file), { recursive: true });
52537
52592
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
52538
- import_node_fs29.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
52539
- import_node_fs29.default.renameSync(tmp, file);
52593
+ import_node_fs30.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
52594
+ import_node_fs30.default.renameSync(tmp, file);
52540
52595
  }
52541
52596
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
52542
52597
  list(scope, sessionId) {
@@ -52622,7 +52677,7 @@ var GroupFileStore = class {
52622
52677
  };
52623
52678
 
52624
52679
  // src/discovery/state-file.ts
52625
- var import_node_fs30 = __toESM(require("fs"), 1);
52680
+ var import_node_fs31 = __toESM(require("fs"), 1);
52626
52681
  var import_node_path31 = __toESM(require("path"), 1);
52627
52682
  function defaultStateFilePath(dataDir) {
52628
52683
  return import_node_path31.default.join(dataDir, "state.json");
@@ -52647,7 +52702,7 @@ var StateFileManager = class {
52647
52702
  }
52648
52703
  read() {
52649
52704
  try {
52650
- const raw = import_node_fs30.default.readFileSync(this.file, "utf8");
52705
+ const raw = import_node_fs31.default.readFileSync(this.file, "utf8");
52651
52706
  const parsed = JSON.parse(raw);
52652
52707
  return parsed;
52653
52708
  } catch {
@@ -52661,20 +52716,20 @@ var StateFileManager = class {
52661
52716
  return { status: "stale", existing };
52662
52717
  }
52663
52718
  write(state) {
52664
- import_node_fs30.default.mkdirSync(import_node_path31.default.dirname(this.file), { recursive: true });
52719
+ import_node_fs31.default.mkdirSync(import_node_path31.default.dirname(this.file), { recursive: true });
52665
52720
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
52666
- import_node_fs30.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
52667
- import_node_fs30.default.renameSync(tmp, this.file);
52721
+ import_node_fs31.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
52722
+ import_node_fs31.default.renameSync(tmp, this.file);
52668
52723
  if (process.platform !== "win32") {
52669
52724
  try {
52670
- import_node_fs30.default.chmodSync(this.file, 384);
52725
+ import_node_fs31.default.chmodSync(this.file, 384);
52671
52726
  } catch {
52672
52727
  }
52673
52728
  }
52674
52729
  }
52675
52730
  delete() {
52676
52731
  try {
52677
- import_node_fs30.default.unlinkSync(this.file);
52732
+ import_node_fs31.default.unlinkSync(this.file);
52678
52733
  } catch {
52679
52734
  }
52680
52735
  }
@@ -52688,13 +52743,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
52688
52743
  }
52689
52744
 
52690
52745
  // src/tunnel/tunnel-manager.ts
52691
- var import_node_fs34 = __toESM(require("fs"), 1);
52746
+ var import_node_fs35 = __toESM(require("fs"), 1);
52692
52747
  var import_node_path35 = __toESM(require("path"), 1);
52693
52748
  var import_node_crypto10 = __toESM(require("crypto"), 1);
52694
52749
  var import_node_child_process9 = require("child_process");
52695
52750
 
52696
52751
  // src/tunnel/tunnel-store.ts
52697
- var import_node_fs31 = __toESM(require("fs"), 1);
52752
+ var import_node_fs32 = __toESM(require("fs"), 1);
52698
52753
  var import_node_path32 = __toESM(require("path"), 1);
52699
52754
  var TunnelStore = class {
52700
52755
  constructor(filePath) {
@@ -52703,7 +52758,7 @@ var TunnelStore = class {
52703
52758
  filePath;
52704
52759
  async get() {
52705
52760
  try {
52706
- const raw = await import_node_fs31.default.promises.readFile(this.filePath, "utf8");
52761
+ const raw = await import_node_fs32.default.promises.readFile(this.filePath, "utf8");
52707
52762
  const obj = JSON.parse(raw);
52708
52763
  if (!isPersistedTunnel(obj)) return null;
52709
52764
  return obj;
@@ -52715,21 +52770,21 @@ var TunnelStore = class {
52715
52770
  }
52716
52771
  async set(v2) {
52717
52772
  const dir = import_node_path32.default.dirname(this.filePath);
52718
- await import_node_fs31.default.promises.mkdir(dir, { recursive: true });
52773
+ await import_node_fs32.default.promises.mkdir(dir, { recursive: true });
52719
52774
  const data = JSON.stringify(v2, null, 2);
52720
52775
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
52721
- await import_node_fs31.default.promises.writeFile(tmp, data, { mode: 384 });
52776
+ await import_node_fs32.default.promises.writeFile(tmp, data, { mode: 384 });
52722
52777
  if (process.platform !== "win32") {
52723
52778
  try {
52724
- await import_node_fs31.default.promises.chmod(tmp, 384);
52779
+ await import_node_fs32.default.promises.chmod(tmp, 384);
52725
52780
  } catch {
52726
52781
  }
52727
52782
  }
52728
- await import_node_fs31.default.promises.rename(tmp, this.filePath);
52783
+ await import_node_fs32.default.promises.rename(tmp, this.filePath);
52729
52784
  }
52730
52785
  async clear() {
52731
52786
  try {
52732
- await import_node_fs31.default.promises.unlink(this.filePath);
52787
+ await import_node_fs32.default.promises.unlink(this.filePath);
52733
52788
  } catch (err) {
52734
52789
  const code = err?.code;
52735
52790
  if (code !== "ENOENT") throw err;
@@ -52824,7 +52879,7 @@ function escape(v2) {
52824
52879
  }
52825
52880
 
52826
52881
  // src/tunnel/frpc-binary.ts
52827
- var import_node_fs32 = __toESM(require("fs"), 1);
52882
+ var import_node_fs33 = __toESM(require("fs"), 1);
52828
52883
  var import_node_os13 = __toESM(require("os"), 1);
52829
52884
  var import_node_path33 = __toESM(require("path"), 1);
52830
52885
  var import_node_child_process7 = require("child_process");
@@ -52858,7 +52913,7 @@ function frpcDownloadUrl(version2, p2) {
52858
52913
  }
52859
52914
  async function ensureFrpcBinary(opts) {
52860
52915
  if (opts.override) {
52861
- if (!import_node_fs32.default.existsSync(opts.override)) {
52916
+ if (!import_node_fs33.default.existsSync(opts.override)) {
52862
52917
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
52863
52918
  }
52864
52919
  return opts.override;
@@ -52866,10 +52921,10 @@ async function ensureFrpcBinary(opts) {
52866
52921
  const version2 = opts.version ?? FRPC_VERSION;
52867
52922
  const platform = opts.platform ?? detectPlatform();
52868
52923
  const binDir = import_node_path33.default.join(opts.dataDir, "bin");
52869
- import_node_fs32.default.mkdirSync(binDir, { recursive: true });
52924
+ import_node_fs33.default.mkdirSync(binDir, { recursive: true });
52870
52925
  cleanupStaleArtifacts(binDir);
52871
52926
  const stableBin = import_node_path33.default.join(binDir, "frpc");
52872
- if (import_node_fs32.default.existsSync(stableBin)) return stableBin;
52927
+ if (import_node_fs33.default.existsSync(stableBin)) return stableBin;
52873
52928
  const partialBin = `${stableBin}.partial`;
52874
52929
  const tarballPath = import_node_path33.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
52875
52930
  try {
@@ -52880,8 +52935,8 @@ async function ensureFrpcBinary(opts) {
52880
52935
  } else {
52881
52936
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
52882
52937
  }
52883
- import_node_fs32.default.chmodSync(partialBin, 493);
52884
- import_node_fs32.default.renameSync(partialBin, stableBin);
52938
+ import_node_fs33.default.chmodSync(partialBin, 493);
52939
+ import_node_fs33.default.renameSync(partialBin, stableBin);
52885
52940
  } finally {
52886
52941
  safeUnlink(tarballPath);
52887
52942
  safeUnlink(partialBin);
@@ -52891,7 +52946,7 @@ async function ensureFrpcBinary(opts) {
52891
52946
  function cleanupStaleArtifacts(binDir) {
52892
52947
  let entries;
52893
52948
  try {
52894
- entries = import_node_fs32.default.readdirSync(binDir);
52949
+ entries = import_node_fs33.default.readdirSync(binDir);
52895
52950
  } catch {
52896
52951
  return;
52897
52952
  }
@@ -52899,7 +52954,7 @@ function cleanupStaleArtifacts(binDir) {
52899
52954
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
52900
52955
  const full = import_node_path33.default.join(binDir, name);
52901
52956
  try {
52902
- import_node_fs32.default.rmSync(full, { recursive: true, force: true });
52957
+ import_node_fs33.default.rmSync(full, { recursive: true, force: true });
52903
52958
  } catch {
52904
52959
  }
52905
52960
  }
@@ -52907,7 +52962,7 @@ function cleanupStaleArtifacts(binDir) {
52907
52962
  }
52908
52963
  function safeUnlink(p2) {
52909
52964
  try {
52910
- import_node_fs32.default.unlinkSync(p2);
52965
+ import_node_fs33.default.unlinkSync(p2);
52911
52966
  } catch {
52912
52967
  }
52913
52968
  }
@@ -52918,13 +52973,13 @@ async function downloadToFile(url, dest, fetchImpl) {
52918
52973
  if (!res.ok || !res.body) {
52919
52974
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
52920
52975
  }
52921
- const out = import_node_fs32.default.createWriteStream(dest);
52976
+ const out = import_node_fs33.default.createWriteStream(dest);
52922
52977
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
52923
52978
  await (0, import_promises4.pipeline)(nodeStream, out);
52924
52979
  }
52925
52980
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
52926
52981
  const work = import_node_path33.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
52927
- import_node_fs32.default.mkdirSync(work, { recursive: true });
52982
+ import_node_fs33.default.mkdirSync(work, { recursive: true });
52928
52983
  try {
52929
52984
  await new Promise((resolve6, reject) => {
52930
52985
  const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -52933,17 +52988,17 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
52933
52988
  });
52934
52989
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
52935
52990
  const src = import_node_path33.default.join(work, dirName, "frpc");
52936
- if (!import_node_fs32.default.existsSync(src)) {
52991
+ if (!import_node_fs33.default.existsSync(src)) {
52937
52992
  throw new Error(`frpc not found inside tarball at ${src}`);
52938
52993
  }
52939
- import_node_fs32.default.copyFileSync(src, destBin);
52994
+ import_node_fs33.default.copyFileSync(src, destBin);
52940
52995
  } finally {
52941
- import_node_fs32.default.rmSync(work, { recursive: true, force: true });
52996
+ import_node_fs33.default.rmSync(work, { recursive: true, force: true });
52942
52997
  }
52943
52998
  }
52944
52999
 
52945
53000
  // src/tunnel/frpc-process.ts
52946
- var import_node_fs33 = __toESM(require("fs"), 1);
53001
+ var import_node_fs34 = __toESM(require("fs"), 1);
52947
53002
  var import_node_path34 = __toESM(require("path"), 1);
52948
53003
  var import_node_child_process8 = require("child_process");
52949
53004
  function frpcPidFilePath(dataDir) {
@@ -52951,13 +53006,13 @@ function frpcPidFilePath(dataDir) {
52951
53006
  }
52952
53007
  function writeFrpcPid(dataDir, pid) {
52953
53008
  try {
52954
- import_node_fs33.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
53009
+ import_node_fs34.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
52955
53010
  } catch {
52956
53011
  }
52957
53012
  }
52958
53013
  function clearFrpcPid(dataDir) {
52959
53014
  try {
52960
- import_node_fs33.default.unlinkSync(frpcPidFilePath(dataDir));
53015
+ import_node_fs34.default.unlinkSync(frpcPidFilePath(dataDir));
52961
53016
  } catch {
52962
53017
  }
52963
53018
  }
@@ -52973,7 +53028,7 @@ function defaultIsPidAlive(pid) {
52973
53028
  }
52974
53029
  function defaultReadPidFile(file) {
52975
53030
  try {
52976
- return import_node_fs33.default.readFileSync(file, "utf8");
53031
+ return import_node_fs34.default.readFileSync(file, "utf8");
52977
53032
  } catch {
52978
53033
  return null;
52979
53034
  }
@@ -53013,7 +53068,7 @@ async function killStaleFrpc(deps) {
53013
53068
  }
53014
53069
  if (victims.size === 0) {
53015
53070
  try {
53016
- import_node_fs33.default.unlinkSync(pidFile);
53071
+ import_node_fs34.default.unlinkSync(pidFile);
53017
53072
  } catch {
53018
53073
  }
53019
53074
  return;
@@ -53024,7 +53079,7 @@ async function killStaleFrpc(deps) {
53024
53079
  }
53025
53080
  await sleep2(deps.reapWaitMs ?? 300);
53026
53081
  try {
53027
- import_node_fs33.default.unlinkSync(pidFile);
53082
+ import_node_fs34.default.unlinkSync(pidFile);
53028
53083
  } catch {
53029
53084
  }
53030
53085
  }
@@ -53199,14 +53254,14 @@ var TunnelManager = class {
53199
53254
  localPort,
53200
53255
  logLevel: "info"
53201
53256
  });
53202
- await import_node_fs34.default.promises.writeFile(tomlPath, toml, { mode: 384 });
53257
+ await import_node_fs35.default.promises.writeFile(tomlPath, toml, { mode: 384 });
53203
53258
  const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
53204
53259
  stdio: ["ignore", "pipe", "pipe"]
53205
53260
  });
53206
53261
  const logDir = import_node_path35.default.join(this.deps.dataDir, "log");
53207
- import_node_fs34.default.mkdirSync(logDir, { recursive: true });
53262
+ import_node_fs35.default.mkdirSync(logDir, { recursive: true });
53208
53263
  const logFilePath = import_node_path35.default.join(logDir, "frpc.log");
53209
- const logStream = import_node_fs34.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
53264
+ const logStream = import_node_fs35.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
53210
53265
  logStream.on("error", () => {
53211
53266
  });
53212
53267
  const tee = (chunk) => {
@@ -53288,7 +53343,7 @@ async function waitForFrpcReady(proc, timeoutMs) {
53288
53343
  }
53289
53344
 
53290
53345
  // src/sshd/sshd-manager.ts
53291
- var import_node_fs38 = __toESM(require("fs"), 1);
53346
+ var import_node_fs39 = __toESM(require("fs"), 1);
53292
53347
  var import_node_path39 = __toESM(require("path"), 1);
53293
53348
  var import_node_child_process11 = require("child_process");
53294
53349
 
@@ -53314,7 +53369,7 @@ function buildSshdConfig(input) {
53314
53369
  }
53315
53370
 
53316
53371
  // src/sshd/sshd-process.ts
53317
- var import_node_fs35 = __toESM(require("fs"), 1);
53372
+ var import_node_fs36 = __toESM(require("fs"), 1);
53318
53373
  var import_node_path36 = __toESM(require("path"), 1);
53319
53374
  var import_node_child_process10 = require("child_process");
53320
53375
  function sshdPidFilePath(dataDir) {
@@ -53323,14 +53378,14 @@ function sshdPidFilePath(dataDir) {
53323
53378
  function writeSshdPid(dataDir, pid) {
53324
53379
  try {
53325
53380
  const p2 = sshdPidFilePath(dataDir);
53326
- import_node_fs35.default.mkdirSync(import_node_path36.default.dirname(p2), { recursive: true, mode: 448 });
53327
- import_node_fs35.default.writeFileSync(p2, String(pid), { mode: 384 });
53381
+ import_node_fs36.default.mkdirSync(import_node_path36.default.dirname(p2), { recursive: true, mode: 448 });
53382
+ import_node_fs36.default.writeFileSync(p2, String(pid), { mode: 384 });
53328
53383
  } catch {
53329
53384
  }
53330
53385
  }
53331
53386
  function clearSshdPid(dataDir) {
53332
53387
  try {
53333
- import_node_fs35.default.unlinkSync(sshdPidFilePath(dataDir));
53388
+ import_node_fs36.default.unlinkSync(sshdPidFilePath(dataDir));
53334
53389
  } catch {
53335
53390
  }
53336
53391
  }
@@ -53346,7 +53401,7 @@ function defaultIsPidAlive2(pid) {
53346
53401
  }
53347
53402
  function defaultReadPidFile2(file) {
53348
53403
  try {
53349
- return import_node_fs35.default.readFileSync(file, "utf8");
53404
+ return import_node_fs36.default.readFileSync(file, "utf8");
53350
53405
  } catch {
53351
53406
  return null;
53352
53407
  }
@@ -53386,7 +53441,7 @@ async function killStaleSshd(deps) {
53386
53441
  }
53387
53442
  if (victims.size === 0) {
53388
53443
  try {
53389
- import_node_fs35.default.unlinkSync(pidFile);
53444
+ import_node_fs36.default.unlinkSync(pidFile);
53390
53445
  } catch {
53391
53446
  }
53392
53447
  return;
@@ -53397,7 +53452,7 @@ async function killStaleSshd(deps) {
53397
53452
  }
53398
53453
  await sleep2(deps.reapWaitMs ?? 300);
53399
53454
  try {
53400
- import_node_fs35.default.unlinkSync(pidFile);
53455
+ import_node_fs36.default.unlinkSync(pidFile);
53401
53456
  } catch {
53402
53457
  }
53403
53458
  }
@@ -53430,7 +53485,7 @@ async function defaultScanSshdPidsByCmdline(configPath, logger) {
53430
53485
  }
53431
53486
 
53432
53487
  // src/sshd/jail-script.ts
53433
- var import_node_fs36 = __toESM(require("fs"), 1);
53488
+ var import_node_fs37 = __toESM(require("fs"), 1);
53434
53489
  var import_node_path37 = __toESM(require("path"), 1);
53435
53490
  var CLAWD_SSH_JAIL_SCRIPT = String.raw`#!/usr/bin/env bash
53436
53491
  # clawd-ssh-jail — SSH reverse access sandbox wrapper (managed by clawd; do not edit)
@@ -53569,14 +53624,14 @@ esac
53569
53624
  `;
53570
53625
  function ensureJailScript(dataDir) {
53571
53626
  const binDir = import_node_path37.default.join(dataDir, "bin");
53572
- import_node_fs36.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53627
+ import_node_fs37.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53573
53628
  const target = import_node_path37.default.join(binDir, "clawd-ssh-jail");
53574
- import_node_fs36.default.writeFileSync(target, CLAWD_SSH_JAIL_SCRIPT, { mode: 493 });
53629
+ import_node_fs37.default.writeFileSync(target, CLAWD_SSH_JAIL_SCRIPT, { mode: 493 });
53575
53630
  return target;
53576
53631
  }
53577
53632
 
53578
53633
  // src/sshd/clawd-shim.ts
53579
- var import_node_fs37 = __toESM(require("fs"), 1);
53634
+ var import_node_fs38 = __toESM(require("fs"), 1);
53580
53635
  var import_node_path38 = __toESM(require("path"), 1);
53581
53636
  function shellQuote(s) {
53582
53637
  return `'${s.replace(/'/g, "'\\''")}'`;
@@ -53593,9 +53648,9 @@ exec ${shellQuote(execPath)} ${shellQuote(cliPath)} "$@"
53593
53648
  }
53594
53649
  function ensureClawdShim(dataDir, execPath, cliPath) {
53595
53650
  const binDir = import_node_path38.default.join(dataDir, "bin");
53596
- import_node_fs37.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53651
+ import_node_fs38.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53597
53652
  const target = import_node_path38.default.join(binDir, "clawd");
53598
- import_node_fs37.default.writeFileSync(target, buildClawdShim(execPath, cliPath), { mode: 493 });
53653
+ import_node_fs38.default.writeFileSync(target, buildClawdShim(execPath, cliPath), { mode: 493 });
53599
53654
  return target;
53600
53655
  }
53601
53656
 
@@ -53622,17 +53677,17 @@ var SshdManager = class {
53622
53677
  ownPid: process.pid,
53623
53678
  logger
53624
53679
  });
53625
- import_node_fs38.default.mkdirSync(this.sshdDir, { recursive: true, mode: 448 });
53626
- import_node_fs38.default.mkdirSync(import_node_path39.default.join(this.sshdDir, "authorized_keys.d"), { recursive: true, mode: 448 });
53680
+ import_node_fs39.default.mkdirSync(this.sshdDir, { recursive: true, mode: 448 });
53681
+ import_node_fs39.default.mkdirSync(import_node_path39.default.join(this.sshdDir, "authorized_keys.d"), { recursive: true, mode: 448 });
53627
53682
  ensureJailScript(this.deps.dataDir);
53628
53683
  ensureClawdShim(this.deps.dataDir, process.execPath, process.argv[1] ?? "");
53629
53684
  const hostKeyPath = import_node_path39.default.join(this.sshdDir, "host_key");
53630
- if (!import_node_fs38.default.existsSync(hostKeyPath)) {
53685
+ if (!import_node_fs39.default.existsSync(hostKeyPath)) {
53631
53686
  await this.generateHostKey(hostKeyPath);
53632
53687
  }
53633
53688
  const akFile = import_node_path39.default.join(this.sshdDir, "authorized_keys.d", "clawd-contacts");
53634
- if (!import_node_fs38.default.existsSync(akFile)) {
53635
- import_node_fs38.default.writeFileSync(akFile, "", { mode: 384 });
53689
+ if (!import_node_fs39.default.existsSync(akFile)) {
53690
+ import_node_fs39.default.writeFileSync(akFile, "", { mode: 384 });
53636
53691
  }
53637
53692
  const configPath = import_node_path39.default.join(this.sshdDir, "sshd_config");
53638
53693
  const config = buildSshdConfig({
@@ -53642,14 +53697,14 @@ var SshdManager = class {
53642
53697
  authorizedKeysFile: akFile,
53643
53698
  pidFilePath: import_node_path39.default.join(this.sshdDir, "sshd.pid")
53644
53699
  });
53645
- import_node_fs38.default.writeFileSync(configPath, config, { mode: 384 });
53700
+ import_node_fs39.default.writeFileSync(configPath, config, { mode: 384 });
53646
53701
  const sshdBin = this.deps.sshdBin ?? "/usr/sbin/sshd";
53647
53702
  const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(sshdBin, ["-D", "-e", "-f", configPath], {
53648
53703
  stdio: ["ignore", "pipe", "pipe"]
53649
53704
  });
53650
53705
  const sshdLogDir = import_node_path39.default.join(this.deps.dataDir, "log");
53651
- import_node_fs38.default.mkdirSync(sshdLogDir, { recursive: true });
53652
- const logStream = import_node_fs38.default.createWriteStream(import_node_path39.default.join(sshdLogDir, "sshd.log"), {
53706
+ import_node_fs39.default.mkdirSync(sshdLogDir, { recursive: true });
53707
+ const logStream = import_node_fs39.default.createWriteStream(import_node_path39.default.join(sshdLogDir, "sshd.log"), {
53653
53708
  flags: "a",
53654
53709
  mode: 384
53655
53710
  });
@@ -53742,7 +53797,7 @@ ${tail}` : ready.error;
53742
53797
  p2.on("error", reject);
53743
53798
  });
53744
53799
  try {
53745
- import_node_fs38.default.chmodSync(hostKeyPath, 384);
53800
+ import_node_fs39.default.chmodSync(hostKeyPath, 384);
53746
53801
  } catch {
53747
53802
  }
53748
53803
  }
@@ -53785,7 +53840,7 @@ async function waitForSshdReady(proc, timeoutMs) {
53785
53840
  }
53786
53841
 
53787
53842
  // src/sshd/authorized-keys.ts
53788
- var import_node_fs39 = __toESM(require("fs"), 1);
53843
+ var import_node_fs40 = __toESM(require("fs"), 1);
53789
53844
  var import_node_path40 = __toESM(require("path"), 1);
53790
53845
  var JAIL_BIN_PATH_ENV = "CLAWD_JAIL_BIN_PATH";
53791
53846
  var AUTHORIZED_KEYS_FILE = "clawd-contacts";
@@ -53795,7 +53850,7 @@ function jailBinPath() {
53795
53850
  function rebuildAuthorizedKeys(store, sshdDir) {
53796
53851
  const akDir = import_node_path40.default.join(sshdDir, "authorized_keys.d");
53797
53852
  const target = import_node_path40.default.join(akDir, AUTHORIZED_KEYS_FILE);
53798
- import_node_fs39.default.mkdirSync(akDir, { recursive: true, mode: 448 });
53853
+ import_node_fs40.default.mkdirSync(akDir, { recursive: true, mode: 448 });
53799
53854
  const lines = ["# managed by clawd; do not edit", ""];
53800
53855
  for (const c of store.list()) {
53801
53856
  if (!c.sshAllowed) continue;
@@ -53809,25 +53864,25 @@ function rebuildAuthorizedKeys(store, sshdDir) {
53809
53864
  }
53810
53865
  const body = lines.join("\n") + "\n";
53811
53866
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
53812
- import_node_fs39.default.writeFileSync(tmp, body, { mode: 384 });
53813
- import_node_fs39.default.renameSync(tmp, target);
53867
+ import_node_fs40.default.writeFileSync(tmp, body, { mode: 384 });
53868
+ import_node_fs40.default.renameSync(tmp, target);
53814
53869
  }
53815
53870
  function readIssuedPubkey(sshdDir, deviceId) {
53816
53871
  const safeId = deviceId.replace(/[\/\\]/g, "_");
53817
53872
  const p2 = import_node_path40.default.join(sshdDir, "keys", `${safeId}.ed25519.pub`);
53818
53873
  try {
53819
- return import_node_fs39.default.readFileSync(p2, "utf8");
53874
+ return import_node_fs40.default.readFileSync(p2, "utf8");
53820
53875
  } catch {
53821
53876
  return null;
53822
53877
  }
53823
53878
  }
53824
53879
 
53825
53880
  // src/sshd/contact-key-puller.ts
53826
- var import_node_fs41 = __toESM(require("fs"), 1);
53881
+ var import_node_fs42 = __toESM(require("fs"), 1);
53827
53882
  var import_node_path42 = __toESM(require("path"), 1);
53828
53883
 
53829
53884
  // src/sshd/contact-ssh-log.ts
53830
- var import_node_fs40 = __toESM(require("fs"), 1);
53885
+ var import_node_fs41 = __toESM(require("fs"), 1);
53831
53886
  var import_node_path41 = __toESM(require("path"), 1);
53832
53887
  function createContactSshLog(dataDir) {
53833
53888
  const file = import_node_path41.default.join(dataDir, "log", "contact-ssh.log");
@@ -53843,8 +53898,8 @@ function createContactSshLog(dataDir) {
53843
53898
  }
53844
53899
  line += "\n";
53845
53900
  try {
53846
- import_node_fs40.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
53847
- import_node_fs40.default.appendFileSync(file, line, { mode: 384 });
53901
+ import_node_fs41.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
53902
+ import_node_fs41.default.appendFileSync(file, line, { mode: 384 });
53848
53903
  } catch {
53849
53904
  }
53850
53905
  }
@@ -53933,12 +53988,12 @@ async function pullContactSshKeyOnce(deps) {
53933
53988
  }
53934
53989
  function writeKeyFile(dataDir, deviceId, pem) {
53935
53990
  const p2 = safeContactKeyPath(dataDir, deviceId);
53936
- import_node_fs41.default.mkdirSync(import_node_path42.default.dirname(p2), { recursive: true, mode: 448 });
53937
- import_node_fs41.default.writeFileSync(p2, pem, { mode: 384 });
53991
+ import_node_fs42.default.mkdirSync(import_node_path42.default.dirname(p2), { recursive: true, mode: 448 });
53992
+ import_node_fs42.default.writeFileSync(p2, pem, { mode: 384 });
53938
53993
  }
53939
53994
  function removeKeyFile(dataDir, deviceId) {
53940
53995
  try {
53941
- import_node_fs41.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53996
+ import_node_fs42.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53942
53997
  return true;
53943
53998
  } catch {
53944
53999
  return false;
@@ -54273,7 +54328,7 @@ function deriveStableDeviceKey(opts = {}) {
54273
54328
  }
54274
54329
 
54275
54330
  // src/auth-store.ts
54276
- var import_node_fs42 = __toESM(require("fs"), 1);
54331
+ var import_node_fs43 = __toESM(require("fs"), 1);
54277
54332
  var import_node_path44 = __toESM(require("path"), 1);
54278
54333
  var import_node_crypto12 = __toESM(require("crypto"), 1);
54279
54334
  var AUTH_FILE_NAME = "auth.json";
@@ -54314,7 +54369,7 @@ function defaultGenerateOwnerPrincipalId() {
54314
54369
  }
54315
54370
  function readAuthFile(file) {
54316
54371
  try {
54317
- const raw = import_node_fs42.default.readFileSync(file, "utf8");
54372
+ const raw = import_node_fs43.default.readFileSync(file, "utf8");
54318
54373
  const parsed = JSON.parse(raw);
54319
54374
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
54320
54375
  return null;
@@ -54334,16 +54389,16 @@ function readAuthFile(file) {
54334
54389
  }
54335
54390
  }
54336
54391
  function writeAuthFile(file, content) {
54337
- import_node_fs42.default.mkdirSync(import_node_path44.default.dirname(file), { recursive: true });
54338
- import_node_fs42.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
54392
+ import_node_fs43.default.mkdirSync(import_node_path44.default.dirname(file), { recursive: true });
54393
+ import_node_fs43.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
54339
54394
  try {
54340
- import_node_fs42.default.chmodSync(file, 384);
54395
+ import_node_fs43.default.chmodSync(file, 384);
54341
54396
  } catch {
54342
54397
  }
54343
54398
  }
54344
54399
 
54345
54400
  // src/owner-profile.ts
54346
- var import_node_fs43 = __toESM(require("fs"), 1);
54401
+ var import_node_fs44 = __toESM(require("fs"), 1);
54347
54402
  var import_node_os15 = __toESM(require("os"), 1);
54348
54403
  var import_node_path45 = __toESM(require("path"), 1);
54349
54404
  var PROFILE_FILENAME = "profile.json";
@@ -54352,7 +54407,7 @@ function loadOwnerDisplayName(dataDir) {
54352
54407
  const profilePath = import_node_path45.default.join(dataDir, PROFILE_FILENAME);
54353
54408
  let raw;
54354
54409
  try {
54355
- raw = import_node_fs43.default.readFileSync(profilePath, "utf8");
54410
+ raw = import_node_fs44.default.readFileSync(profilePath, "utf8");
54356
54411
  } catch {
54357
54412
  return fallback;
54358
54413
  }
@@ -54375,7 +54430,7 @@ function loadOwnerDisplayName(dataDir) {
54375
54430
  }
54376
54431
 
54377
54432
  // src/feishu-auth/owner-identity-store.ts
54378
- var import_node_fs44 = __toESM(require("fs"), 1);
54433
+ var import_node_fs45 = __toESM(require("fs"), 1);
54379
54434
  var import_node_path46 = __toESM(require("path"), 1);
54380
54435
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
54381
54436
  var OwnerIdentityStore = class {
@@ -54386,7 +54441,7 @@ var OwnerIdentityStore = class {
54386
54441
  read() {
54387
54442
  let raw;
54388
54443
  try {
54389
- raw = import_node_fs44.default.readFileSync(this.file, "utf8");
54444
+ raw = import_node_fs45.default.readFileSync(this.file, "utf8");
54390
54445
  } catch {
54391
54446
  return null;
54392
54447
  }
@@ -54414,16 +54469,16 @@ var OwnerIdentityStore = class {
54414
54469
  };
54415
54470
  }
54416
54471
  write(record) {
54417
- import_node_fs44.default.mkdirSync(import_node_path46.default.dirname(this.file), { recursive: true });
54418
- import_node_fs44.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
54472
+ import_node_fs45.default.mkdirSync(import_node_path46.default.dirname(this.file), { recursive: true });
54473
+ import_node_fs45.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
54419
54474
  try {
54420
- import_node_fs44.default.chmodSync(this.file, 384);
54475
+ import_node_fs45.default.chmodSync(this.file, 384);
54421
54476
  } catch {
54422
54477
  }
54423
54478
  }
54424
54479
  clear() {
54425
54480
  try {
54426
- import_node_fs44.default.unlinkSync(this.file);
54481
+ import_node_fs45.default.unlinkSync(this.file);
54427
54482
  } catch (err) {
54428
54483
  const code = err?.code;
54429
54484
  if (code !== "ENOENT") throw err;
@@ -54756,7 +54811,7 @@ function verifyConnectToken(args) {
54756
54811
  }
54757
54812
 
54758
54813
  // src/feishu-auth/server-key.ts
54759
- var fs54 = __toESM(require("fs"), 1);
54814
+ var fs55 = __toESM(require("fs"), 1);
54760
54815
  var path55 = __toESM(require("path"), 1);
54761
54816
  var FILE_NAME2 = "server-signing-key.json";
54762
54817
  var ServerKeyStore = class {
@@ -54770,7 +54825,7 @@ var ServerKeyStore = class {
54770
54825
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
54771
54826
  read() {
54772
54827
  try {
54773
- const raw = fs54.readFileSync(this.filePath(), "utf8");
54828
+ const raw = fs55.readFileSync(this.filePath(), "utf8");
54774
54829
  const parsed = JSON.parse(raw);
54775
54830
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
54776
54831
  return parsed.publicKeyPem;
@@ -54785,12 +54840,12 @@ var ServerKeyStore = class {
54785
54840
  publicKeyPem,
54786
54841
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
54787
54842
  };
54788
- fs54.mkdirSync(this.dataDir, { recursive: true });
54789
- fs54.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54843
+ fs55.mkdirSync(this.dataDir, { recursive: true });
54844
+ fs55.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54790
54845
  }
54791
54846
  clear() {
54792
54847
  try {
54793
- fs54.unlinkSync(this.filePath());
54848
+ fs55.unlinkSync(this.filePath());
54794
54849
  } catch {
54795
54850
  }
54796
54851
  }
@@ -54803,12 +54858,12 @@ init_protocol();
54803
54858
  init_protocol();
54804
54859
 
54805
54860
  // src/session/fork.ts
54806
- var import_node_fs45 = __toESM(require("fs"), 1);
54861
+ var import_node_fs46 = __toESM(require("fs"), 1);
54807
54862
  var import_node_os16 = __toESM(require("os"), 1);
54808
54863
  var import_node_path47 = __toESM(require("path"), 1);
54809
54864
  init_claude_history();
54810
54865
  function readJsonlEntries(file) {
54811
- const raw = import_node_fs45.default.readFileSync(file, "utf8");
54866
+ const raw = import_node_fs46.default.readFileSync(file, "utf8");
54812
54867
  const out = [];
54813
54868
  for (const line of raw.split("\n")) {
54814
54869
  const t = line.trim();
@@ -54824,7 +54879,7 @@ function forkSession(input) {
54824
54879
  const baseDir = input.baseDir ?? import_node_path47.default.join(import_node_os16.default.homedir(), ".claude");
54825
54880
  let projectDir = import_node_path47.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54826
54881
  let sourceFile = import_node_path47.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54827
- if (!import_node_fs45.default.existsSync(sourceFile)) {
54882
+ if (!import_node_fs46.default.existsSync(sourceFile)) {
54828
54883
  const found = findTranscriptByToolSessionId(
54829
54884
  import_node_path47.default.join(baseDir, "projects"),
54830
54885
  input.toolSessionId
@@ -54863,8 +54918,8 @@ function forkSession(input) {
54863
54918
  forkedLines.push(JSON.stringify(forked));
54864
54919
  }
54865
54920
  const forkedFilePath = import_node_path47.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54866
- import_node_fs45.default.mkdirSync(projectDir, { recursive: true });
54867
- import_node_fs45.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54921
+ import_node_fs46.default.mkdirSync(projectDir, { recursive: true });
54922
+ import_node_fs46.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54868
54923
  return { forkedToolSessionId, forkedFilePath };
54869
54924
  }
54870
54925
 
@@ -55498,14 +55553,14 @@ init_protocol();
55498
55553
 
55499
55554
  // src/workspace/git.ts
55500
55555
  var import_node_child_process12 = require("child_process");
55501
- var import_node_fs46 = __toESM(require("fs"), 1);
55556
+ var import_node_fs47 = __toESM(require("fs"), 1);
55502
55557
  var import_node_path48 = __toESM(require("path"), 1);
55503
55558
  var import_node_util = require("util");
55504
55559
  var pexec = (0, import_node_util.promisify)(import_node_child_process12.execFile);
55505
55560
  function normalizePath(p2) {
55506
55561
  const resolved = import_node_path48.default.resolve(p2);
55507
55562
  try {
55508
- return import_node_fs46.default.realpathSync(resolved);
55563
+ return import_node_fs47.default.realpathSync(resolved);
55509
55564
  } catch {
55510
55565
  return resolved;
55511
55566
  }
@@ -55916,7 +55971,7 @@ function buildContactHandlers(deps) {
55916
55971
  init_protocol();
55917
55972
 
55918
55973
  // src/sshd/key-issue.ts
55919
- var import_node_fs47 = __toESM(require("fs"), 1);
55974
+ var import_node_fs48 = __toESM(require("fs"), 1);
55920
55975
  var import_node_path49 = __toESM(require("path"), 1);
55921
55976
  var import_node_child_process13 = require("child_process");
55922
55977
  function safeDeviceId(deviceId) {
@@ -55925,13 +55980,13 @@ function safeDeviceId(deviceId) {
55925
55980
  async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55926
55981
  const safeId = safeDeviceId(deviceId);
55927
55982
  const keysDir = import_node_path49.default.join(sshdDir, "keys");
55928
- import_node_fs47.default.mkdirSync(keysDir, { recursive: true, mode: 448 });
55983
+ import_node_fs48.default.mkdirSync(keysDir, { recursive: true, mode: 448 });
55929
55984
  const privPath = import_node_path49.default.join(keysDir, `${safeId}.ed25519`);
55930
55985
  const pubPath = `${privPath}.pub`;
55931
- if (import_node_fs47.default.existsSync(privPath) && import_node_fs47.default.existsSync(pubPath)) {
55986
+ if (import_node_fs48.default.existsSync(privPath) && import_node_fs48.default.existsSync(pubPath)) {
55932
55987
  return {
55933
- privateKeyPem: import_node_fs47.default.readFileSync(privPath, "utf8"),
55934
- publicKeyLine: import_node_fs47.default.readFileSync(pubPath, "utf8").trim()
55988
+ privateKeyPem: import_node_fs48.default.readFileSync(privPath, "utf8"),
55989
+ publicKeyLine: import_node_fs48.default.readFileSync(pubPath, "utf8").trim()
55935
55990
  };
55936
55991
  }
55937
55992
  const bin = opts.keygenBin ?? "/usr/bin/ssh-keygen";
@@ -55945,16 +56000,16 @@ async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55945
56000
  p2.on("error", reject);
55946
56001
  });
55947
56002
  try {
55948
- import_node_fs47.default.chmodSync(privPath, 384);
56003
+ import_node_fs48.default.chmodSync(privPath, 384);
55949
56004
  } catch {
55950
56005
  }
55951
56006
  try {
55952
- import_node_fs47.default.chmodSync(pubPath, 420);
56007
+ import_node_fs48.default.chmodSync(pubPath, 420);
55953
56008
  } catch {
55954
56009
  }
55955
56010
  return {
55956
- privateKeyPem: import_node_fs47.default.readFileSync(privPath, "utf8"),
55957
- publicKeyLine: import_node_fs47.default.readFileSync(pubPath, "utf8").trim()
56011
+ privateKeyPem: import_node_fs48.default.readFileSync(privPath, "utf8"),
56012
+ publicKeyLine: import_node_fs48.default.readFileSync(pubPath, "utf8").trim()
55958
56013
  };
55959
56014
  }
55960
56015
 
@@ -57235,7 +57290,7 @@ function buildExtensionHandlers(deps) {
57235
57290
  }
57236
57291
 
57237
57292
  // src/app-builder/project-store.ts
57238
- var import_node_fs48 = require("fs");
57293
+ var import_node_fs49 = require("fs");
57239
57294
  var import_node_child_process14 = require("child_process");
57240
57295
  var import_node_path56 = require("path");
57241
57296
  init_protocol();
@@ -57263,7 +57318,7 @@ var ProjectStore = class {
57263
57318
  async list() {
57264
57319
  let entries;
57265
57320
  try {
57266
- entries = await import_node_fs48.promises.readdir(this.projectsRoot());
57321
+ entries = await import_node_fs49.promises.readdir(this.projectsRoot());
57267
57322
  } catch (err) {
57268
57323
  if (err.code === "ENOENT") return [];
57269
57324
  throw err;
@@ -57271,7 +57326,7 @@ var ProjectStore = class {
57271
57326
  const out = [];
57272
57327
  for (const name of entries) {
57273
57328
  try {
57274
- const raw = await import_node_fs48.promises.readFile(this.metaPath(name), "utf8");
57329
+ const raw = await import_node_fs49.promises.readFile(this.metaPath(name), "utf8");
57275
57330
  const json = JSON.parse(raw);
57276
57331
  let migrated = false;
57277
57332
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -57282,7 +57337,7 @@ var ProjectStore = class {
57282
57337
  if (parsed.success) {
57283
57338
  out.push(parsed.data);
57284
57339
  if (migrated) {
57285
- void import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
57340
+ void import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
57286
57341
  });
57287
57342
  }
57288
57343
  }
@@ -57326,8 +57381,8 @@ var ProjectStore = class {
57326
57381
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
57327
57382
  }
57328
57383
  const dir = this.projectDir(name);
57329
- await import_node_fs48.promises.mkdir(dir, { recursive: true });
57330
- await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
57384
+ await import_node_fs49.promises.mkdir(dir, { recursive: true });
57385
+ await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
57331
57386
  return meta;
57332
57387
  }
57333
57388
  /**
@@ -57370,7 +57425,7 @@ var ProjectStore = class {
57370
57425
  }
57371
57426
  async delete(name) {
57372
57427
  const dir = this.projectDir(name);
57373
- await import_node_fs48.promises.rm(dir, { recursive: true, force: true });
57428
+ await import_node_fs49.promises.rm(dir, { recursive: true, force: true });
57374
57429
  }
57375
57430
  async updatePort(name, newPort) {
57376
57431
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -57386,7 +57441,7 @@ var ProjectStore = class {
57386
57441
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
57387
57442
  }
57388
57443
  const updated = { ...target, port: newPort };
57389
- await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
57444
+ await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
57390
57445
  return updated;
57391
57446
  }
57392
57447
  /**
@@ -57403,7 +57458,7 @@ var ProjectStore = class {
57403
57458
  if (!validated.success) {
57404
57459
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
57405
57460
  }
57406
- await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
57461
+ await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
57407
57462
  return validated.data;
57408
57463
  }
57409
57464
  /**
@@ -57424,7 +57479,7 @@ var ProjectStore = class {
57424
57479
  if (!validated.success) {
57425
57480
  throw new Error(`invalid publishJob: ${validated.error.message}`);
57426
57481
  }
57427
- await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
57482
+ await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
57428
57483
  return validated.data;
57429
57484
  }
57430
57485
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -57439,7 +57494,7 @@ var ProjectStore = class {
57439
57494
  if (!validated.success) {
57440
57495
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
57441
57496
  }
57442
- await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
57497
+ await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
57443
57498
  return validated.data;
57444
57499
  }
57445
57500
  };
@@ -57560,7 +57615,7 @@ var PublishJobRegistry = class {
57560
57615
 
57561
57616
  // src/app-builder/publish-job-runner.ts
57562
57617
  var import_node_child_process16 = require("child_process");
57563
- var import_node_fs49 = require("fs");
57618
+ var import_node_fs50 = require("fs");
57564
57619
  var import_node_path57 = require("path");
57565
57620
 
57566
57621
  // src/app-builder/publish-stage-parser.ts
@@ -57596,7 +57651,7 @@ async function startPublishJob(deps, args) {
57596
57651
  const logPath = (0, import_node_path57.join)(projDir, ".publish.log");
57597
57652
  let logStream = null;
57598
57653
  try {
57599
- logStream = (0, import_node_fs49.createWriteStream)(logPath, { flags: "w" });
57654
+ logStream = (0, import_node_fs50.createWriteStream)(logPath, { flags: "w" });
57600
57655
  } catch {
57601
57656
  logStream = null;
57602
57657
  }
@@ -57854,7 +57909,7 @@ async function recoverInterruptedJobs(deps) {
57854
57909
  // src/handlers/app-builder.ts
57855
57910
  init_protocol();
57856
57911
  var import_node_path58 = require("path");
57857
- var import_node_fs50 = require("fs");
57912
+ var import_node_fs51 = require("fs");
57858
57913
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
57859
57914
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
57860
57915
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -57935,7 +57990,7 @@ function buildAppBuilderHandlers(deps) {
57935
57990
  async function listAllUsersProjects() {
57936
57991
  if (!deps.usersRoot || !deps.getStore) return [];
57937
57992
  const getStore = deps.getStore;
57938
- const userIds = await import_node_fs50.promises.readdir(deps.usersRoot).catch(() => []);
57993
+ const userIds = await import_node_fs51.promises.readdir(deps.usersRoot).catch(() => []);
57939
57994
  const perUser = await Promise.all(
57940
57995
  userIds.map((uid) => getStore(uid).list().catch(() => []))
57941
57996
  );
@@ -59442,7 +59497,7 @@ async function startDaemon(config) {
59442
59497
  homeDir: import_node_os21.default.homedir()
59443
59498
  });
59444
59499
  const logDir = import_node_path64.default.join(config.dataDir, "log");
59445
- import_node_fs51.default.mkdirSync(logDir, { recursive: true });
59500
+ import_node_fs52.default.mkdirSync(logDir, { recursive: true });
59446
59501
  const logger = createLogger({
59447
59502
  level: config.logLevel,
59448
59503
  file: import_node_path64.default.join(logDir, "clawd.log"),
@@ -59456,6 +59511,24 @@ async function startDaemon(config) {
59456
59511
  logger.info("screen-idle probe logger enabled", {
59457
59512
  file: import_node_path64.default.join(logDir, "screen-idle-probe.log")
59458
59513
  });
59514
+ const CAP_TARGETS = [
59515
+ import_node_path64.default.join(logDir, "clawd.log"),
59516
+ import_node_path64.default.join(logDir, "screen-idle-probe.log")
59517
+ ];
59518
+ const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
59519
+ const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
59520
+ const runLogCap = () => {
59521
+ for (const f of CAP_TARGETS) {
59522
+ try {
59523
+ truncateLogFileToTail(f, LOG_CAP_MAX_BYTES, LOG_CAP_KEEP_BYTES);
59524
+ } catch (e) {
59525
+ logger.warn("log-cap failed", { file: f, err: String(e) });
59526
+ }
59527
+ }
59528
+ };
59529
+ runLogCap();
59530
+ const logCapTimer = setInterval(runLogCap, 10 * 60 * 1e3);
59531
+ logCapTimer.unref();
59459
59532
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
59460
59533
  const pre = stateMgr.preflight();
59461
59534
  if (pre.status === "active") {
@@ -59622,7 +59695,7 @@ async function startDaemon(config) {
59622
59695
  import_node_path64.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59623
59696
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
59624
59697
  ];
59625
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59698
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
59626
59699
  let dispatchMcpConfigPath2;
59627
59700
  if (dispatchServerScriptPath) {
59628
59701
  const dispatchLogPath = import_node_path64.default.join(logDir, "dispatch-mcp-server.log");
@@ -59645,7 +59718,7 @@ async function startDaemon(config) {
59645
59718
  import_node_path64.default.join(here, "ticket", "mcp-server.cjs"),
59646
59719
  import_node_path64.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59647
59720
  ];
59648
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59721
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
59649
59722
  let ticketMcpConfigPath2;
59650
59723
  if (ticketServerScriptPath) {
59651
59724
  const ticketLogPath = import_node_path64.default.join(logDir, "ticket-mcp-server.log");
@@ -59670,7 +59743,7 @@ async function startDaemon(config) {
59670
59743
  import_node_path64.default.join(here, "shift", "mcp-server.cjs"),
59671
59744
  import_node_path64.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59672
59745
  ];
59673
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59746
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
59674
59747
  let shiftMcpConfigPath2;
59675
59748
  if (shiftServerScriptPath) {
59676
59749
  const shiftLogPath = import_node_path64.default.join(logDir, "shift-mcp-server.log");
@@ -59694,7 +59767,7 @@ async function startDaemon(config) {
59694
59767
  import_node_path64.default.join(here, "inbox", "mcp-server.cjs"),
59695
59768
  import_node_path64.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59696
59769
  ];
59697
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59770
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
59698
59771
  let inboxMcpConfigPath2;
59699
59772
  if (inboxServerScriptPath) {
59700
59773
  const inboxLogPath = import_node_path64.default.join(logDir, "inbox-mcp-server.log");
@@ -59784,7 +59857,7 @@ async function startDaemon(config) {
59784
59857
  const absPath = import_node_path64.default.isAbsolute(input.relPath) ? input.relPath : import_node_path64.default.join(input.cwd, input.relPath);
59785
59858
  let size = 0;
59786
59859
  try {
59787
- size = import_node_fs51.default.statSync(absPath).size;
59860
+ size = import_node_fs52.default.statSync(absPath).size;
59788
59861
  } catch (err) {
59789
59862
  logger.warn("attachment.onFileEdit stat failed", {
59790
59863
  sessionId: input.sessionId,
@@ -59927,11 +60000,26 @@ async function startDaemon(config) {
59927
60000
  // deviceId 从 auth.json 稳定读;apiUrl 走同一份 clawosApi;apiKey 复用 CLAWD_TICKETS_API_KEY。
59928
60001
  // 失败即登录失败(fail-hard,login-flow.spec §upsert 失败)。
59929
60002
  getDeviceId: () => authFile.deviceId,
59930
- upsertBinding: (opts) => upsertDeviceBinding({
59931
- apiUrl: config.clawosApi ?? DEFAULT_CLAWOS_API,
59932
- apiKey: resolveClawdTicketsApiKey(),
59933
- ...opts
59934
- })
60003
+ upsertBinding: async (opts) => {
60004
+ try {
60005
+ await upsertDeviceBinding({
60006
+ apiUrl: config.clawosApi ?? DEFAULT_CLAWOS_API,
60007
+ apiKey: resolveClawdTicketsApiKey(),
60008
+ ...opts
60009
+ });
60010
+ logger.info("device-binding upsert succeeded", {
60011
+ deviceId: opts.deviceId,
60012
+ unionId: opts.unionId
60013
+ });
60014
+ } catch (err) {
60015
+ logger.warn("device-binding upsert failed", {
60016
+ deviceId: opts.deviceId,
60017
+ unionId: opts.unionId,
60018
+ error: err instanceof Error ? err.message : String(err)
60019
+ });
60020
+ throw err;
60021
+ }
60022
+ }
59935
60023
  });
59936
60024
  const visitorStore = createVisitorStore({ dir: config.dataDir });
59937
60025
  const exchangeVisitorToken = buildVisitorLogin({
@@ -60186,11 +60274,13 @@ async function startDaemon(config) {
60186
60274
  sourceJsonlPath,
60187
60275
  // B 角色(跨设备):非空 → guest scope + creatorPrincipalId/creatorDisplayName = A。
60188
60276
  guestPrincipalId: args.guestPrincipalId,
60189
- guestDisplayName: args.guestDisplayName
60277
+ guestDisplayName: args.guestDisplayName,
60278
+ // T-20: 可选 model override 透到 SessionFile.model
60279
+ ...args.model ? { model: args.model } : {}
60190
60280
  });
60191
60281
  },
60192
60282
  // A 角色:从 ContactStore 取 peer 可达 URL + connect token,转发到对端 daemon /rpc。
60193
- forwardToPeer: async ({ targetDeviceId, targetPersona, prompt }) => {
60283
+ forwardToPeer: async ({ targetDeviceId, targetPersona, prompt, model }) => {
60194
60284
  const contact = contactStore.get(targetDeviceId);
60195
60285
  if (!contact || !contact.remoteUrl || !contact.connectToken) {
60196
60286
  return {
@@ -60201,7 +60291,9 @@ async function startDaemon(config) {
60201
60291
  return forwardDispatchToPeer({
60202
60292
  contact: { remoteUrl: contact.remoteUrl, connectToken: contact.connectToken },
60203
60293
  targetPersona,
60204
- prompt
60294
+ prompt,
60295
+ // T-20: 跨设备也透 model,让远端 daemon 用同一 claude 模型 spawn B
60296
+ ...model ? { model } : {}
60205
60297
  });
60206
60298
  },
60207
60299
  // B 角色:判断 targetPersona 是否 public(跨设备授权边界,private 拒)。
@@ -60293,6 +60385,12 @@ async function startDaemon(config) {
60293
60385
  handleLoginCallback: async (params) => {
60294
60386
  const result = await loginFlow.handleCallback(params);
60295
60387
  if (result.ok) {
60388
+ logger.info("feishu-login succeeded", {
60389
+ deviceId: authFile.deviceId,
60390
+ ownerId: result.identity.ownerId,
60391
+ unionId: result.identity.unionId,
60392
+ displayName: result.identity.displayName
60393
+ });
60296
60394
  feishuActive = true;
60297
60395
  ownerId = result.identity.ownerId;
60298
60396
  ownerProvider = result.identity.provider;
@@ -60304,6 +60402,11 @@ async function startDaemon(config) {
60304
60402
  void reportDevice();
60305
60403
  void fetchServerKey();
60306
60404
  } else {
60405
+ logger.warn("feishu-login failed", {
60406
+ reason: result.reason,
60407
+ deviceId: authFile.deviceId,
60408
+ hasToken: Boolean(params.token)
60409
+ });
60307
60410
  wsServer?.broadcastToOwners({ type: "auth:login:failed", reason: result.reason });
60308
60411
  }
60309
60412
  return result;
@@ -60523,7 +60626,7 @@ ${bar}
60523
60626
  `);
60524
60627
  try {
60525
60628
  const connectPath = import_node_path64.default.join(config.dataDir, "connect.txt");
60526
- import_node_fs51.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
60629
+ import_node_fs52.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
60527
60630
  } catch {
60528
60631
  }
60529
60632
  } catch (err) {
@@ -60627,7 +60730,7 @@ ${bar}
60627
60730
  function migrateDropPersonsDir(dataDir) {
60628
60731
  const dir = import_node_path64.default.join(dataDir, "persons");
60629
60732
  try {
60630
- import_node_fs51.default.rmSync(dir, { recursive: true, force: true });
60733
+ import_node_fs52.default.rmSync(dir, { recursive: true, force: true });
60631
60734
  } catch {
60632
60735
  }
60633
60736
  }