@clawos-dev/clawd 0.2.484 → 0.2.486

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
@@ -450,8 +450,8 @@ var init_parseUtil = __esm({
450
450
  init_errors();
451
451
  init_en();
452
452
  makeIssue = (params) => {
453
- const { data, path: path97, errorMaps, issueData } = params;
454
- const fullPath = [...path97, ...issueData.path || []];
453
+ const { data, path: path98, errorMaps, issueData } = params;
454
+ const fullPath = [...path98, ...issueData.path || []];
455
455
  const fullIssue = {
456
456
  ...issueData,
457
457
  path: fullPath
@@ -762,11 +762,11 @@ var init_types = __esm({
762
762
  init_parseUtil();
763
763
  init_util();
764
764
  ParseInputLazyPath = class {
765
- constructor(parent, value, path97, key) {
765
+ constructor(parent, value, path98, key) {
766
766
  this._cachedPath = [];
767
767
  this.parent = parent;
768
768
  this.data = value;
769
- this._path = path97;
769
+ this._path = path98;
770
770
  this._key = key;
771
771
  }
772
772
  get path() {
@@ -6022,6 +6022,11 @@ var init_environment_schemas = __esm({
6022
6022
  });
6023
6023
 
6024
6024
  // ../protocol/src/deploy-schemas.ts
6025
+ function isScanFresh(scan, repo2) {
6026
+ if (!scan || !repo2) return false;
6027
+ if (scan.status !== "done") return false;
6028
+ return scan.head === repo2.head && !repo2.dirty;
6029
+ }
6025
6030
  function repoSlug(url) {
6026
6031
  return url.trim().replace(/^git@[^:]+:/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/\.git$/, "");
6027
6032
  }
@@ -6044,6 +6049,16 @@ var init_deploy_schemas = __esm({
6044
6049
  notes: external_exports.array(external_exports.string()).default([]),
6045
6050
  /** 扫描时被告知的共享资产名单(判「扫描器后来长了新本事」用) */
6046
6051
  scannedAssets: external_exports.array(external_exports.string()).default([]),
6052
+ /**
6053
+ * 这次扫描是**对哪个 commit 的断言**。`deploy:start` 在起扫描之前会先把 persona 目录
6054
+ * 提交并推上去,所以这个值一定是仓库里真实存在的一版。
6055
+ *
6056
+ * 有了它,「清单过没过时」才是个可判定的等式(`head === repo.head`),
6057
+ * 而不是从 `dirty` / `ahead` 里猜——那两个字段判不出「清单是好几版之前扫的」。
6058
+ *
6059
+ * 缺席 = 旧版 clawd 扫的记录。**一律当过时**:没有第三种情况,重扫一次就有了。
6060
+ */
6061
+ head: external_exports.string().min(1).optional(),
6047
6062
  startedAt: external_exports.number(),
6048
6063
  finishedAt: external_exports.number().optional(),
6049
6064
  error: external_exports.string().optional()
@@ -7588,7 +7603,12 @@ var init_schemas = __esm({
7588
7603
  // 缺省 = 该 tool 的 effort 与模型无关(claude 即此情形),消费方回落到 configSchema 里
7589
7604
  // name==='effort' 那条字段的 options。
7590
7605
  efforts: external_exports.array(SelectOptionSchema).optional(),
7591
- defaultEffort: external_exports.string().optional()
7606
+ defaultEffort: external_exports.string().optional(),
7607
+ // 下拉分组标题(codex:模型家族名 GPT / Gemini / Claude…,由 daemon 从 model id 派生)。
7608
+ // 缺省 = 该 tool 的模型不分组(claude 即此情形),消费方平铺渲染、不出标题。
7609
+ // 全表只落在一个家族时 daemon 也不填——一个横跨全表的标题没有信息量。
7610
+ // 消费方假定同 group 的条目已连续排好(排序在 daemon 侧,见 codex-model-list.mergeProviderModels)。
7611
+ group: external_exports.string().optional()
7592
7612
  });
7593
7613
  ModeInfoSchema = external_exports.object({
7594
7614
  id: external_exports.string().min(1),
@@ -9904,8 +9924,8 @@ var require_req = __commonJS({
9904
9924
  if (req.originalUrl) {
9905
9925
  _req.url = req.originalUrl;
9906
9926
  } else {
9907
- const path97 = req.path;
9908
- _req.url = typeof path97 === "string" ? path97 : req.url ? req.url.path || req.url : void 0;
9927
+ const path98 = req.path;
9928
+ _req.url = typeof path98 === "string" ? path98 : req.url ? req.url.path || req.url : void 0;
9909
9929
  }
9910
9930
  if (req.query) {
9911
9931
  _req.query = req.query;
@@ -10070,14 +10090,14 @@ var require_redact = __commonJS({
10070
10090
  }
10071
10091
  return obj;
10072
10092
  }
10073
- function parsePath(path97) {
10093
+ function parsePath(path98) {
10074
10094
  const parts = [];
10075
10095
  let current = "";
10076
10096
  let inBrackets = false;
10077
10097
  let inQuotes = false;
10078
10098
  let quoteChar = "";
10079
- for (let i = 0; i < path97.length; i++) {
10080
- const char = path97[i];
10099
+ for (let i = 0; i < path98.length; i++) {
10100
+ const char = path98[i];
10081
10101
  if (!inBrackets && char === ".") {
10082
10102
  if (current) {
10083
10103
  parts.push(current);
@@ -10208,10 +10228,10 @@ var require_redact = __commonJS({
10208
10228
  return current;
10209
10229
  }
10210
10230
  function redactPaths(obj, paths, censor, remove = false) {
10211
- for (const path97 of paths) {
10212
- const parts = parsePath(path97);
10231
+ for (const path98 of paths) {
10232
+ const parts = parsePath(path98);
10213
10233
  if (parts.includes("*")) {
10214
- redactWildcardPath(obj, parts, censor, path97, remove);
10234
+ redactWildcardPath(obj, parts, censor, path98, remove);
10215
10235
  } else {
10216
10236
  if (remove) {
10217
10237
  removeKey(obj, parts);
@@ -10296,8 +10316,8 @@ var require_redact = __commonJS({
10296
10316
  }
10297
10317
  } else {
10298
10318
  if (afterWildcard.includes("*")) {
10299
- const wrappedCensor = typeof censor === "function" ? (value, path97) => {
10300
- const fullPath = [...pathArray.slice(0, pathLength), ...path97];
10319
+ const wrappedCensor = typeof censor === "function" ? (value, path98) => {
10320
+ const fullPath = [...pathArray.slice(0, pathLength), ...path98];
10301
10321
  return censor(value, fullPath);
10302
10322
  } : censor;
10303
10323
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -10332,8 +10352,8 @@ var require_redact = __commonJS({
10332
10352
  return null;
10333
10353
  }
10334
10354
  const pathStructure = /* @__PURE__ */ new Map();
10335
- for (const path97 of pathsToClone) {
10336
- const parts = parsePath(path97);
10355
+ for (const path98 of pathsToClone) {
10356
+ const parts = parsePath(path98);
10337
10357
  let current = pathStructure;
10338
10358
  for (let i = 0; i < parts.length; i++) {
10339
10359
  const part = parts[i];
@@ -10385,24 +10405,24 @@ var require_redact = __commonJS({
10385
10405
  }
10386
10406
  return cloneSelectively(obj, pathStructure);
10387
10407
  }
10388
- function validatePath(path97) {
10389
- if (typeof path97 !== "string") {
10408
+ function validatePath(path98) {
10409
+ if (typeof path98 !== "string") {
10390
10410
  throw new Error("Paths must be (non-empty) strings");
10391
10411
  }
10392
- if (path97 === "") {
10412
+ if (path98 === "") {
10393
10413
  throw new Error("Invalid redaction path ()");
10394
10414
  }
10395
- if (path97.includes("..")) {
10396
- throw new Error(`Invalid redaction path (${path97})`);
10415
+ if (path98.includes("..")) {
10416
+ throw new Error(`Invalid redaction path (${path98})`);
10397
10417
  }
10398
- if (path97.includes(",")) {
10399
- throw new Error(`Invalid redaction path (${path97})`);
10418
+ if (path98.includes(",")) {
10419
+ throw new Error(`Invalid redaction path (${path98})`);
10400
10420
  }
10401
10421
  let bracketCount = 0;
10402
10422
  let inQuotes = false;
10403
10423
  let quoteChar = "";
10404
- for (let i = 0; i < path97.length; i++) {
10405
- const char = path97[i];
10424
+ for (let i = 0; i < path98.length; i++) {
10425
+ const char = path98[i];
10406
10426
  if ((char === '"' || char === "'") && bracketCount > 0) {
10407
10427
  if (!inQuotes) {
10408
10428
  inQuotes = true;
@@ -10416,20 +10436,20 @@ var require_redact = __commonJS({
10416
10436
  } else if (char === "]" && !inQuotes) {
10417
10437
  bracketCount--;
10418
10438
  if (bracketCount < 0) {
10419
- throw new Error(`Invalid redaction path (${path97})`);
10439
+ throw new Error(`Invalid redaction path (${path98})`);
10420
10440
  }
10421
10441
  }
10422
10442
  }
10423
10443
  if (bracketCount !== 0) {
10424
- throw new Error(`Invalid redaction path (${path97})`);
10444
+ throw new Error(`Invalid redaction path (${path98})`);
10425
10445
  }
10426
10446
  }
10427
10447
  function validatePaths(paths) {
10428
10448
  if (!Array.isArray(paths)) {
10429
10449
  throw new TypeError("paths must be an array");
10430
10450
  }
10431
- for (const path97 of paths) {
10432
- validatePath(path97);
10451
+ for (const path98 of paths) {
10452
+ validatePath(path98);
10433
10453
  }
10434
10454
  }
10435
10455
  function slowRedact(options = {}) {
@@ -10597,8 +10617,8 @@ var require_redaction = __commonJS({
10597
10617
  if (shape[k2] === null) {
10598
10618
  o[k2] = (value) => topCensor(value, [k2]);
10599
10619
  } else {
10600
- const wrappedCensor = typeof censor === "function" ? (value, path97) => {
10601
- return censor(value, [k2, ...path97]);
10620
+ const wrappedCensor = typeof censor === "function" ? (value, path98) => {
10621
+ return censor(value, [k2, ...path98]);
10602
10622
  } : censor;
10603
10623
  o[k2] = Redact({
10604
10624
  paths: shape[k2],
@@ -10816,10 +10836,10 @@ var require_atomic_sleep = __commonJS({
10816
10836
  var require_sonic_boom = __commonJS({
10817
10837
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
10818
10838
  "use strict";
10819
- var fs85 = require("fs");
10839
+ var fs86 = require("fs");
10820
10840
  var EventEmitter3 = require("events");
10821
10841
  var inherits = require("util").inherits;
10822
- var path97 = require("path");
10842
+ var path98 = require("path");
10823
10843
  var sleep2 = require_atomic_sleep();
10824
10844
  var assert = require("assert");
10825
10845
  var BUSY_WRITE_TIMEOUT = 100;
@@ -10873,20 +10893,20 @@ var require_sonic_boom = __commonJS({
10873
10893
  const mode = sonic.mode;
10874
10894
  if (sonic.sync) {
10875
10895
  try {
10876
- if (sonic.mkdir) fs85.mkdirSync(path97.dirname(file), { recursive: true });
10877
- const fd = fs85.openSync(file, flags, mode);
10896
+ if (sonic.mkdir) fs86.mkdirSync(path98.dirname(file), { recursive: true });
10897
+ const fd = fs86.openSync(file, flags, mode);
10878
10898
  fileOpened(null, fd);
10879
10899
  } catch (err) {
10880
10900
  fileOpened(err);
10881
10901
  throw err;
10882
10902
  }
10883
10903
  } else if (sonic.mkdir) {
10884
- fs85.mkdir(path97.dirname(file), { recursive: true }, (err) => {
10904
+ fs86.mkdir(path98.dirname(file), { recursive: true }, (err) => {
10885
10905
  if (err) return fileOpened(err);
10886
- fs85.open(file, flags, mode, fileOpened);
10906
+ fs86.open(file, flags, mode, fileOpened);
10887
10907
  });
10888
10908
  } else {
10889
- fs85.open(file, flags, mode, fileOpened);
10909
+ fs86.open(file, flags, mode, fileOpened);
10890
10910
  }
10891
10911
  }
10892
10912
  function SonicBoom(opts) {
@@ -10927,8 +10947,8 @@ var require_sonic_boom = __commonJS({
10927
10947
  this.flush = flushBuffer;
10928
10948
  this.flushSync = flushBufferSync;
10929
10949
  this._actualWrite = actualWriteBuffer;
10930
- fsWriteSync = () => fs85.writeSync(this.fd, this._writingBuf);
10931
- fsWrite = () => fs85.write(this.fd, this._writingBuf, this.release);
10950
+ fsWriteSync = () => fs86.writeSync(this.fd, this._writingBuf);
10951
+ fsWrite = () => fs86.write(this.fd, this._writingBuf, this.release);
10932
10952
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
10933
10953
  this._writingBuf = "";
10934
10954
  this.write = write;
@@ -10937,15 +10957,15 @@ var require_sonic_boom = __commonJS({
10937
10957
  this._actualWrite = actualWrite;
10938
10958
  fsWriteSync = () => {
10939
10959
  if (Buffer.isBuffer(this._writingBuf)) {
10940
- return fs85.writeSync(this.fd, this._writingBuf);
10960
+ return fs86.writeSync(this.fd, this._writingBuf);
10941
10961
  }
10942
- return fs85.writeSync(this.fd, this._writingBuf, "utf8");
10962
+ return fs86.writeSync(this.fd, this._writingBuf, "utf8");
10943
10963
  };
10944
10964
  fsWrite = () => {
10945
10965
  if (Buffer.isBuffer(this._writingBuf)) {
10946
- return fs85.write(this.fd, this._writingBuf, this.release);
10966
+ return fs86.write(this.fd, this._writingBuf, this.release);
10947
10967
  }
10948
- return fs85.write(this.fd, this._writingBuf, "utf8", this.release);
10968
+ return fs86.write(this.fd, this._writingBuf, "utf8", this.release);
10949
10969
  };
10950
10970
  } else {
10951
10971
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -11002,7 +11022,7 @@ var require_sonic_boom = __commonJS({
11002
11022
  }
11003
11023
  }
11004
11024
  if (this._fsync) {
11005
- fs85.fsyncSync(this.fd);
11025
+ fs86.fsyncSync(this.fd);
11006
11026
  }
11007
11027
  const len = this._len;
11008
11028
  if (this._reopening) {
@@ -11116,7 +11136,7 @@ var require_sonic_boom = __commonJS({
11116
11136
  const onDrain = () => {
11117
11137
  if (!this._fsync) {
11118
11138
  try {
11119
- fs85.fsync(this.fd, (err) => {
11139
+ fs86.fsync(this.fd, (err) => {
11120
11140
  this._flushPending = false;
11121
11141
  cb(err);
11122
11142
  });
@@ -11218,7 +11238,7 @@ var require_sonic_boom = __commonJS({
11218
11238
  const fd = this.fd;
11219
11239
  this.once("ready", () => {
11220
11240
  if (fd !== this.fd) {
11221
- fs85.close(fd, (err) => {
11241
+ fs86.close(fd, (err) => {
11222
11242
  if (err) {
11223
11243
  return this.emit("error", err);
11224
11244
  }
@@ -11267,7 +11287,7 @@ var require_sonic_boom = __commonJS({
11267
11287
  buf = this._bufs[0];
11268
11288
  }
11269
11289
  try {
11270
- const n = Buffer.isBuffer(buf) ? fs85.writeSync(this.fd, buf) : fs85.writeSync(this.fd, buf, "utf8");
11290
+ const n = Buffer.isBuffer(buf) ? fs86.writeSync(this.fd, buf) : fs86.writeSync(this.fd, buf, "utf8");
11271
11291
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
11272
11292
  buf = releasedBufObj.writingBuf;
11273
11293
  this._len = releasedBufObj.len;
@@ -11283,7 +11303,7 @@ var require_sonic_boom = __commonJS({
11283
11303
  }
11284
11304
  }
11285
11305
  try {
11286
- fs85.fsyncSync(this.fd);
11306
+ fs86.fsyncSync(this.fd);
11287
11307
  } catch {
11288
11308
  }
11289
11309
  }
@@ -11304,7 +11324,7 @@ var require_sonic_boom = __commonJS({
11304
11324
  buf = mergeBuf(this._bufs[0], this._lens[0]);
11305
11325
  }
11306
11326
  try {
11307
- const n = fs85.writeSync(this.fd, buf);
11327
+ const n = fs86.writeSync(this.fd, buf);
11308
11328
  buf = buf.subarray(n);
11309
11329
  this._len = Math.max(this._len - n, 0);
11310
11330
  if (buf.length <= 0) {
@@ -11332,13 +11352,13 @@ var require_sonic_boom = __commonJS({
11332
11352
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
11333
11353
  if (this.sync) {
11334
11354
  try {
11335
- const written = Buffer.isBuffer(this._writingBuf) ? fs85.writeSync(this.fd, this._writingBuf) : fs85.writeSync(this.fd, this._writingBuf, "utf8");
11355
+ const written = Buffer.isBuffer(this._writingBuf) ? fs86.writeSync(this.fd, this._writingBuf) : fs86.writeSync(this.fd, this._writingBuf, "utf8");
11336
11356
  release2(null, written);
11337
11357
  } catch (err) {
11338
11358
  release2(err);
11339
11359
  }
11340
11360
  } else {
11341
- fs85.write(this.fd, this._writingBuf, release2);
11361
+ fs86.write(this.fd, this._writingBuf, release2);
11342
11362
  }
11343
11363
  }
11344
11364
  function actualWriteBuffer() {
@@ -11347,7 +11367,7 @@ var require_sonic_boom = __commonJS({
11347
11367
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
11348
11368
  if (this.sync) {
11349
11369
  try {
11350
- const written = fs85.writeSync(this.fd, this._writingBuf);
11370
+ const written = fs86.writeSync(this.fd, this._writingBuf);
11351
11371
  release2(null, written);
11352
11372
  } catch (err) {
11353
11373
  release2(err);
@@ -11356,7 +11376,7 @@ var require_sonic_boom = __commonJS({
11356
11376
  if (kCopyBuffer) {
11357
11377
  this._writingBuf = Buffer.from(this._writingBuf);
11358
11378
  }
11359
- fs85.write(this.fd, this._writingBuf, release2);
11379
+ fs86.write(this.fd, this._writingBuf, release2);
11360
11380
  }
11361
11381
  }
11362
11382
  function actualClose(sonic) {
@@ -11372,12 +11392,12 @@ var require_sonic_boom = __commonJS({
11372
11392
  sonic._lens = [];
11373
11393
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
11374
11394
  try {
11375
- fs85.fsync(sonic.fd, closeWrapped);
11395
+ fs86.fsync(sonic.fd, closeWrapped);
11376
11396
  } catch {
11377
11397
  }
11378
11398
  function closeWrapped() {
11379
11399
  if (sonic.fd !== 1 && sonic.fd !== 2) {
11380
- fs85.close(sonic.fd, done);
11400
+ fs86.close(sonic.fd, done);
11381
11401
  } else {
11382
11402
  done();
11383
11403
  }
@@ -13741,7 +13761,7 @@ var require_multistream = __commonJS({
13741
13761
  var require_pino = __commonJS({
13742
13762
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
13743
13763
  "use strict";
13744
- var os31 = require("os");
13764
+ var os32 = require("os");
13745
13765
  var stdSerializers = require_pino_std_serializers();
13746
13766
  var caller = require_caller();
13747
13767
  var redaction = require_redaction();
@@ -13788,7 +13808,7 @@ var require_pino = __commonJS({
13788
13808
  } = symbols;
13789
13809
  var { epochTime, nullTime } = time;
13790
13810
  var { pid } = process;
13791
- var hostname = os31.hostname();
13811
+ var hostname = os32.hostname();
13792
13812
  var defaultErrorSerializer = stdSerializers.err;
13793
13813
  var defaultOptions2 = {
13794
13814
  level: "info",
@@ -14512,11 +14532,11 @@ var init_lib = __esm({
14512
14532
  }
14513
14533
  }
14514
14534
  },
14515
- addToPath: function addToPath(path97, added, removed, oldPosInc, options) {
14516
- var last = path97.lastComponent;
14535
+ addToPath: function addToPath(path98, added, removed, oldPosInc, options) {
14536
+ var last = path98.lastComponent;
14517
14537
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
14518
14538
  return {
14519
- oldPos: path97.oldPos + oldPosInc,
14539
+ oldPos: path98.oldPos + oldPosInc,
14520
14540
  lastComponent: {
14521
14541
  count: last.count + 1,
14522
14542
  added,
@@ -14526,7 +14546,7 @@ var init_lib = __esm({
14526
14546
  };
14527
14547
  } else {
14528
14548
  return {
14529
- oldPos: path97.oldPos + oldPosInc,
14549
+ oldPos: path98.oldPos + oldPosInc,
14530
14550
  lastComponent: {
14531
14551
  count: 1,
14532
14552
  added,
@@ -15108,10 +15128,10 @@ function attachmentToHistoryMessage(o, ts) {
15108
15128
  const memories = raw.map((m2) => {
15109
15129
  if (!m2 || typeof m2 !== "object") return null;
15110
15130
  const rec4 = m2;
15111
- const path97 = typeof rec4.path === "string" ? rec4.path : null;
15131
+ const path98 = typeof rec4.path === "string" ? rec4.path : null;
15112
15132
  const content = typeof rec4.content === "string" ? rec4.content : null;
15113
- if (!path97 || content == null) return null;
15114
- const entry = { path: path97, content };
15133
+ if (!path98 || content == null) return null;
15134
+ const entry = { path: path98, content };
15115
15135
  if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
15116
15136
  return entry;
15117
15137
  }).filter((m2) => m2 !== null);
@@ -15977,10 +15997,10 @@ function parseAttachment(obj) {
15977
15997
  const memories = raw.map((m2) => {
15978
15998
  if (!m2 || typeof m2 !== "object") return null;
15979
15999
  const rec4 = m2;
15980
- const path97 = typeof rec4.path === "string" ? rec4.path : null;
16000
+ const path98 = typeof rec4.path === "string" ? rec4.path : null;
15981
16001
  const content = typeof rec4.content === "string" ? rec4.content : null;
15982
- if (!path97 || content == null) return null;
15983
- const out = { path: path97, content };
16002
+ if (!path98 || content == null) return null;
16003
+ const out = { path: path98, content };
15984
16004
  if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
15985
16005
  return out;
15986
16006
  }).filter((m2) => m2 !== null);
@@ -36954,8 +36974,8 @@ var require_utils = __commonJS({
36954
36974
  var result = transform[inputType][outputType](input);
36955
36975
  return result;
36956
36976
  };
36957
- exports2.resolve = function(path97) {
36958
- var parts = path97.split("/");
36977
+ exports2.resolve = function(path98) {
36978
+ var parts = path98.split("/");
36959
36979
  var result = [];
36960
36980
  for (var index = 0; index < parts.length; index++) {
36961
36981
  var part = parts[index];
@@ -42808,18 +42828,18 @@ var require_object = __commonJS({
42808
42828
  var object = new ZipObject(name, zipObjectContent, o);
42809
42829
  this.files[name] = object;
42810
42830
  };
42811
- var parentFolder = function(path97) {
42812
- if (path97.slice(-1) === "/") {
42813
- path97 = path97.substring(0, path97.length - 1);
42831
+ var parentFolder = function(path98) {
42832
+ if (path98.slice(-1) === "/") {
42833
+ path98 = path98.substring(0, path98.length - 1);
42814
42834
  }
42815
- var lastSlash = path97.lastIndexOf("/");
42816
- return lastSlash > 0 ? path97.substring(0, lastSlash) : "";
42835
+ var lastSlash = path98.lastIndexOf("/");
42836
+ return lastSlash > 0 ? path98.substring(0, lastSlash) : "";
42817
42837
  };
42818
- var forceTrailingSlash = function(path97) {
42819
- if (path97.slice(-1) !== "/") {
42820
- path97 += "/";
42838
+ var forceTrailingSlash = function(path98) {
42839
+ if (path98.slice(-1) !== "/") {
42840
+ path98 += "/";
42821
42841
  }
42822
- return path97;
42842
+ return path98;
42823
42843
  };
42824
42844
  var folderAdd = function(name, createFolders) {
42825
42845
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -43821,7 +43841,7 @@ var require_lib3 = __commonJS({
43821
43841
  // src/run-case/recorder.ts
43822
43842
  function startRunCaseRecorder(opts) {
43823
43843
  const now = opts.now ?? Date.now;
43824
- const dir = import_node_path79.default.dirname(opts.recordPath);
43844
+ const dir = import_node_path80.default.dirname(opts.recordPath);
43825
43845
  let stream = null;
43826
43846
  let closing = false;
43827
43847
  let closedSettled = false;
@@ -43835,8 +43855,8 @@ function startRunCaseRecorder(opts) {
43835
43855
  });
43836
43856
  const ensureStream = () => {
43837
43857
  if (stream) return stream;
43838
- import_node_fs57.default.mkdirSync(dir, { recursive: true });
43839
- stream = import_node_fs57.default.createWriteStream(opts.recordPath, { flags: "a" });
43858
+ import_node_fs58.default.mkdirSync(dir, { recursive: true });
43859
+ stream = import_node_fs58.default.createWriteStream(opts.recordPath, { flags: "a" });
43840
43860
  stream.on("close", () => closedResolve());
43841
43861
  return stream;
43842
43862
  };
@@ -43861,12 +43881,12 @@ function startRunCaseRecorder(opts) {
43861
43881
  };
43862
43882
  return { tap, close, closed };
43863
43883
  }
43864
- var import_node_fs57, import_node_path79;
43884
+ var import_node_fs58, import_node_path80;
43865
43885
  var init_recorder = __esm({
43866
43886
  "src/run-case/recorder.ts"() {
43867
43887
  "use strict";
43868
- import_node_fs57 = __toESM(require("fs"), 1);
43869
- import_node_path79 = __toESM(require("path"), 1);
43888
+ import_node_fs58 = __toESM(require("fs"), 1);
43889
+ import_node_path80 = __toESM(require("path"), 1);
43870
43890
  }
43871
43891
  });
43872
43892
 
@@ -43909,7 +43929,7 @@ var init_wire = __esm({
43909
43929
  // src/run-case/controller.ts
43910
43930
  async function runController(opts) {
43911
43931
  const now = opts.now ?? Date.now;
43912
- const cwd = opts.cwd ?? (0, import_node_fs58.mkdtempSync)(import_node_path80.default.join(import_node_os27.default.tmpdir(), "clawd-runcase-"));
43932
+ const cwd = opts.cwd ?? (0, import_node_fs59.mkdtempSync)(import_node_path81.default.join(import_node_os28.default.tmpdir(), "clawd-runcase-"));
43913
43933
  const ownsCwd = opts.cwd === void 0;
43914
43934
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
43915
43935
  const spawnCtx = { cwd };
@@ -44070,19 +44090,19 @@ async function runController(opts) {
44070
44090
  if (sigintHandler) process.off("SIGINT", sigintHandler);
44071
44091
  if (ownsCwd) {
44072
44092
  try {
44073
- (0, import_node_fs58.rmSync)(cwd, { recursive: true, force: true });
44093
+ (0, import_node_fs59.rmSync)(cwd, { recursive: true, force: true });
44074
44094
  } catch {
44075
44095
  }
44076
44096
  }
44077
44097
  return exitCode ?? 0;
44078
44098
  }
44079
- var import_node_fs58, import_node_os27, import_node_path80;
44099
+ var import_node_fs59, import_node_os28, import_node_path81;
44080
44100
  var init_controller = __esm({
44081
44101
  "src/run-case/controller.ts"() {
44082
44102
  "use strict";
44083
- import_node_fs58 = require("fs");
44084
- import_node_os27 = __toESM(require("os"), 1);
44085
- import_node_path80 = __toESM(require("path"), 1);
44103
+ import_node_fs59 = require("fs");
44104
+ import_node_os28 = __toESM(require("os"), 1);
44105
+ import_node_path81 = __toESM(require("path"), 1);
44086
44106
  init_claude();
44087
44107
  init_stdout_splitter();
44088
44108
  init_permission_stdio();
@@ -44357,9 +44377,9 @@ Env (advanced):
44357
44377
  `;
44358
44378
 
44359
44379
  // src/index.ts
44360
- var import_node_path78 = __toESM(require("path"), 1);
44361
- var import_node_fs56 = __toESM(require("fs"), 1);
44362
- var import_node_os26 = __toESM(require("os"), 1);
44380
+ var import_node_path79 = __toESM(require("path"), 1);
44381
+ var import_node_fs57 = __toESM(require("fs"), 1);
44382
+ var import_node_os27 = __toESM(require("os"), 1);
44363
44383
  var import_node_crypto22 = require("crypto");
44364
44384
  var import_node_url5 = require("url");
44365
44385
 
@@ -51142,7 +51162,7 @@ init_claude();
51142
51162
 
51143
51163
  // src/tools/codex.ts
51144
51164
  var import_node_child_process6 = require("child_process");
51145
- var import_node_fs19 = __toESM(require("fs"), 1);
51165
+ var import_node_fs20 = __toESM(require("fs"), 1);
51146
51166
 
51147
51167
  // src/tools/codex-session.ts
51148
51168
  var import_node_child_process4 = require("child_process");
@@ -51615,8 +51635,8 @@ function turnStartInput(text) {
51615
51635
  const items = [];
51616
51636
  let leftover = text;
51617
51637
  for (const m2 of text.matchAll(SKILL_RE)) {
51618
- const [marker, name, path97] = m2;
51619
- items.push({ type: "skill", name, path: path97 });
51638
+ const [marker, name, path98] = m2;
51639
+ items.push({ type: "skill", name, path: path98 });
51620
51640
  leftover = leftover.replace(marker, "");
51621
51641
  }
51622
51642
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -52005,6 +52025,105 @@ function mapModelList(raw) {
52005
52025
  }
52006
52026
  return models;
52007
52027
  }
52028
+ function modelFamily(id) {
52029
+ const head = (id.split("-")[0] || id).toLowerCase();
52030
+ if (head === "gpt") return "GPT";
52031
+ return head.charAt(0).toUpperCase() + head.slice(1);
52032
+ }
52033
+ function familyRank(family) {
52034
+ return family === "GPT" ? 0 : 1;
52035
+ }
52036
+ function mergeProviderModels(native, provider) {
52037
+ const nativeOrder = new Map(native.map((m2, i) => [m2.id, i]));
52038
+ const extras = provider.filter((p2) => !nativeOrder.has(p2.id)).map((p2) => ({ id: p2.id, label: p2.id, contextWindowSize: CODEX_CONTEXT_WINDOW }));
52039
+ const sorted = [...native, ...extras].sort((a, b2) => {
52040
+ const fa = modelFamily(a.id);
52041
+ const fb = modelFamily(b2.id);
52042
+ if (fa !== fb) return familyRank(fa) - familyRank(fb) || fa.localeCompare(fb);
52043
+ const ia = nativeOrder.get(a.id);
52044
+ const ib = nativeOrder.get(b2.id);
52045
+ if (ia !== void 0 && ib !== void 0) return ia - ib;
52046
+ if (ia !== void 0) return -1;
52047
+ if (ib !== void 0) return 1;
52048
+ return a.id.localeCompare(b2.id);
52049
+ });
52050
+ if (new Set(sorted.map((m2) => modelFamily(m2.id))).size <= 1) return sorted;
52051
+ return sorted.map((m2) => ({ ...m2, group: modelFamily(m2.id) }));
52052
+ }
52053
+
52054
+ // src/tools/codex-provider-models.ts
52055
+ var import_node_fs19 = __toESM(require("fs"), 1);
52056
+ var import_node_os7 = __toESM(require("os"), 1);
52057
+ var import_node_path18 = __toESM(require("path"), 1);
52058
+ var PROVIDER_FETCH_TIMEOUT_MS = 3e3;
52059
+ function asRecord(v2) {
52060
+ return v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : null;
52061
+ }
52062
+ function readAuthKey(codexHome) {
52063
+ try {
52064
+ const raw = JSON.parse(import_node_fs19.default.readFileSync(import_node_path18.default.join(codexHome, "auth.json"), "utf8"));
52065
+ const key = asRecord(raw)?.OPENAI_API_KEY;
52066
+ return typeof key === "string" && key ? key : void 0;
52067
+ } catch {
52068
+ return void 0;
52069
+ }
52070
+ }
52071
+ function resolveProviderEndpoint(rawConfig, deps = {}) {
52072
+ const config = asRecord(asRecord(rawConfig)?.config);
52073
+ if (!config) return null;
52074
+ const name = config.model_provider;
52075
+ if (typeof name !== "string" || !name) return null;
52076
+ const entry = asRecord(asRecord(config.model_providers)?.[name]);
52077
+ if (!entry) return null;
52078
+ const baseUrl = entry.base_url;
52079
+ if (typeof baseUrl !== "string" || !baseUrl) return null;
52080
+ const env = deps.env ?? process.env;
52081
+ const codexHome = deps.codexHome ?? env.CODEX_HOME ?? import_node_path18.default.join(import_node_os7.default.homedir(), ".codex");
52082
+ const envKey = typeof entry.env_key === "string" && entry.env_key ? entry.env_key : null;
52083
+ const token = envKey ? env[envKey] : readAuthKey(codexHome);
52084
+ if (!token) {
52085
+ deps.logger?.warn?.(
52086
+ envKey ? `provider "${name}": env_key ${envKey} is not set in the daemon process, sending unauthenticated` : `provider "${name}": no OPENAI_API_KEY in ${codexHome}/auth.json, sending unauthenticated`
52087
+ );
52088
+ }
52089
+ return {
52090
+ baseUrl,
52091
+ headers: {
52092
+ Accept: "application/json",
52093
+ ...token ? { Authorization: `Bearer ${token}` } : {}
52094
+ }
52095
+ };
52096
+ }
52097
+ async function fetchProviderModels(endpoint, deps = {}) {
52098
+ const fetchImpl = deps.fetchImpl ?? fetch;
52099
+ const controller = new AbortController();
52100
+ const timer = setTimeout(() => controller.abort(), deps.timeoutMs ?? PROVIDER_FETCH_TIMEOUT_MS);
52101
+ const url = `${endpoint.baseUrl.replace(/\/$/, "")}/models`;
52102
+ try {
52103
+ const res = await fetchImpl(url, { headers: endpoint.headers, signal: controller.signal });
52104
+ if (!res.ok) {
52105
+ deps.logger?.warn?.(`provider model list failed: HTTP ${res.status} from ${url}`);
52106
+ return [];
52107
+ }
52108
+ const data = asRecord(await res.json())?.data;
52109
+ if (!Array.isArray(data)) {
52110
+ deps.logger?.warn?.(`provider model list: \`data\` is not an array (${url})`);
52111
+ return [];
52112
+ }
52113
+ const out = [];
52114
+ for (const item of data) {
52115
+ const e = asRecord(item);
52116
+ if (!e || typeof e.id !== "string" || !e.id) continue;
52117
+ out.push({ id: e.id, ...typeof e.owned_by === "string" ? { ownedBy: e.owned_by } : {} });
52118
+ }
52119
+ return out;
52120
+ } catch (err) {
52121
+ deps.logger?.warn?.(`provider model list failed: ${err.message}`);
52122
+ return [];
52123
+ } finally {
52124
+ clearTimeout(timer);
52125
+ }
52126
+ }
52008
52127
 
52009
52128
  // src/tools/codex.ts
52010
52129
  init_claude();
@@ -52069,14 +52188,13 @@ function buildCapabilities(models) {
52069
52188
  function sanitizeCodexModel(model) {
52070
52189
  if (model === void 0) return void 0;
52071
52190
  if (CLAUDE_MODEL_IDS.includes(model)) return void 0;
52072
- if (model.startsWith("claude-")) return void 0;
52073
52191
  return model;
52074
52192
  }
52075
52193
  async function probeCodex(env = process.env) {
52076
- if (env.CODEX_BIN && import_node_fs19.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
52194
+ if (env.CODEX_BIN && import_node_fs20.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
52077
52195
  try {
52078
52196
  const out = (0, import_node_child_process6.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
52079
- if (out && import_node_fs19.default.existsSync(out)) return { available: true, path: out };
52197
+ if (out && import_node_fs20.default.existsSync(out)) return { available: true, path: out };
52080
52198
  } catch {
52081
52199
  }
52082
52200
  return { available: false };
@@ -52089,6 +52207,8 @@ var CodexAdapter = class {
52089
52207
  logger;
52090
52208
  probeOverride;
52091
52209
  queryOverride;
52210
+ configQueryOverride;
52211
+ fetchImpl;
52092
52212
  /** CODEX_HOME 归属解析(spec 2026-08-18-codex-project-alignment §3.1),由 index.ts 注入 */
52093
52213
  codexHomeFor;
52094
52214
  // capabilities 的进程级 memo。**回落结果同样被缓存**——否则 codex 没装时每次开弹窗都
@@ -52100,6 +52220,8 @@ var CodexAdapter = class {
52100
52220
  this.probeOverride = opts.probeOverride;
52101
52221
  this.historyReader = opts.historyReader;
52102
52222
  this.queryOverride = opts.queryOverride;
52223
+ this.configQueryOverride = opts.configQueryOverride;
52224
+ this.fetchImpl = opts.fetchImpl;
52103
52225
  this.codexHomeFor = opts.codexHomeFor;
52104
52226
  }
52105
52227
  async probe() {
@@ -52112,14 +52234,46 @@ var CodexAdapter = class {
52112
52234
  return this.capsPromise;
52113
52235
  }
52114
52236
  async loadCapabilities() {
52237
+ const [native, providerModels] = await Promise.all([
52238
+ this.loadNativeModels(),
52239
+ this.loadProviderModels()
52240
+ ]);
52241
+ if (native.length === 0 && providerModels.length === 0) {
52242
+ return buildCapabilities([CODEX_DEFAULT_MODEL_ENTRY]);
52243
+ }
52244
+ const base = native.length > 0 ? [] : [CODEX_DEFAULT_MODEL_ENTRY];
52245
+ return buildCapabilities([...base, ...mergeProviderModels(native, providerModels)]);
52246
+ }
52247
+ /** codex 内置型号表。失败返回 [],由 loadCapabilities 决定怎么降级 */
52248
+ async loadNativeModels() {
52115
52249
  try {
52116
52250
  const raw = this.queryOverride ? await this.queryOverride() : await queryCodexAppServer(process.cwd(), "model/list", {});
52117
- return buildCapabilities(mapModelList(raw));
52251
+ return mapModelList(raw);
52118
52252
  } catch (err) {
52119
- this.logger?.warn?.(
52120
- `codex model/list failed, falling back to config.toml default only: ${err.message}`
52121
- );
52122
- return buildCapabilities([CODEX_DEFAULT_MODEL_ENTRY]);
52253
+ this.logger?.warn?.(`codex model/list failed: ${err.message}`);
52254
+ return [];
52255
+ }
52256
+ }
52257
+ /**
52258
+ * provider 订阅侧全集。未配自定义 provider(官方用户)或任何失败都返回 []。
52259
+ * 见 codex-provider-models.ts —— model/list 只报 codex 内置型号,代理转发的模型全靠这里。
52260
+ */
52261
+ async loadProviderModels() {
52262
+ try {
52263
+ const raw = this.configQueryOverride ? await this.configQueryOverride() : await queryCodexAppServer(process.cwd(), "config/read", {}, {
52264
+ timeoutMs: PROVIDER_FETCH_TIMEOUT_MS
52265
+ });
52266
+ const endpoint = resolveProviderEndpoint(raw, {
52267
+ ...this.logger ? { logger: this.logger } : {}
52268
+ });
52269
+ if (!endpoint) return [];
52270
+ return await fetchProviderModels(endpoint, {
52271
+ ...this.fetchImpl ? { fetchImpl: this.fetchImpl } : {},
52272
+ ...this.logger ? { logger: this.logger } : {}
52273
+ });
52274
+ } catch (err) {
52275
+ this.logger?.warn?.(`codex provider model list failed: ${err.message}`);
52276
+ return [];
52123
52277
  }
52124
52278
  }
52125
52279
  // 纯函数、无 IO。所有 codex 模型共用同一静态窗口值(model/list 不给 contextWindow),
@@ -52149,9 +52303,9 @@ var CodexAdapter = class {
52149
52303
 
52150
52304
  // src/tools/claude-tui.ts
52151
52305
  var import_node_crypto5 = require("crypto");
52152
- var import_node_fs20 = __toESM(require("fs"), 1);
52153
- var import_node_os7 = __toESM(require("os"), 1);
52154
- var import_node_path18 = __toESM(require("path"), 1);
52306
+ var import_node_fs21 = __toESM(require("fs"), 1);
52307
+ var import_node_os8 = __toESM(require("os"), 1);
52308
+ var import_node_path19 = __toESM(require("path"), 1);
52155
52309
  var import_headless = __toESM(require_xterm_headless(), 1);
52156
52310
 
52157
52311
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -53376,10 +53530,10 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
53376
53530
  }
53377
53531
  function jsonlExistsForCtx(ctx) {
53378
53532
  if (!ctx.toolSessionId) return false;
53379
- const home = import_node_os7.default.homedir();
53380
- const file = import_node_path18.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
53533
+ const home = import_node_os8.default.homedir();
53534
+ const file = import_node_path19.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
53381
53535
  try {
53382
- return import_node_fs20.default.statSync(file).isFile();
53536
+ return import_node_fs21.default.statSync(file).isFile();
53383
53537
  } catch {
53384
53538
  return false;
53385
53539
  }
@@ -53463,7 +53617,7 @@ var PersonaDispatchManager = class {
53463
53617
 
53464
53618
  // src/dispatch/store.ts
53465
53619
  var import_promises = __toESM(require("fs/promises"), 1);
53466
- var import_node_path19 = __toESM(require("path"), 1);
53620
+ var import_node_path20 = __toESM(require("path"), 1);
53467
53621
 
53468
53622
  // src/shift/constants.ts
53469
53623
  var MAX_RUNS_PER_SHIFT = 30;
@@ -53501,7 +53655,7 @@ function createDispatchStore(deps) {
53501
53655
  flushTimer = null;
53502
53656
  }
53503
53657
  const content = { version: 1, records };
53504
- await import_promises.default.mkdir(import_node_path19.default.dirname(deps.filePath), { recursive: true });
53658
+ await import_promises.default.mkdir(import_node_path20.default.dirname(deps.filePath), { recursive: true });
53505
53659
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
53506
53660
  await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
53507
53661
  await import_promises.default.rename(tmp, deps.filePath);
@@ -53567,7 +53721,7 @@ function createDispatchStore(deps) {
53567
53721
 
53568
53722
  // src/channel/json-store.ts
53569
53723
  var import_promises2 = __toESM(require("fs/promises"), 1);
53570
- var import_node_path20 = __toESM(require("path"), 1);
53724
+ var import_node_path21 = __toESM(require("path"), 1);
53571
53725
  function createJsonStore(deps) {
53572
53726
  let items = [];
53573
53727
  let flushTimer = null;
@@ -53578,7 +53732,7 @@ function createJsonStore(deps) {
53578
53732
  flushTimer = null;
53579
53733
  }
53580
53734
  const content = { version: version2, [deps.key]: items };
53581
- await import_promises2.default.mkdir(import_node_path20.default.dirname(deps.filePath), { recursive: true });
53735
+ await import_promises2.default.mkdir(import_node_path21.default.dirname(deps.filePath), { recursive: true });
53582
53736
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
53583
53737
  await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
53584
53738
  await import_promises2.default.rename(tmp, deps.filePath);
@@ -53870,10 +54024,10 @@ function createTopicStore(deps) {
53870
54024
  }
53871
54025
 
53872
54026
  // src/dispatch/mcp-config.ts
53873
- var import_node_fs21 = __toESM(require("fs"), 1);
53874
- var import_node_path21 = __toESM(require("path"), 1);
54027
+ var import_node_fs22 = __toESM(require("fs"), 1);
54028
+ var import_node_path22 = __toESM(require("path"), 1);
53875
54029
  function dispatchMcpConfigPath(dataDir) {
53876
- return import_node_path21.default.join(dataDir, "dispatch.mcp.json");
54030
+ return import_node_path22.default.join(dataDir, "dispatch.mcp.json");
53877
54031
  }
53878
54032
  function writeDispatchMcpConfig(args) {
53879
54033
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -53892,16 +54046,16 @@ function writeDispatchMcpConfig(args) {
53892
54046
  }
53893
54047
  }
53894
54048
  };
53895
- import_node_fs21.default.mkdirSync(args.dataDir, { recursive: true });
53896
- import_node_fs21.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
54049
+ import_node_fs22.default.mkdirSync(args.dataDir, { recursive: true });
54050
+ import_node_fs22.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
53897
54051
  return cfgPath;
53898
54052
  }
53899
54053
 
53900
54054
  // src/ticket/mcp-config.ts
53901
- var import_node_fs22 = __toESM(require("fs"), 1);
53902
- var import_node_path22 = __toESM(require("path"), 1);
54055
+ var import_node_fs23 = __toESM(require("fs"), 1);
54056
+ var import_node_path23 = __toESM(require("path"), 1);
53903
54057
  function ticketMcpConfigPath(dataDir) {
53904
- return import_node_path22.default.join(dataDir, "ticket.mcp.json");
54058
+ return import_node_path23.default.join(dataDir, "ticket.mcp.json");
53905
54059
  }
53906
54060
  function writeTicketMcpConfig(args) {
53907
54061
  const cfgPath = ticketMcpConfigPath(args.dataDir);
@@ -53923,16 +54077,16 @@ function writeTicketMcpConfig(args) {
53923
54077
  }
53924
54078
  }
53925
54079
  };
53926
- import_node_fs22.default.mkdirSync(args.dataDir, { recursive: true });
53927
- import_node_fs22.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
54080
+ import_node_fs23.default.mkdirSync(args.dataDir, { recursive: true });
54081
+ import_node_fs23.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
53928
54082
  return cfgPath;
53929
54083
  }
53930
54084
 
53931
54085
  // src/shift/mcp-config.ts
53932
- var import_node_fs23 = __toESM(require("fs"), 1);
53933
- var import_node_path23 = __toESM(require("path"), 1);
54086
+ var import_node_fs24 = __toESM(require("fs"), 1);
54087
+ var import_node_path24 = __toESM(require("path"), 1);
53934
54088
  function shiftMcpConfigPath(dataDir) {
53935
- return import_node_path23.default.join(dataDir, "shift.mcp.json");
54089
+ return import_node_path24.default.join(dataDir, "shift.mcp.json");
53936
54090
  }
53937
54091
  async function writeShiftMcpConfig(args) {
53938
54092
  const cfgPath = shiftMcpConfigPath(args.dataDir);
@@ -53951,16 +54105,16 @@ async function writeShiftMcpConfig(args) {
53951
54105
  }
53952
54106
  }
53953
54107
  };
53954
- await import_node_fs23.default.promises.mkdir(args.dataDir, { recursive: true });
53955
- await import_node_fs23.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
54108
+ await import_node_fs24.default.promises.mkdir(args.dataDir, { recursive: true });
54109
+ await import_node_fs24.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
53956
54110
  return cfgPath;
53957
54111
  }
53958
54112
 
53959
54113
  // src/inbox/mcp-config.ts
53960
- var import_node_fs24 = __toESM(require("fs"), 1);
53961
- var import_node_path24 = __toESM(require("path"), 1);
54114
+ var import_node_fs25 = __toESM(require("fs"), 1);
54115
+ var import_node_path25 = __toESM(require("path"), 1);
53962
54116
  function inboxMcpConfigPath(dataDir) {
53963
- return import_node_path24.default.join(dataDir, "inbox.mcp.json");
54117
+ return import_node_path25.default.join(dataDir, "inbox.mcp.json");
53964
54118
  }
53965
54119
  async function writeInboxMcpConfig(args) {
53966
54120
  const cfgPath = inboxMcpConfigPath(args.dataDir);
@@ -53979,16 +54133,16 @@ async function writeInboxMcpConfig(args) {
53979
54133
  }
53980
54134
  }
53981
54135
  };
53982
- await import_node_fs24.default.promises.mkdir(args.dataDir, { recursive: true });
53983
- await import_node_fs24.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
54136
+ await import_node_fs25.default.promises.mkdir(args.dataDir, { recursive: true });
54137
+ await import_node_fs25.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
53984
54138
  return cfgPath;
53985
54139
  }
53986
54140
 
53987
54141
  // src/peer-ops/mcp-config.ts
53988
- var import_node_fs25 = __toESM(require("fs"), 1);
53989
- var import_node_path25 = __toESM(require("path"), 1);
54142
+ var import_node_fs26 = __toESM(require("fs"), 1);
54143
+ var import_node_path26 = __toESM(require("path"), 1);
53990
54144
  function peerOpsMcpConfigPath(dataDir) {
53991
- return import_node_path25.default.join(dataDir, "peer-ops.mcp.json");
54145
+ return import_node_path26.default.join(dataDir, "peer-ops.mcp.json");
53992
54146
  }
53993
54147
  function writePeerOpsMcpConfig(args) {
53994
54148
  const cfgPath = peerOpsMcpConfigPath(args.dataDir);
@@ -54005,16 +54159,16 @@ function writePeerOpsMcpConfig(args) {
54005
54159
  }
54006
54160
  }
54007
54161
  };
54008
- import_node_fs25.default.mkdirSync(args.dataDir, { recursive: true });
54009
- import_node_fs25.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
54162
+ import_node_fs26.default.mkdirSync(args.dataDir, { recursive: true });
54163
+ import_node_fs26.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
54010
54164
  return cfgPath;
54011
54165
  }
54012
54166
 
54013
54167
  // src/rpc-tool/mcp-config.ts
54014
- var import_node_fs26 = __toESM(require("fs"), 1);
54015
- var import_node_path26 = __toESM(require("path"), 1);
54168
+ var import_node_fs27 = __toESM(require("fs"), 1);
54169
+ var import_node_path27 = __toESM(require("path"), 1);
54016
54170
  function rpcToolMcpConfigPath(dataDir) {
54017
- return import_node_path26.default.join(dataDir, "rpc-tool.mcp.json");
54171
+ return import_node_path27.default.join(dataDir, "rpc-tool.mcp.json");
54018
54172
  }
54019
54173
  function writeRpcToolMcpConfig(args) {
54020
54174
  const cfgPath = rpcToolMcpConfigPath(args.dataDir);
@@ -54033,29 +54187,29 @@ function writeRpcToolMcpConfig(args) {
54033
54187
  }
54034
54188
  }
54035
54189
  };
54036
- import_node_fs26.default.mkdirSync(args.dataDir, { recursive: true });
54037
- import_node_fs26.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
54190
+ import_node_fs27.default.mkdirSync(args.dataDir, { recursive: true });
54191
+ import_node_fs27.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
54038
54192
  return cfgPath;
54039
54193
  }
54040
54194
 
54041
54195
  // src/deploy/secret-table.ts
54042
- var import_node_fs27 = __toESM(require("fs"), 1);
54043
- var import_node_path27 = __toESM(require("path"), 1);
54196
+ var import_node_fs28 = __toESM(require("fs"), 1);
54197
+ var import_node_path28 = __toESM(require("path"), 1);
54044
54198
  var import_node_url4 = require("url");
54045
54199
  var import_meta4 = {};
54046
54200
  var LOCAL_SECRETS_DIRNAME = "secrets";
54047
54201
  function findSecretsBundleRoot(logger) {
54048
54202
  const candidates = [];
54049
54203
  try {
54050
- const here = import_node_path27.default.dirname((0, import_node_url4.fileURLToPath)(import_meta4.url));
54051
- candidates.push(import_node_path27.default.resolve(here, "..", "secrets"));
54204
+ const here = import_node_path28.default.dirname((0, import_node_url4.fileURLToPath)(import_meta4.url));
54205
+ candidates.push(import_node_path28.default.resolve(here, "..", "secrets"));
54052
54206
  } catch {
54053
54207
  }
54054
54208
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "secrets");
54055
54209
  if (fromArgv) candidates.push(fromArgv);
54056
54210
  for (const c of candidates) {
54057
54211
  try {
54058
- if (import_node_fs27.default.statSync(c).isDirectory()) return c;
54212
+ if (import_node_fs28.default.statSync(c).isDirectory()) return c;
54059
54213
  } catch {
54060
54214
  }
54061
54215
  }
@@ -54081,7 +54235,7 @@ function readDir(dir, logger) {
54081
54235
  const out = {};
54082
54236
  let files;
54083
54237
  try {
54084
- files = import_node_fs27.default.readdirSync(dir).filter((f) => f.endsWith(".env")).sort();
54238
+ files = import_node_fs28.default.readdirSync(dir).filter((f) => f.endsWith(".env")).sort();
54085
54239
  } catch (e) {
54086
54240
  const code = e.code;
54087
54241
  if (code !== "ENOENT") logger?.warn("secrets.dir-unreadable", { dir, code: code ?? "unknown" });
@@ -54089,9 +54243,9 @@ function readDir(dir, logger) {
54089
54243
  }
54090
54244
  for (const f of files) {
54091
54245
  try {
54092
- Object.assign(out, parseEnvFile(import_node_fs27.default.readFileSync(import_node_path27.default.join(dir, f), "utf8")));
54246
+ Object.assign(out, parseEnvFile(import_node_fs28.default.readFileSync(import_node_path28.default.join(dir, f), "utf8")));
54093
54247
  } catch (e) {
54094
- logger?.warn("secrets.file-unreadable", { file: import_node_path27.default.join(dir, f), error: e.message });
54248
+ logger?.warn("secrets.file-unreadable", { file: import_node_path28.default.join(dir, f), error: e.message });
54095
54249
  }
54096
54250
  }
54097
54251
  return out;
@@ -54101,7 +54255,7 @@ function collectKitPlaceholders(kitDir) {
54101
54255
  const scan = (file, re) => {
54102
54256
  let text;
54103
54257
  try {
54104
- text = import_node_fs27.default.readFileSync(file, "utf8");
54258
+ text = import_node_fs28.default.readFileSync(file, "utf8");
54105
54259
  } catch {
54106
54260
  return;
54107
54261
  }
@@ -54111,20 +54265,20 @@ function collectKitPlaceholders(kitDir) {
54111
54265
  if (depth > 6) return [];
54112
54266
  let entries;
54113
54267
  try {
54114
- entries = import_node_fs27.default.readdirSync(dir, { withFileTypes: true });
54268
+ entries = import_node_fs28.default.readdirSync(dir, { withFileTypes: true });
54115
54269
  } catch {
54116
54270
  return [];
54117
54271
  }
54118
54272
  return entries.flatMap((e) => {
54119
54273
  if (e.name === "node_modules") return [];
54120
- const p2 = import_node_path27.default.join(dir, e.name);
54274
+ const p2 = import_node_path28.default.join(dir, e.name);
54121
54275
  return e.isDirectory() ? walk2(p2, depth + 1) : [p2];
54122
54276
  });
54123
54277
  };
54124
- for (const f of walk2(import_node_path27.default.join(kitDir, "contract"), 0)) {
54278
+ for (const f of walk2(import_node_path28.default.join(kitDir, "contract"), 0)) {
54125
54279
  if (f.endsWith(".tmpl")) scan(f, /__([A-Z0-9_]+)__/g);
54126
54280
  }
54127
- for (const f of walk2(import_node_path27.default.join(kitDir, "examples"), 0)) {
54281
+ for (const f of walk2(import_node_path28.default.join(kitDir, "examples"), 0)) {
54128
54282
  if (f.endsWith(".env.example")) scan(f, /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g);
54129
54283
  }
54130
54284
  return out;
@@ -54142,12 +54296,12 @@ function readSecretTable(args) {
54142
54296
  }
54143
54297
 
54144
54298
  // src/dispatch/source-transcript.ts
54145
- var import_node_path28 = __toESM(require("path"), 1);
54299
+ var import_node_path29 = __toESM(require("path"), 1);
54146
54300
  init_claude_history();
54147
54301
  var NO_SOURCE_TRANSCRIPT = "(no transcript yet \u2014 operate from the task description alone)";
54148
54302
  function resolveSourceJsonlPath(sourceFile, home) {
54149
54303
  if (!sourceFile?.toolSessionId) return NO_SOURCE_TRANSCRIPT;
54150
- return import_node_path28.default.join(
54304
+ return import_node_path29.default.join(
54151
54305
  home,
54152
54306
  ".claude",
54153
54307
  "projects",
@@ -54158,7 +54312,7 @@ function resolveSourceJsonlPath(sourceFile, home) {
54158
54312
 
54159
54313
  // src/shift/store.ts
54160
54314
  var import_promises3 = __toESM(require("fs/promises"), 1);
54161
- var import_node_path29 = __toESM(require("path"), 1);
54315
+ var import_node_path30 = __toESM(require("path"), 1);
54162
54316
  var import_node_crypto6 = require("crypto");
54163
54317
 
54164
54318
  // src/shift/schedule.ts
@@ -54233,7 +54387,7 @@ function createShiftStore(deps) {
54233
54387
  flushTimer = null;
54234
54388
  }
54235
54389
  const content = { version: 1, shifts };
54236
- await import_promises3.default.mkdir(import_node_path29.default.dirname(deps.filePath), { recursive: true });
54390
+ await import_promises3.default.mkdir(import_node_path30.default.dirname(deps.filePath), { recursive: true });
54237
54391
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
54238
54392
  await import_promises3.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
54239
54393
  await import_promises3.default.rename(tmp, deps.filePath);
@@ -54681,10 +54835,10 @@ function redactEvidence(evidence) {
54681
54835
 
54682
54836
  // src/deploy/deploy-file.ts
54683
54837
  var import_promises4 = __toESM(require("fs/promises"), 1);
54684
- var import_node_path30 = __toESM(require("path"), 1);
54838
+ var import_node_path31 = __toESM(require("path"), 1);
54685
54839
  init_protocol();
54686
- var DEPLOY_FILE = import_node_path30.default.join(".clawd", "deploy.json");
54687
- var SCAN_FILE = import_node_path30.default.join(".clawd", "deploy-scan.json");
54840
+ var DEPLOY_FILE = import_node_path31.default.join(".clawd", "deploy.json");
54841
+ var SCAN_FILE = import_node_path31.default.join(".clawd", "deploy-scan.json");
54688
54842
  async function readJson(file) {
54689
54843
  let raw;
54690
54844
  try {
@@ -54700,14 +54854,14 @@ async function readJson(file) {
54700
54854
  }
54701
54855
  }
54702
54856
  async function writeJson(file, value) {
54703
- await import_promises4.default.mkdir(import_node_path30.default.dirname(file), { recursive: true });
54857
+ await import_promises4.default.mkdir(import_node_path31.default.dirname(file), { recursive: true });
54704
54858
  const tmp = `${file}.tmp-${process.pid}`;
54705
54859
  await import_promises4.default.writeFile(tmp, `${JSON.stringify(value, null, 2)}
54706
54860
  `);
54707
54861
  await import_promises4.default.rename(tmp, file);
54708
54862
  }
54709
54863
  async function readDeployFile(dir) {
54710
- const raw = await readJson(import_node_path30.default.join(dir, DEPLOY_FILE));
54864
+ const raw = await readJson(import_node_path31.default.join(dir, DEPLOY_FILE));
54711
54865
  if (raw === void 0) return void 0;
54712
54866
  const parsed = DeployFileSchema.safeParse(raw);
54713
54867
  if (!parsed.success) {
@@ -54717,10 +54871,10 @@ async function readDeployFile(dir) {
54717
54871
  return parsed.data;
54718
54872
  }
54719
54873
  async function writeDeployFile(dir, file) {
54720
- await writeJson(import_node_path30.default.join(dir, DEPLOY_FILE), DeployFileSchema.parse(file));
54874
+ await writeJson(import_node_path31.default.join(dir, DEPLOY_FILE), DeployFileSchema.parse(file));
54721
54875
  }
54722
54876
  async function readScan(dir) {
54723
- const raw = await readJson(import_node_path30.default.join(dir, SCAN_FILE));
54877
+ const raw = await readJson(import_node_path31.default.join(dir, SCAN_FILE));
54724
54878
  if (raw === void 0) return void 0;
54725
54879
  const parsed = DeployScanSchema.safeParse(raw);
54726
54880
  if (!parsed.success) {
@@ -54730,7 +54884,7 @@ async function readScan(dir) {
54730
54884
  return parsed.data;
54731
54885
  }
54732
54886
  async function writeScan(dir, scan) {
54733
- await writeJson(import_node_path30.default.join(dir, SCAN_FILE), DeployScanSchema.parse(scan));
54887
+ await writeJson(import_node_path31.default.join(dir, SCAN_FILE), DeployScanSchema.parse(scan));
54734
54888
  }
54735
54889
  function emptyDeployFile() {
54736
54890
  return { version: 1, manifest: { version: 1, clis: [], secrets: [], assets: [] } };
@@ -54760,7 +54914,7 @@ function requiredEnvNames(file) {
54760
54914
  // src/deploy/repo.ts
54761
54915
  var import_node_child_process8 = require("child_process");
54762
54916
  var import_promises5 = __toESM(require("fs/promises"), 1);
54763
- var import_node_path31 = __toESM(require("path"), 1);
54917
+ var import_node_path32 = __toESM(require("path"), 1);
54764
54918
  init_protocol();
54765
54919
 
54766
54920
  // src/deploy/templates.ts
@@ -55054,7 +55208,7 @@ async function samePath(a, b2) {
55054
55208
  try {
55055
55209
  return await import_promises5.default.realpath(x);
55056
55210
  } catch {
55057
- return import_node_path31.default.resolve(x);
55211
+ return import_node_path32.default.resolve(x);
55058
55212
  }
55059
55213
  };
55060
55214
  return await real(a) === await real(b2);
@@ -55080,7 +55234,7 @@ async function identityArgs(exec, dir) {
55080
55234
  return ["-c", "user.name=clawd", "-c", "user.email=clawd@clawos.local"];
55081
55235
  }
55082
55236
  async function writeTemplates(dir) {
55083
- const gi = import_node_path31.default.join(dir, ".gitignore");
55237
+ const gi = import_node_path32.default.join(dir, ".gitignore");
55084
55238
  let existing;
55085
55239
  try {
55086
55240
  existing = await import_promises5.default.readFile(gi, "utf8");
@@ -55088,8 +55242,8 @@ async function writeTemplates(dir) {
55088
55242
  existing = void 0;
55089
55243
  }
55090
55244
  await import_promises5.default.writeFile(gi, mergeGitignore(existing));
55091
- const wf = import_node_path31.default.join(dir, WORKFLOW_PATH);
55092
- await import_promises5.default.mkdir(import_node_path31.default.dirname(wf), { recursive: true });
55245
+ const wf = import_node_path32.default.join(dir, WORKFLOW_PATH);
55246
+ await import_promises5.default.mkdir(import_node_path32.default.dirname(wf), { recursive: true });
55093
55247
  await import_promises5.default.writeFile(wf, WORKFLOW_TEMPLATE);
55094
55248
  }
55095
55249
  async function ensureRepo(exec, args) {
@@ -55153,6 +55307,16 @@ async function listSecrets(exec, dir) {
55153
55307
  return { env: x.name, ...Number.isFinite(at2) ? { setAt: at2 } : {} };
55154
55308
  });
55155
55309
  }
55310
+ async function commitAndPush(exec, args) {
55311
+ await mustGit(exec, args.dir, ["add", "-A"], "\u6682\u5B58\u6587\u4EF6");
55312
+ const staged = await git(exec, args.dir, ["diff", "--cached", "--quiet"]);
55313
+ if (staged.code === 1) {
55314
+ const identity = await identityArgs(exec, args.dir);
55315
+ await mustGit(exec, args.dir, [...identity, "commit", "-m", args.message], "\u63D0\u4EA4");
55316
+ }
55317
+ await mustGit(exec, args.dir, ["push", "-u", "origin", "HEAD"], "\u63A8\u9001", { timeoutMs: 12e4 });
55318
+ return mustGit(exec, args.dir, ["rev-parse", "HEAD"], "\u8BFB\u63D0\u4EA4");
55319
+ }
55156
55320
  async function release(exec, args) {
55157
55321
  const info = await repoInfo(exec, args.dir);
55158
55322
  if (!info) throw new RepoError("\u8FD8\u6CA1\u6709\u4ED3\u5E93\uFF0C\u5148\u70B9\u4E00\u6B21\u300C\u53D1\u5E03\u5230\u4E91\u4E0A\u300D\u5EFA\u4ED3");
@@ -55183,8 +55347,8 @@ function runStatusOf(status) {
55183
55347
  if (status === "queued" || status === "waiting" || status === "requested" || status === "pending") return "queued";
55184
55348
  return "running";
55185
55349
  }
55186
- async function ghJson(exec, path97) {
55187
- const r = await exec("gh", ["api", path97], { timeoutMs: TIMEOUT_MS });
55350
+ async function ghJson(exec, path98) {
55351
+ const r = await exec("gh", ["api", path98], { timeoutMs: TIMEOUT_MS });
55188
55352
  if (r.spawnError || r.code !== 0) return void 0;
55189
55353
  try {
55190
55354
  return JSON.parse(r.stdout);
@@ -55244,12 +55408,12 @@ async function rerunJob(exec, slug, runId, jobId) {
55244
55408
  }
55245
55409
 
55246
55410
  // src/deploy/scan-task.ts
55247
- var import_node_path32 = __toESM(require("path"), 1);
55411
+ var import_node_path33 = __toESM(require("path"), 1);
55248
55412
  var BUTLER_PERSONA_ID = "persona-clawd-butler";
55249
55413
  var SCANNABLE_ASSETS = [
55250
55414
  {
55251
55415
  name: "deploy-kit",
55252
- path: (dataDir) => import_node_path32.default.join(dataDir, "deploy-kit"),
55416
+ path: (dataDir) => import_node_path33.default.join(dataDir, "deploy-kit"),
55253
55417
  what: "FC \u90E8\u7F72\u80FD\u529B\uFF08publish.sh / new-extension.sh / \u5DE5\u5177\u94FE / \u51ED\u8BC1\u76EE\u5F55\uFF09\u3002persona \u7528\u7EDD\u5BF9\u8DEF\u5F84\u53BB\u8C03\u8FD9\u91CC\u7684\u811A\u672C\u65F6\uFF0C\u5C31\u8BE5\u62A5\u4E00\u6761 asset\u3002"
55254
55418
  },
55255
55419
  {
@@ -55389,20 +55553,24 @@ function buildDeployHandlers(deps) {
55389
55553
  }
55390
55554
  secretsCache.delete(personaId2);
55391
55555
  }
55392
- const prev = await readDeployFile(dir).catch(() => void 0);
55556
+ let head;
55557
+ try {
55558
+ head = await commitAndPush(deps.exec, { dir, message: `clawd: \u626B\u63CF\u524D\u843D\u5B58 ${new Date(deps.now()).toISOString()}` });
55559
+ } catch (err) {
55560
+ throw toClawdError(err);
55561
+ }
55562
+ runCache.delete(personaId2);
55393
55563
  await writeDeployFile(dir, emptyDeployFile());
55394
55564
  const startedAt = deps.now();
55395
- await writeScan(dir, { status: "scanning", evidence: [], notes: [], scannedAssets: [], startedAt });
55565
+ const base = { evidence: [], notes: [], scannedAssets: [], startedAt, head };
55566
+ await writeScan(dir, { status: "scanning", ...base });
55396
55567
  const started = deps.startScan(personaId2);
55397
55568
  if ("sessionId" in started) {
55398
- await writeScan(dir, { status: "scanning", scanSessionId: started.sessionId, evidence: [], notes: [], scannedAssets: [], startedAt });
55569
+ await writeScan(dir, { status: "scanning", scanSessionId: started.sessionId, ...base });
55399
55570
  } else {
55400
55571
  await writeScan(dir, {
55401
55572
  status: "failed",
55402
- evidence: [],
55403
- notes: [],
55404
- scannedAssets: [],
55405
- startedAt,
55573
+ ...base,
55406
55574
  finishedAt: deps.now(),
55407
55575
  error: `\u8D77\u626B\u63CF\u4F1A\u8BDD\u5931\u8D25\uFF1A${started.error}`
55408
55576
  });
@@ -55498,6 +55666,11 @@ function buildDeployHandlers(deps) {
55498
55666
  const scan = await readScan(dir);
55499
55667
  if (scan?.status === "scanning") throw invalid("\u626B\u63CF\u8FD8\u6CA1\u7ED3\u675F");
55500
55668
  if (scan?.status !== "done") throw invalid(scan?.status === "failed" ? "\u4E0A\u6B21\u626B\u63CF\u5931\u8D25\u4E86\uFF0C\u5148\u91CD\u65B0\u626B\u63CF" : "\u8FD8\u6CA1\u626B\u63CF\u8FC7\uFF0C\u5148\u626B\u63CF");
55669
+ if (!isScanFresh(scan, repo2)) {
55670
+ throw invalid(
55671
+ repo2.dirty ? "persona \u76EE\u5F55\u6709\u6539\u52A8\u8FD8\u6CA1\u626B\u8FC7\uFF0C\u5148\u91CD\u65B0\u626B\u63CF\u4E00\u6B21\uFF08\u6E05\u5355\u8981\u8DDF\u7740\u6539\u52A8\u8D70\uFF09" : "\u6E05\u5355\u662F\u66F4\u65E9\u90A3\u4E00\u7248\u626B\u51FA\u6765\u7684\uFF0C\u5148\u91CD\u65B0\u626B\u63CF\u4E00\u6B21"
55672
+ );
55673
+ }
55501
55674
  const blockers = [];
55502
55675
  let present;
55503
55676
  try {
@@ -55518,6 +55691,8 @@ function buildDeployHandlers(deps) {
55518
55691
  try {
55519
55692
  const result = await release(deps.exec, { dir, now: deps.now });
55520
55693
  runCache.delete(personaId2);
55694
+ const scanned = await readScan(dir);
55695
+ if (scanned) await writeScan(dir, { ...scanned, head: result.sha });
55521
55696
  return { response: { type: "deploy:release", ...result } };
55522
55697
  } catch (err) {
55523
55698
  throw toClawdError(err);
@@ -55942,15 +56117,15 @@ async function refreshTunnelUrlOnStartup(deps) {
55942
56117
  }
55943
56118
 
55944
56119
  // src/lark-bot-connector/binding-store.ts
55945
- var import_node_fs28 = __toESM(require("fs"), 1);
55946
- var import_node_path33 = __toESM(require("path"), 1);
56120
+ var import_node_fs29 = __toESM(require("fs"), 1);
56121
+ var import_node_path34 = __toESM(require("path"), 1);
55947
56122
  function createLarkBotBindingStore(personaRoot) {
55948
- const filePath = (personaId2) => import_node_path33.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
56123
+ const filePath = (personaId2) => import_node_path34.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
55949
56124
  const read = (personaId2) => {
55950
56125
  const file = filePath(personaId2);
55951
- if (!import_node_fs28.default.existsSync(file)) return null;
56126
+ if (!import_node_fs29.default.existsSync(file)) return null;
55952
56127
  try {
55953
- const raw = JSON.parse(import_node_fs28.default.readFileSync(file, "utf8"));
56128
+ const raw = JSON.parse(import_node_fs29.default.readFileSync(file, "utf8"));
55954
56129
  if (typeof raw?.appId !== "string" || raw.appId.length === 0) return null;
55955
56130
  return raw;
55956
56131
  } catch {
@@ -55959,16 +56134,16 @@ function createLarkBotBindingStore(personaRoot) {
55959
56134
  };
55960
56135
  const write = (personaId2, meta) => {
55961
56136
  const file = filePath(personaId2);
55962
- import_node_fs28.default.mkdirSync(import_node_path33.default.dirname(file), { recursive: true });
56137
+ import_node_fs29.default.mkdirSync(import_node_path34.default.dirname(file), { recursive: true });
55963
56138
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
55964
- import_node_fs28.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
55965
- import_node_fs28.default.renameSync(tmp, file);
56139
+ import_node_fs29.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
56140
+ import_node_fs29.default.renameSync(tmp, file);
55966
56141
  };
55967
56142
  return {
55968
56143
  read,
55969
56144
  write,
55970
56145
  remove(personaId2) {
55971
- import_node_fs28.default.rmSync(filePath(personaId2), { force: true });
56146
+ import_node_fs29.default.rmSync(filePath(personaId2), { force: true });
55972
56147
  },
55973
56148
  addRemovedChat(personaId2, chatId) {
55974
56149
  const meta = read(personaId2);
@@ -56126,8 +56301,8 @@ function createLarkBotCloudClient(opts) {
56126
56301
  }
56127
56302
 
56128
56303
  // src/lark-bot-connector/chat-router.ts
56129
- var import_node_fs29 = __toESM(require("fs"), 1);
56130
- var import_node_path34 = __toESM(require("path"), 1);
56304
+ var import_node_fs30 = __toESM(require("fs"), 1);
56305
+ var import_node_path35 = __toESM(require("path"), 1);
56131
56306
  init_protocol();
56132
56307
  var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
56133
56308
  var LOCAL_TURN_RETRIES = 2;
@@ -56193,9 +56368,9 @@ function createLarkChatRouter(deps) {
56193
56368
  continue;
56194
56369
  }
56195
56370
  const dir = deps.mediaRootFor(env.chatId);
56196
- import_node_fs29.default.mkdirSync(dir, { recursive: true });
56197
- const p2 = import_node_path34.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
56198
- import_node_fs29.default.writeFileSync(p2, r.data);
56371
+ import_node_fs30.default.mkdirSync(dir, { recursive: true });
56372
+ const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
56373
+ import_node_fs30.default.writeFileSync(p2, r.data);
56199
56374
  lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56200
56375
  } catch (err) {
56201
56376
  deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
@@ -56216,9 +56391,9 @@ function createLarkChatRouter(deps) {
56216
56391
  continue;
56217
56392
  }
56218
56393
  const dir = deps.mediaRootFor(env.chatId);
56219
- import_node_fs29.default.mkdirSync(dir, { recursive: true });
56220
- const p2 = import_node_path34.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
56221
- import_node_fs29.default.writeFileSync(p2, r.data);
56394
+ import_node_fs30.default.mkdirSync(dir, { recursive: true });
56395
+ const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
56396
+ import_node_fs30.default.writeFileSync(p2, r.data);
56222
56397
  lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56223
56398
  } catch (err) {
56224
56399
  deps.logger?.warn(`larkBot file fetch failed ${f.key}: ${err.message}`);
@@ -57307,7 +57482,7 @@ var CodexHistoryReader = class {
57307
57482
  };
57308
57483
 
57309
57484
  // src/tools/codex-skills.ts
57310
- var import_node_path35 = __toESM(require("path"), 1);
57485
+ var import_node_path36 = __toESM(require("path"), 1);
57311
57486
  function str3(v2) {
57312
57487
  return typeof v2 === "string" ? v2 : void 0;
57313
57488
  }
@@ -57322,13 +57497,13 @@ function mapSkillsListResponse(res) {
57322
57497
  const r = s ?? {};
57323
57498
  const name = str3(r.name);
57324
57499
  if (!name) continue;
57325
- const path97 = str3(r.path);
57500
+ const path98 = str3(r.path);
57326
57501
  const description = str3(r.description);
57327
57502
  const isPlugin = name.includes(":");
57328
57503
  out.push({
57329
57504
  name,
57330
57505
  source: isPlugin ? "plugin" : "project",
57331
- ...path97 ? { path: path97 } : {},
57506
+ ...path98 ? { path: path98 } : {},
57332
57507
  ...description ? { description } : {},
57333
57508
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
57334
57509
  });
@@ -57344,7 +57519,7 @@ async function listCodexSkills(cwd, deps = {}) {
57344
57519
  // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
57345
57520
  // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
57346
57521
  beforeRequest: (client) => {
57347
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path35.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
57522
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path36.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
57348
57523
  }
57349
57524
  });
57350
57525
  return mapSkillsListResponse(res);
@@ -57429,23 +57604,23 @@ function str4(v2) {
57429
57604
  }
57430
57605
 
57431
57606
  // src/workspace/browser.ts
57432
- var import_node_fs30 = __toESM(require("fs"), 1);
57433
- var import_node_os8 = __toESM(require("os"), 1);
57434
- var import_node_path36 = __toESM(require("path"), 1);
57607
+ var import_node_fs31 = __toESM(require("fs"), 1);
57608
+ var import_node_os9 = __toESM(require("os"), 1);
57609
+ var import_node_path37 = __toESM(require("path"), 1);
57435
57610
  init_protocol();
57436
57611
  var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
57437
57612
  function resolveInsideCwd(cwd, subpath) {
57438
- const absCwd = import_node_path36.default.resolve(cwd);
57439
- const joined = import_node_path36.default.resolve(absCwd, subpath ?? ".");
57440
- const rel = import_node_path36.default.relative(absCwd, joined);
57441
- if (rel.startsWith("..") || import_node_path36.default.isAbsolute(rel)) {
57613
+ const absCwd = import_node_path37.default.resolve(cwd);
57614
+ const joined = import_node_path37.default.resolve(absCwd, subpath ?? ".");
57615
+ const rel = import_node_path37.default.relative(absCwd, joined);
57616
+ if (rel.startsWith("..") || import_node_path37.default.isAbsolute(rel)) {
57442
57617
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
57443
57618
  }
57444
57619
  return joined;
57445
57620
  }
57446
57621
  function ensureCwd(cwd) {
57447
57622
  try {
57448
- const stat = import_node_fs30.default.statSync(cwd);
57623
+ const stat = import_node_fs31.default.statSync(cwd);
57449
57624
  if (!stat.isDirectory()) {
57450
57625
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
57451
57626
  }
@@ -57456,10 +57631,10 @@ function ensureCwd(cwd) {
57456
57631
  }
57457
57632
  var WorkspaceBrowser = class {
57458
57633
  list(args) {
57459
- const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
57634
+ const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os9.default.homedir();
57460
57635
  ensureCwd(cwd);
57461
57636
  const full = resolveInsideCwd(cwd, args.path);
57462
- const dirents = import_node_fs30.default.readdirSync(full, { withFileTypes: true });
57637
+ const dirents = import_node_fs31.default.readdirSync(full, { withFileTypes: true });
57463
57638
  const entries = [];
57464
57639
  for (const d of dirents) {
57465
57640
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -57469,7 +57644,7 @@ var WorkspaceBrowser = class {
57469
57644
  mtime: ""
57470
57645
  };
57471
57646
  try {
57472
- const st = import_node_fs30.default.statSync(import_node_path36.default.join(full, d.name));
57647
+ const st = import_node_fs31.default.statSync(import_node_path37.default.join(full, d.name));
57473
57648
  entry.mtime = new Date(st.mtimeMs).toISOString();
57474
57649
  if (d.isFile()) entry.size = st.size;
57475
57650
  } catch {
@@ -57485,14 +57660,14 @@ var WorkspaceBrowser = class {
57485
57660
  read(args) {
57486
57661
  ensureCwd(args.cwd);
57487
57662
  const full = resolveInsideCwd(args.cwd, args.path);
57488
- const st = import_node_fs30.default.statSync(full);
57663
+ const st = import_node_fs31.default.statSync(full);
57489
57664
  if (!st.isFile()) {
57490
57665
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
57491
57666
  }
57492
57667
  if (st.size > MAX_FILE_BYTES2) {
57493
57668
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
57494
57669
  }
57495
- const buf = import_node_fs30.default.readFileSync(full);
57670
+ const buf = import_node_fs31.default.readFileSync(full);
57496
57671
  const isBinary = buf.includes(0);
57497
57672
  if (isBinary) {
57498
57673
  return {
@@ -57514,20 +57689,20 @@ var WorkspaceBrowser = class {
57514
57689
  };
57515
57690
 
57516
57691
  // src/skills/agents-scanner.ts
57517
- var import_node_fs31 = __toESM(require("fs"), 1);
57518
- var import_node_os9 = __toESM(require("os"), 1);
57519
- var import_node_path37 = __toESM(require("path"), 1);
57692
+ var import_node_fs32 = __toESM(require("fs"), 1);
57693
+ var import_node_os10 = __toESM(require("os"), 1);
57694
+ var import_node_path38 = __toESM(require("path"), 1);
57520
57695
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
57521
57696
  function isDirLikeSync2(p2) {
57522
57697
  try {
57523
- return import_node_fs31.default.statSync(p2).isDirectory();
57698
+ return import_node_fs32.default.statSync(p2).isDirectory();
57524
57699
  } catch {
57525
57700
  return false;
57526
57701
  }
57527
57702
  }
57528
57703
  function fileExistsSync(p2) {
57529
57704
  try {
57530
- return import_node_fs31.default.statSync(p2).isFile();
57705
+ return import_node_fs32.default.statSync(p2).isFile();
57531
57706
  } catch {
57532
57707
  return false;
57533
57708
  }
@@ -57535,7 +57710,7 @@ function fileExistsSync(p2) {
57535
57710
  function parseAgentFile(filePath) {
57536
57711
  let content;
57537
57712
  try {
57538
- content = import_node_fs31.default.readFileSync(filePath, "utf8");
57713
+ content = import_node_fs32.default.readFileSync(filePath, "utf8");
57539
57714
  } catch {
57540
57715
  return {};
57541
57716
  }
@@ -57548,16 +57723,16 @@ function parseAgentFile(filePath) {
57548
57723
  function scanAgentsDir(dir, source, seen, out) {
57549
57724
  let entries;
57550
57725
  try {
57551
- entries = import_node_fs31.default.readdirSync(dir, { withFileTypes: true });
57726
+ entries = import_node_fs32.default.readdirSync(dir, { withFileTypes: true });
57552
57727
  } catch {
57553
57728
  return;
57554
57729
  }
57555
57730
  for (const ent of entries) {
57556
57731
  if (!ent.name.endsWith(".md")) continue;
57557
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path37.default.join(dir, ent.name)))) {
57732
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path38.default.join(dir, ent.name)))) {
57558
57733
  continue;
57559
57734
  }
57560
- const filePath = import_node_path37.default.join(dir, ent.name);
57735
+ const filePath = import_node_path38.default.join(dir, ent.name);
57561
57736
  const baseName = ent.name.replace(/\.md$/, "");
57562
57737
  if (seen.has(baseName)) continue;
57563
57738
  seen.add(baseName);
@@ -57575,12 +57750,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
57575
57750
  function walk2(dir, namespaces) {
57576
57751
  let entries;
57577
57752
  try {
57578
- entries = import_node_fs31.default.readdirSync(dir, { withFileTypes: true });
57753
+ entries = import_node_fs32.default.readdirSync(dir, { withFileTypes: true });
57579
57754
  } catch {
57580
57755
  return;
57581
57756
  }
57582
57757
  for (const ent of entries) {
57583
- const childPath = import_node_path37.default.join(dir, ent.name);
57758
+ const childPath = import_node_path38.default.join(dir, ent.name);
57584
57759
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
57585
57760
  walk2(childPath, [...namespaces, ent.name]);
57586
57761
  continue;
@@ -57605,13 +57780,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
57605
57780
  walk2(root, []);
57606
57781
  }
57607
57782
  function readInstalledPlugins2(home) {
57608
- const pluginsDir = import_node_path37.default.join(home, ".claude", "plugins");
57609
- const v2 = import_node_path37.default.join(pluginsDir, "installed_plugins_v2.json");
57610
- const v1 = import_node_path37.default.join(pluginsDir, "installed_plugins.json");
57783
+ const pluginsDir = import_node_path38.default.join(home, ".claude", "plugins");
57784
+ const v2 = import_node_path38.default.join(pluginsDir, "installed_plugins_v2.json");
57785
+ const v1 = import_node_path38.default.join(pluginsDir, "installed_plugins.json");
57611
57786
  let raw = null;
57612
57787
  for (const candidate of [v2, v1]) {
57613
57788
  try {
57614
- raw = import_node_fs31.default.readFileSync(candidate, "utf8");
57789
+ raw = import_node_fs32.default.readFileSync(candidate, "utf8");
57615
57790
  break;
57616
57791
  } catch {
57617
57792
  }
@@ -57636,19 +57811,19 @@ function readInstalledPlugins2(home) {
57636
57811
  return out;
57637
57812
  }
57638
57813
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
57639
- let cur = import_node_path37.default.resolve(startCwd);
57640
- const fsRoot = import_node_path37.default.parse(cur).root;
57814
+ let cur = import_node_path38.default.resolve(startCwd);
57815
+ const fsRoot = import_node_path38.default.parse(cur).root;
57641
57816
  while (true) {
57642
- scanAgentsDir(import_node_path37.default.join(cur, ".claude", "agents"), "project", seen, out);
57817
+ scanAgentsDir(import_node_path38.default.join(cur, ".claude", "agents"), "project", seen, out);
57643
57818
  let hasGit = false;
57644
57819
  try {
57645
- hasGit = import_node_fs31.default.existsSync(import_node_path37.default.join(cur, ".git"));
57820
+ hasGit = import_node_fs32.default.existsSync(import_node_path38.default.join(cur, ".git"));
57646
57821
  } catch {
57647
57822
  }
57648
57823
  if (hasGit) return;
57649
57824
  if (cur === home) return;
57650
57825
  if (cur === fsRoot) return;
57651
- const parent = import_node_path37.default.dirname(cur);
57826
+ const parent = import_node_path38.default.dirname(cur);
57652
57827
  if (parent === cur) return;
57653
57828
  cur = parent;
57654
57829
  }
@@ -57658,7 +57833,7 @@ var AgentsScanner = class {
57658
57833
  extraPluginRoots;
57659
57834
  policyDir;
57660
57835
  constructor(opts = {}) {
57661
- this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os9.default.homedir();
57836
+ this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os10.default.homedir();
57662
57837
  this.extraPluginRoots = opts.extraPluginRoots ?? [];
57663
57838
  if (opts.policyDir !== void 0) {
57664
57839
  this.policyDir = opts.policyDir;
@@ -57683,7 +57858,7 @@ var AgentsScanner = class {
57683
57858
  }
57684
57859
  const fsBlock = [];
57685
57860
  scanAgentsDir(
57686
- import_node_path37.default.join(this.home, ".claude", "agents"),
57861
+ import_node_path38.default.join(this.home, ".claude", "agents"),
57687
57862
  "global",
57688
57863
  seen,
57689
57864
  fsBlock
@@ -57697,7 +57872,7 @@ var AgentsScanner = class {
57697
57872
  ...this.extraPluginRoots
57698
57873
  ];
57699
57874
  for (const { name, root } of plugins) {
57700
- const agentsRoot = import_node_path37.default.join(root, "agents");
57875
+ const agentsRoot = import_node_path38.default.join(root, "agents");
57701
57876
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
57702
57877
  }
57703
57878
  return [...builtinBlock, ...fsBlock];
@@ -57705,28 +57880,28 @@ var AgentsScanner = class {
57705
57880
  };
57706
57881
 
57707
57882
  // src/observer/session-observer.ts
57708
- var import_node_fs33 = __toESM(require("fs"), 1);
57709
- var import_node_os11 = __toESM(require("os"), 1);
57710
- var import_node_path39 = __toESM(require("path"), 1);
57883
+ var import_node_fs34 = __toESM(require("fs"), 1);
57884
+ var import_node_os12 = __toESM(require("os"), 1);
57885
+ var import_node_path40 = __toESM(require("path"), 1);
57711
57886
  init_claude_history();
57712
57887
 
57713
57888
  // src/observer/subagent-meta-observer.ts
57714
- var import_node_fs32 = __toESM(require("fs"), 1);
57715
- var import_node_os10 = __toESM(require("os"), 1);
57716
- var import_node_path38 = __toESM(require("path"), 1);
57889
+ var import_node_fs33 = __toESM(require("fs"), 1);
57890
+ var import_node_os11 = __toESM(require("os"), 1);
57891
+ var import_node_path39 = __toESM(require("path"), 1);
57717
57892
  init_claude_history();
57718
57893
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
57719
57894
  var SubagentMetaObserver = class {
57720
57895
  constructor(opts) {
57721
57896
  this.opts = opts;
57722
- this.home = opts.home ?? import_node_os10.default.homedir();
57897
+ this.home = opts.home ?? import_node_os11.default.homedir();
57723
57898
  }
57724
57899
  opts;
57725
57900
  home;
57726
57901
  watches = /* @__PURE__ */ new Map();
57727
57902
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
57728
57903
  resolveSubagentDir(cwd, toolSessionId) {
57729
- return import_node_path38.default.join(
57904
+ return import_node_path39.default.join(
57730
57905
  this.home,
57731
57906
  ".claude",
57732
57907
  "projects",
@@ -57756,7 +57931,7 @@ var SubagentMetaObserver = class {
57756
57931
  attachWatcher(w2) {
57757
57932
  if (w2.watcher) return;
57758
57933
  try {
57759
- w2.watcher = import_node_fs32.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
57934
+ w2.watcher = import_node_fs33.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
57760
57935
  if (!name) return;
57761
57936
  const m2 = META_RE.exec(String(name));
57762
57937
  if (!m2) return;
@@ -57768,7 +57943,7 @@ var SubagentMetaObserver = class {
57768
57943
  scan(w2) {
57769
57944
  let entries;
57770
57945
  try {
57771
- entries = import_node_fs32.default.readdirSync(w2.dirPath);
57946
+ entries = import_node_fs33.default.readdirSync(w2.dirPath);
57772
57947
  } catch {
57773
57948
  return;
57774
57949
  }
@@ -57782,10 +57957,10 @@ var SubagentMetaObserver = class {
57782
57957
  if (!m2) return;
57783
57958
  const agentId = m2[1];
57784
57959
  if (w2.emitted.has(agentId)) return;
57785
- const file = import_node_path38.default.join(w2.dirPath, name);
57960
+ const file = import_node_path39.default.join(w2.dirPath, name);
57786
57961
  let raw;
57787
57962
  try {
57788
- raw = import_node_fs32.default.readFileSync(file, "utf8");
57963
+ raw = import_node_fs33.default.readFileSync(file, "utf8");
57789
57964
  } catch {
57790
57965
  return;
57791
57966
  }
@@ -57830,7 +58005,7 @@ var SubagentMetaObserver = class {
57830
58005
  var SessionObserver = class {
57831
58006
  constructor(opts) {
57832
58007
  this.opts = opts;
57833
- this.home = opts.home ?? import_node_os11.default.homedir();
58008
+ this.home = opts.home ?? import_node_os12.default.homedir();
57834
58009
  this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
57835
58010
  }
57836
58011
  opts;
@@ -57842,14 +58017,14 @@ var SessionObserver = class {
57842
58017
  metaObserver;
57843
58018
  resolveJsonlPath(cwd, toolSessionId, override) {
57844
58019
  if (override) return override;
57845
- return import_node_path39.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
58020
+ return import_node_path40.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
57846
58021
  }
57847
58022
  start(args) {
57848
58023
  this.stop(args.sessionId);
57849
58024
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
57850
58025
  let size = 0;
57851
58026
  try {
57852
- size = import_node_fs33.default.statSync(filePath).size;
58027
+ size = import_node_fs34.default.statSync(filePath).size;
57853
58028
  } catch {
57854
58029
  }
57855
58030
  const w2 = {
@@ -57862,16 +58037,16 @@ var SessionObserver = class {
57862
58037
  adapter: args.adapter,
57863
58038
  prevIsRejectSentinel: false,
57864
58039
  toolSessionId: args.toolSessionId,
57865
- sawFile: import_node_fs33.default.existsSync(filePath),
58040
+ sawFile: import_node_fs34.default.existsSync(filePath),
57866
58041
  lastRelocateScanMs: 0,
57867
58042
  pendingCwdDerive: false,
57868
58043
  lastDeriveMs: 0
57869
58044
  };
57870
58045
  try {
57871
- import_node_fs33.default.mkdirSync(import_node_path39.default.dirname(filePath), { recursive: true });
58046
+ import_node_fs34.default.mkdirSync(import_node_path40.default.dirname(filePath), { recursive: true });
57872
58047
  } catch {
57873
58048
  }
57874
- w2.watcher = import_node_fs33.default.watch(import_node_path39.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
58049
+ w2.watcher = import_node_fs34.default.watch(import_node_path40.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
57875
58050
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
57876
58051
  this.poll(w2);
57877
58052
  });
@@ -57894,7 +58069,7 @@ var SessionObserver = class {
57894
58069
  // 异常静默吞,不阻塞 watcher 启动
57895
58070
  hydrateMetaTail(w2, maxLines = 200) {
57896
58071
  try {
57897
- const raw = import_node_fs33.default.readFileSync(w2.filePath, "utf8");
58072
+ const raw = import_node_fs34.default.readFileSync(w2.filePath, "utf8");
57898
58073
  if (!raw) return;
57899
58074
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
57900
58075
  if (allLines.length === 0) return;
@@ -57918,7 +58093,7 @@ var SessionObserver = class {
57918
58093
  poll(w2) {
57919
58094
  let size = 0;
57920
58095
  try {
57921
- size = import_node_fs33.default.statSync(w2.filePath).size;
58096
+ size = import_node_fs34.default.statSync(w2.filePath).size;
57922
58097
  } catch {
57923
58098
  if (w2.sawFile) this.maybeRelocate(w2);
57924
58099
  return;
@@ -57929,11 +58104,11 @@ var SessionObserver = class {
57929
58104
  w2.buf = "";
57930
58105
  }
57931
58106
  if (size === w2.lastSize) return;
57932
- const fd = import_node_fs33.default.openSync(w2.filePath, "r");
58107
+ const fd = import_node_fs34.default.openSync(w2.filePath, "r");
57933
58108
  try {
57934
58109
  const len = size - w2.lastSize;
57935
58110
  const buf = Buffer.alloc(len);
57936
- import_node_fs33.default.readSync(fd, buf, 0, len, w2.lastSize);
58111
+ import_node_fs34.default.readSync(fd, buf, 0, len, w2.lastSize);
57937
58112
  w2.lastSize = size;
57938
58113
  w2.buf += buf.toString("utf8");
57939
58114
  let newlineIndex;
@@ -57956,7 +58131,7 @@ var SessionObserver = class {
57956
58131
  }
57957
58132
  }
57958
58133
  } finally {
57959
- import_node_fs33.default.closeSync(fd);
58134
+ import_node_fs34.default.closeSync(fd);
57960
58135
  }
57961
58136
  if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
57962
58137
  }
@@ -57968,7 +58143,7 @@ var SessionObserver = class {
57968
58143
  const now = Date.now();
57969
58144
  if (now - w2.lastRelocateScanMs < 1e3) return;
57970
58145
  w2.lastRelocateScanMs = now;
57971
- const projectsRoot = import_node_path39.default.join(this.home, ".claude", "projects");
58146
+ const projectsRoot = import_node_path40.default.join(this.home, ".claude", "projects");
57972
58147
  const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
57973
58148
  if (!found || found === w2.filePath) return;
57974
58149
  try {
@@ -57977,7 +58152,7 @@ var SessionObserver = class {
57977
58152
  }
57978
58153
  w2.filePath = found;
57979
58154
  try {
57980
- w2.watcher = import_node_fs33.default.watch(import_node_path39.default.dirname(found), { persistent: false }, (_event, changedName) => {
58155
+ w2.watcher = import_node_fs34.default.watch(import_node_path40.default.dirname(found), { persistent: false }, (_event, changedName) => {
57981
58156
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
57982
58157
  this.poll(w2);
57983
58158
  });
@@ -58098,9 +58273,9 @@ function listRegistered() {
58098
58273
 
58099
58274
  // src/tools/title-generator.ts
58100
58275
  var import_node_child_process9 = require("child_process");
58101
- var import_node_fs34 = __toESM(require("fs"), 1);
58102
- var import_node_os12 = __toESM(require("os"), 1);
58103
- var import_node_path40 = __toESM(require("path"), 1);
58276
+ var import_node_fs35 = __toESM(require("fs"), 1);
58277
+ var import_node_os13 = __toESM(require("os"), 1);
58278
+ var import_node_path41 = __toESM(require("path"), 1);
58104
58279
  var TITLE_GEN_DIR_PREFIX = "clawd-title-";
58105
58280
  var TITLE_MODEL_BY_TOOL = {
58106
58281
  claude: "haiku",
@@ -58171,21 +58346,21 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
58171
58346
  if (!text) return null;
58172
58347
  let workDir;
58173
58348
  try {
58174
- workDir = import_node_fs34.default.mkdtempSync(import_node_path40.default.join(import_node_os12.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
58349
+ workDir = import_node_fs35.default.mkdtempSync(import_node_path41.default.join(import_node_os13.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
58175
58350
  } catch {
58176
58351
  return null;
58177
58352
  }
58178
58353
  const cleanupWorkDir = () => {
58179
58354
  try {
58180
- import_node_fs34.default.rmSync(workDir, { recursive: true, force: true });
58355
+ import_node_fs35.default.rmSync(workDir, { recursive: true, force: true });
58181
58356
  } catch {
58182
58357
  }
58183
58358
  };
58184
- const outFile = import_node_path40.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
58185
- const schemaFile = import_node_path40.default.join(workDir, "title-schema.json");
58359
+ const outFile = import_node_path41.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
58360
+ const schemaFile = import_node_path41.default.join(workDir, "title-schema.json");
58186
58361
  if (tool === "codex") {
58187
58362
  try {
58188
- import_node_fs34.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
58363
+ import_node_fs35.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
58189
58364
  } catch {
58190
58365
  cleanupWorkDir();
58191
58366
  return null;
@@ -58235,7 +58410,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
58235
58410
  if (tool === "claude") return finish(parseTitleJson(stdout));
58236
58411
  let fileText = "";
58237
58412
  try {
58238
- fileText = import_node_fs34.default.readFileSync(outFile, "utf8");
58413
+ fileText = import_node_fs35.default.readFileSync(outFile, "utf8");
58239
58414
  } catch {
58240
58415
  return finish(null);
58241
58416
  }
@@ -58945,8 +59120,8 @@ async function authenticate(token, deps) {
58945
59120
  }
58946
59121
 
58947
59122
  // src/legacy-cleanup.ts
58948
- var fs45 = __toESM(require("fs/promises"), 1);
58949
- var path48 = __toESM(require("path"), 1);
59123
+ var fs46 = __toESM(require("fs/promises"), 1);
59124
+ var path49 = __toESM(require("path"), 1);
58950
59125
  var LEGACY_FILES = [
58951
59126
  "personal-capability.json",
58952
59127
  "received-capabilities.json",
@@ -58955,9 +59130,9 @@ var LEGACY_FILES = [
58955
59130
  async function cleanupLegacyCapabilityFiles(dataDir, logger) {
58956
59131
  const removed = [];
58957
59132
  for (const name of LEGACY_FILES) {
58958
- const p2 = path48.join(dataDir, name);
59133
+ const p2 = path49.join(dataDir, name);
58959
59134
  try {
58960
- await fs45.unlink(p2);
59135
+ await fs46.unlink(p2);
58961
59136
  removed.push(name);
58962
59137
  logger.debug("legacy capability file removed", { file: name });
58963
59138
  } catch (err) {
@@ -58969,13 +59144,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
58969
59144
  }
58970
59145
 
58971
59146
  // src/inbox/inbox-store.ts
58972
- var fs46 = __toESM(require("fs"), 1);
58973
- var path49 = __toESM(require("path"), 1);
59147
+ var fs47 = __toESM(require("fs"), 1);
59148
+ var path50 = __toESM(require("path"), 1);
58974
59149
  var INBOX_SUBDIR = "inbox";
58975
59150
  var InboxStore = class {
58976
59151
  constructor(dataDir) {
58977
59152
  this.dataDir = dataDir;
58978
- fs46.mkdirSync(this.dirPath(), { recursive: true });
59153
+ fs47.mkdirSync(this.dirPath(), { recursive: true });
58979
59154
  }
58980
59155
  dataDir;
58981
59156
  /**
@@ -58987,7 +59162,7 @@ var InboxStore = class {
58987
59162
  const file = this.filePath(peerDeviceId);
58988
59163
  let raw;
58989
59164
  try {
58990
- raw = fs46.readFileSync(file, "utf8");
59165
+ raw = fs47.readFileSync(file, "utf8");
58991
59166
  } catch (err) {
58992
59167
  if (err?.code === "ENOENT") return [];
58993
59168
  return [];
@@ -59003,7 +59178,7 @@ var InboxStore = class {
59003
59178
  const dir = this.dirPath();
59004
59179
  let entries;
59005
59180
  try {
59006
- entries = fs46.readdirSync(dir);
59181
+ entries = fs47.readdirSync(dir);
59007
59182
  } catch (err) {
59008
59183
  if (err?.code === "ENOENT") return [];
59009
59184
  return [];
@@ -59019,9 +59194,9 @@ var InboxStore = class {
59019
59194
  if (existing.some((m2) => m2.id === message.id)) return;
59020
59195
  const file = this.filePath(message.peerDeviceId);
59021
59196
  const line = JSON.stringify(message) + "\n";
59022
- fs46.appendFileSync(file, line, { mode: 384 });
59197
+ fs47.appendFileSync(file, line, { mode: 384 });
59023
59198
  try {
59024
- fs46.chmodSync(file, 384);
59199
+ fs47.chmodSync(file, 384);
59025
59200
  } catch {
59026
59201
  }
59027
59202
  }
@@ -59051,7 +59226,7 @@ var InboxStore = class {
59051
59226
  removeByPeerDeviceId(peerDeviceId) {
59052
59227
  const file = this.filePath(peerDeviceId);
59053
59228
  try {
59054
- fs46.unlinkSync(file);
59229
+ fs47.unlinkSync(file);
59055
59230
  } catch (err) {
59056
59231
  if (err?.code === "ENOENT") return;
59057
59232
  }
@@ -59060,18 +59235,18 @@ var InboxStore = class {
59060
59235
  const file = this.filePath(peerDeviceId);
59061
59236
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
59062
59237
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
59063
- fs46.writeFileSync(tmp, content, { mode: 384 });
59064
- fs46.renameSync(tmp, file);
59238
+ fs47.writeFileSync(tmp, content, { mode: 384 });
59239
+ fs47.renameSync(tmp, file);
59065
59240
  try {
59066
- fs46.chmodSync(file, 384);
59241
+ fs47.chmodSync(file, 384);
59067
59242
  } catch {
59068
59243
  }
59069
59244
  }
59070
59245
  dirPath() {
59071
- return path49.join(this.dataDir, INBOX_SUBDIR);
59246
+ return path50.join(this.dataDir, INBOX_SUBDIR);
59072
59247
  }
59073
59248
  filePath(peerDeviceId) {
59074
- return path49.join(this.dirPath(), `${peerDeviceId}.jsonl`);
59249
+ return path50.join(this.dirPath(), `${peerDeviceId}.jsonl`);
59075
59250
  }
59076
59251
  };
59077
59252
  function parseAllLines(raw) {
@@ -59159,8 +59334,8 @@ var InboxManager = class {
59159
59334
  };
59160
59335
 
59161
59336
  // src/state/contact-store.ts
59162
- var fs47 = __toESM(require("fs"), 1);
59163
- var path50 = __toESM(require("path"), 1);
59337
+ var fs48 = __toESM(require("fs"), 1);
59338
+ var path51 = __toESM(require("path"), 1);
59164
59339
  var FILE_NAME = "contacts.json";
59165
59340
  var ContactStore = class {
59166
59341
  constructor(dataDir) {
@@ -59170,10 +59345,10 @@ var ContactStore = class {
59170
59345
  contacts = /* @__PURE__ */ new Map();
59171
59346
  load() {
59172
59347
  this.contacts.clear();
59173
- const file = path50.join(this.dataDir, FILE_NAME);
59348
+ const file = path51.join(this.dataDir, FILE_NAME);
59174
59349
  let raw;
59175
59350
  try {
59176
- raw = fs47.readFileSync(file, "utf8");
59351
+ raw = fs48.readFileSync(file, "utf8");
59177
59352
  } catch (err) {
59178
59353
  if (err?.code !== "ENOENT") this.renameBak(file);
59179
59354
  return;
@@ -59254,20 +59429,20 @@ var ContactStore = class {
59254
59429
  return true;
59255
59430
  }
59256
59431
  flush() {
59257
- const file = path50.join(this.dataDir, FILE_NAME);
59432
+ const file = path51.join(this.dataDir, FILE_NAME);
59258
59433
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
59259
59434
  const content = JSON.stringify(
59260
59435
  { contacts: Array.from(this.contacts.values()) },
59261
59436
  null,
59262
59437
  2
59263
59438
  );
59264
- fs47.mkdirSync(this.dataDir, { recursive: true });
59265
- fs47.writeFileSync(tmp, content, { mode: 384 });
59266
- fs47.renameSync(tmp, file);
59439
+ fs48.mkdirSync(this.dataDir, { recursive: true });
59440
+ fs48.writeFileSync(tmp, content, { mode: 384 });
59441
+ fs48.renameSync(tmp, file);
59267
59442
  }
59268
59443
  renameBak(file) {
59269
59444
  try {
59270
- fs47.renameSync(file, `${file}.bak`);
59445
+ fs48.renameSync(file, `${file}.bak`);
59271
59446
  } catch {
59272
59447
  }
59273
59448
  }
@@ -59375,61 +59550,61 @@ async function connectRemote(args) {
59375
59550
  }
59376
59551
 
59377
59552
  // src/migrations/2026-05-20-flatten-sessions.ts
59378
- var fs48 = __toESM(require("fs"), 1);
59379
- var path51 = __toESM(require("path"), 1);
59553
+ var fs49 = __toESM(require("fs"), 1);
59554
+ var path52 = __toESM(require("path"), 1);
59380
59555
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
59381
59556
  function migrateFlattenSessions(opts) {
59382
59557
  const dataDir = opts.dataDir;
59383
59558
  const now = opts.now ?? Date.now;
59384
- const sessionsDir = path51.join(dataDir, "sessions");
59385
- const flagPath = path51.join(sessionsDir, MIGRATION_FLAG_NAME);
59559
+ const sessionsDir = path52.join(dataDir, "sessions");
59560
+ const flagPath = path52.join(sessionsDir, MIGRATION_FLAG_NAME);
59386
59561
  if (existsSync3(flagPath)) {
59387
59562
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
59388
59563
  }
59389
59564
  let movedBare = 0;
59390
59565
  let movedVmOwner = 0;
59391
59566
  let archivedListener = 0;
59392
- const defaultDir = path51.join(sessionsDir, "default");
59567
+ const defaultDir = path52.join(sessionsDir, "default");
59393
59568
  if (existsSync3(defaultDir)) {
59394
59569
  for (const entry of readdirSafe(defaultDir)) {
59395
59570
  if (!entry.endsWith(".json")) continue;
59396
- const src = path51.join(defaultDir, entry);
59397
- const dst = path51.join(sessionsDir, entry);
59398
- fs48.renameSync(src, dst);
59571
+ const src = path52.join(defaultDir, entry);
59572
+ const dst = path52.join(sessionsDir, entry);
59573
+ fs49.renameSync(src, dst);
59399
59574
  movedBare += 1;
59400
59575
  }
59401
59576
  rmdirIfEmpty(defaultDir);
59402
59577
  }
59403
59578
  for (const pid of readdirSafe(sessionsDir)) {
59404
- const personaDir = path51.join(sessionsDir, pid);
59579
+ const personaDir = path52.join(sessionsDir, pid);
59405
59580
  if (!isDir(personaDir)) continue;
59406
59581
  if (pid === "default") continue;
59407
- const ownerSrc = path51.join(personaDir, "owner");
59582
+ const ownerSrc = path52.join(personaDir, "owner");
59408
59583
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
59409
- const ownerDst = path51.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
59410
- fs48.mkdirSync(ownerDst, { recursive: true });
59584
+ const ownerDst = path52.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
59585
+ fs49.mkdirSync(ownerDst, { recursive: true });
59411
59586
  for (const file of readdirSafe(ownerSrc)) {
59412
59587
  if (!file.endsWith(".json")) continue;
59413
- fs48.renameSync(path51.join(ownerSrc, file), path51.join(ownerDst, file));
59588
+ fs49.renameSync(path52.join(ownerSrc, file), path52.join(ownerDst, file));
59414
59589
  movedVmOwner += 1;
59415
59590
  }
59416
59591
  rmdirIfEmpty(ownerSrc);
59417
59592
  }
59418
- const listenerSrc = path51.join(personaDir, "listener");
59593
+ const listenerSrc = path52.join(personaDir, "listener");
59419
59594
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
59420
- const archiveDst = path51.join(dataDir, ".legacy", `listener-${pid}`);
59421
- fs48.mkdirSync(archiveDst, { recursive: true });
59595
+ const archiveDst = path52.join(dataDir, ".legacy", `listener-${pid}`);
59596
+ fs49.mkdirSync(archiveDst, { recursive: true });
59422
59597
  for (const file of readdirSafe(listenerSrc)) {
59423
59598
  if (!file.endsWith(".json")) continue;
59424
- fs48.renameSync(path51.join(listenerSrc, file), path51.join(archiveDst, file));
59599
+ fs49.renameSync(path52.join(listenerSrc, file), path52.join(archiveDst, file));
59425
59600
  archivedListener += 1;
59426
59601
  }
59427
59602
  rmdirIfEmpty(listenerSrc);
59428
59603
  }
59429
59604
  rmdirIfEmpty(personaDir);
59430
59605
  }
59431
- fs48.mkdirSync(sessionsDir, { recursive: true });
59432
- fs48.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
59606
+ fs49.mkdirSync(sessionsDir, { recursive: true });
59607
+ fs49.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
59433
59608
  return {
59434
59609
  skipped: false,
59435
59610
  flagWritten: true,
@@ -59440,7 +59615,7 @@ function migrateFlattenSessions(opts) {
59440
59615
  }
59441
59616
  function existsSync3(p2) {
59442
59617
  try {
59443
- fs48.statSync(p2);
59618
+ fs49.statSync(p2);
59444
59619
  return true;
59445
59620
  } catch {
59446
59621
  return false;
@@ -59448,61 +59623,61 @@ function existsSync3(p2) {
59448
59623
  }
59449
59624
  function isDir(p2) {
59450
59625
  try {
59451
- return fs48.statSync(p2).isDirectory();
59626
+ return fs49.statSync(p2).isDirectory();
59452
59627
  } catch {
59453
59628
  return false;
59454
59629
  }
59455
59630
  }
59456
59631
  function readdirSafe(p2) {
59457
59632
  try {
59458
- return fs48.readdirSync(p2);
59633
+ return fs49.readdirSync(p2);
59459
59634
  } catch {
59460
59635
  return [];
59461
59636
  }
59462
59637
  }
59463
59638
  function rmdirIfEmpty(p2) {
59464
59639
  try {
59465
- fs48.rmdirSync(p2);
59640
+ fs49.rmdirSync(p2);
59466
59641
  } catch {
59467
59642
  }
59468
59643
  }
59469
59644
 
59470
59645
  // src/migrations/2026-08-18-drop-seeded-projects.ts
59471
- var fs49 = __toESM(require("fs"), 1);
59472
- var path52 = __toESM(require("path"), 1);
59646
+ var fs50 = __toESM(require("fs"), 1);
59647
+ var path53 = __toESM(require("path"), 1);
59473
59648
  var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
59474
59649
  function dropSeededProjects(opts) {
59475
- fs49.mkdirSync(opts.dataDir, { recursive: true });
59476
- const flag = path52.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
59477
- if (fs49.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
59478
- const file = path52.join(opts.dataDir, "projects.json");
59650
+ fs50.mkdirSync(opts.dataDir, { recursive: true });
59651
+ const flag = path53.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
59652
+ if (fs50.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
59653
+ const file = path53.join(opts.dataDir, "projects.json");
59479
59654
  let raw = null;
59480
59655
  let dropped = 0;
59481
59656
  try {
59482
- raw = fs49.readFileSync(file, "utf8");
59657
+ raw = fs50.readFileSync(file, "utf8");
59483
59658
  dropped = JSON.parse(raw).projects?.length ?? 0;
59484
59659
  } catch {
59485
59660
  }
59486
59661
  let backup = null;
59487
59662
  if (raw != null && dropped > 0) {
59488
- const dir = path52.join(opts.dataDir, "backups");
59489
- fs49.mkdirSync(dir, { recursive: true });
59490
- backup = path52.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
59491
- fs49.writeFileSync(backup, raw);
59663
+ const dir = path53.join(opts.dataDir, "backups");
59664
+ fs50.mkdirSync(dir, { recursive: true });
59665
+ backup = path53.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
59666
+ fs50.writeFileSync(backup, raw);
59492
59667
  }
59493
59668
  if (raw != null || dropped > 0) {
59494
- fs49.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
59669
+ fs50.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
59495
59670
  }
59496
- fs49.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
59671
+ fs50.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
59497
59672
  return { skipped: false, dropped, backup };
59498
59673
  }
59499
59674
 
59500
59675
  // src/transport/http-router.ts
59501
- var import_node_fs36 = __toESM(require("fs"), 1);
59502
- var import_node_path44 = __toESM(require("path"), 1);
59676
+ var import_node_fs37 = __toESM(require("fs"), 1);
59677
+ var import_node_path45 = __toESM(require("path"), 1);
59503
59678
 
59504
59679
  // src/attachment/mime.ts
59505
- var import_node_path41 = __toESM(require("path"), 1);
59680
+ var import_node_path42 = __toESM(require("path"), 1);
59506
59681
  var TEXT_PLAIN = "text/plain; charset=utf-8";
59507
59682
  var EXT_TO_NATIVE_MIME = {
59508
59683
  // 图片
@@ -59609,7 +59784,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
59609
59784
  ".mk"
59610
59785
  ]);
59611
59786
  function lookupMime(filePathOrName) {
59612
- const ext = import_node_path41.default.extname(filePathOrName).toLowerCase();
59787
+ const ext = import_node_path42.default.extname(filePathOrName).toLowerCase();
59613
59788
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
59614
59789
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
59615
59790
  return "application/octet-stream";
@@ -59679,8 +59854,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
59679
59854
  }
59680
59855
 
59681
59856
  // src/attachment/upload.ts
59682
- var import_node_fs35 = __toESM(require("fs"), 1);
59683
- var import_node_path42 = __toESM(require("path"), 1);
59857
+ var import_node_fs36 = __toESM(require("fs"), 1);
59858
+ var import_node_path43 = __toESM(require("path"), 1);
59684
59859
  var import_node_crypto10 = __toESM(require("crypto"), 1);
59685
59860
  var import_promises7 = require("stream/promises");
59686
59861
  var UploadError = class extends Error {
@@ -59692,22 +59867,22 @@ var UploadError = class extends Error {
59692
59867
  code;
59693
59868
  };
59694
59869
  function assertValidFileName(fileName) {
59695
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path42.default.basename(fileName)) {
59870
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path43.default.basename(fileName)) {
59696
59871
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
59697
59872
  }
59698
59873
  }
59699
59874
  var HASH_PREFIX_LEN = 16;
59700
59875
  async function writeUploadedAttachment(args) {
59701
59876
  assertValidFileName(args.fileName);
59702
- const attachmentsRoot = import_node_path42.default.join(args.baseDir, ".attachments");
59877
+ const attachmentsRoot = import_node_path43.default.join(args.baseDir, ".attachments");
59703
59878
  try {
59704
- import_node_fs35.default.mkdirSync(attachmentsRoot, { recursive: true });
59879
+ import_node_fs36.default.mkdirSync(attachmentsRoot, { recursive: true });
59705
59880
  } catch (err) {
59706
59881
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
59707
59882
  }
59708
59883
  const hasher = import_node_crypto10.default.createHash("sha256");
59709
59884
  let actualSize = 0;
59710
- const tmpPath = import_node_path42.default.join(
59885
+ const tmpPath = import_node_path43.default.join(
59711
59886
  attachmentsRoot,
59712
59887
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto10.default.randomBytes(4).toString("hex")}`
59713
59888
  );
@@ -59722,18 +59897,18 @@ async function writeUploadedAttachment(args) {
59722
59897
  yield buf;
59723
59898
  }
59724
59899
  },
59725
- import_node_fs35.default.createWriteStream(tmpPath, { mode: 384 })
59900
+ import_node_fs36.default.createWriteStream(tmpPath, { mode: 384 })
59726
59901
  );
59727
59902
  } catch (err) {
59728
59903
  try {
59729
- import_node_fs35.default.unlinkSync(tmpPath);
59904
+ import_node_fs36.default.unlinkSync(tmpPath);
59730
59905
  } catch {
59731
59906
  }
59732
59907
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
59733
59908
  }
59734
59909
  if (actualSize !== args.contentLength) {
59735
59910
  try {
59736
- import_node_fs35.default.unlinkSync(tmpPath);
59911
+ import_node_fs36.default.unlinkSync(tmpPath);
59737
59912
  } catch {
59738
59913
  }
59739
59914
  throw new UploadError(
@@ -59742,34 +59917,34 @@ async function writeUploadedAttachment(args) {
59742
59917
  );
59743
59918
  }
59744
59919
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
59745
- const hashDir = import_node_path42.default.join(attachmentsRoot, attachmentId);
59920
+ const hashDir = import_node_path43.default.join(attachmentsRoot, attachmentId);
59746
59921
  let finalFileName;
59747
59922
  let hashDirExists = false;
59748
59923
  try {
59749
- hashDirExists = import_node_fs35.default.statSync(hashDir).isDirectory();
59924
+ hashDirExists = import_node_fs36.default.statSync(hashDir).isDirectory();
59750
59925
  } catch {
59751
59926
  }
59752
59927
  if (hashDirExists) {
59753
- const existing = import_node_fs35.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
59928
+ const existing = import_node_fs36.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
59754
59929
  finalFileName = existing[0] ?? args.fileName;
59755
59930
  try {
59756
- import_node_fs35.default.unlinkSync(tmpPath);
59931
+ import_node_fs36.default.unlinkSync(tmpPath);
59757
59932
  } catch {
59758
59933
  }
59759
59934
  } else {
59760
59935
  try {
59761
- import_node_fs35.default.mkdirSync(hashDir, { recursive: true });
59936
+ import_node_fs36.default.mkdirSync(hashDir, { recursive: true });
59762
59937
  finalFileName = args.fileName;
59763
- import_node_fs35.default.renameSync(tmpPath, import_node_path42.default.join(hashDir, finalFileName));
59938
+ import_node_fs36.default.renameSync(tmpPath, import_node_path43.default.join(hashDir, finalFileName));
59764
59939
  } catch (err) {
59765
59940
  try {
59766
- import_node_fs35.default.unlinkSync(tmpPath);
59941
+ import_node_fs36.default.unlinkSync(tmpPath);
59767
59942
  } catch {
59768
59943
  }
59769
59944
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
59770
59945
  }
59771
59946
  }
59772
- const absPath = import_node_path42.default.join(hashDir, finalFileName);
59947
+ const absPath = import_node_path43.default.join(hashDir, finalFileName);
59773
59948
  const relPath = absPath;
59774
59949
  args.groupFileStore.upsert(args.scope, args.sessionId, {
59775
59950
  relPath: absPath,
@@ -59784,8 +59959,8 @@ async function writeUploadedAttachment(args) {
59784
59959
 
59785
59960
  // src/extension/import.ts
59786
59961
  var import_promises8 = __toESM(require("fs/promises"), 1);
59787
- var import_node_path43 = __toESM(require("path"), 1);
59788
- var import_node_os13 = __toESM(require("os"), 1);
59962
+ var import_node_path44 = __toESM(require("path"), 1);
59963
+ var import_node_os14 = __toESM(require("os"), 1);
59789
59964
  var import_jszip = __toESM(require_lib3(), 1);
59790
59965
  var ImportError = class extends Error {
59791
59966
  constructor(code, message) {
@@ -59802,7 +59977,7 @@ async function importZip(buf, root) {
59802
59977
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
59803
59978
  }
59804
59979
  for (const name of Object.keys(zip.files)) {
59805
- if (name.includes("..") || name.startsWith("/") || import_node_path43.default.isAbsolute(name)) {
59980
+ if (name.includes("..") || name.startsWith("/") || import_node_path44.default.isAbsolute(name)) {
59806
59981
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
59807
59982
  }
59808
59983
  }
@@ -59835,7 +60010,7 @@ async function importZip(buf, root) {
59835
60010
  );
59836
60011
  }
59837
60012
  }
59838
- const destDir = import_node_path43.default.join(root, manifest.id);
60013
+ const destDir = import_node_path44.default.join(root, manifest.id);
59839
60014
  let destExists = false;
59840
60015
  try {
59841
60016
  await import_promises8.default.access(destDir);
@@ -59845,15 +60020,15 @@ async function importZip(buf, root) {
59845
60020
  if (destExists) {
59846
60021
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
59847
60022
  }
59848
- const stage = await import_promises8.default.mkdtemp(import_node_path43.default.join(import_node_os13.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
60023
+ const stage = await import_promises8.default.mkdtemp(import_node_path44.default.join(import_node_os14.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
59849
60024
  try {
59850
60025
  for (const [name, entry] of Object.entries(zip.files)) {
59851
- const dest = import_node_path43.default.join(stage, name);
60026
+ const dest = import_node_path44.default.join(stage, name);
59852
60027
  if (entry.dir) {
59853
60028
  await import_promises8.default.mkdir(dest, { recursive: true });
59854
60029
  continue;
59855
60030
  }
59856
- await import_promises8.default.mkdir(import_node_path43.default.dirname(dest), { recursive: true });
60031
+ await import_promises8.default.mkdir(import_node_path44.default.dirname(dest), { recursive: true });
59857
60032
  const content = await entry.async("nodebuffer");
59858
60033
  await import_promises8.default.writeFile(dest, content);
59859
60034
  }
@@ -59883,7 +60058,7 @@ var SHARE_UI_ASSET_MIME = {
59883
60058
  ".wasm": "application/wasm"
59884
60059
  };
59885
60060
  function shareUiAssetMime(filePath) {
59886
- const ext = import_node_path44.default.extname(filePath).toLowerCase();
60061
+ const ext = import_node_path45.default.extname(filePath).toLowerCase();
59887
60062
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
59888
60063
  }
59889
60064
  var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
@@ -59982,7 +60157,7 @@ function isValidUploadFileName(fileName) {
59982
60157
  if (fileName === "." || fileName === "..") return false;
59983
60158
  if (fileName.startsWith(".")) return false;
59984
60159
  if (fileName.includes("/") || fileName.includes("\\")) return false;
59985
- return fileName === import_node_path44.default.basename(fileName);
60160
+ return fileName === import_node_path45.default.basename(fileName);
59986
60161
  }
59987
60162
  function createHttpRouter(deps) {
59988
60163
  return async (req, res) => {
@@ -60070,7 +60245,7 @@ function createHttpRouter(deps) {
60070
60245
  }
60071
60246
  let buf;
60072
60247
  try {
60073
- buf = await import_node_fs36.default.promises.readFile(abs);
60248
+ buf = await import_node_fs37.default.promises.readFile(abs);
60074
60249
  } catch {
60075
60250
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
60076
60251
  return true;
@@ -60218,7 +60393,7 @@ function createHttpRouter(deps) {
60218
60393
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
60219
60394
  return true;
60220
60395
  }
60221
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path44.default.basename(r.absPath)));
60396
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path45.default.basename(r.absPath)));
60222
60397
  return true;
60223
60398
  }
60224
60399
  const ctx = deps.authResolver.resolveFromHeader(
@@ -60339,7 +60514,7 @@ function createHttpRouter(deps) {
60339
60514
  return true;
60340
60515
  }
60341
60516
  let absPath;
60342
- if (import_node_path44.default.isAbsolute(pathParam)) {
60517
+ if (import_node_path45.default.isAbsolute(pathParam)) {
60343
60518
  absPath = pathParam;
60344
60519
  } else if (deps.sessionStore) {
60345
60520
  const file = deps.sessionStore.read(sid);
@@ -60347,7 +60522,7 @@ function createHttpRouter(deps) {
60347
60522
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
60348
60523
  return true;
60349
60524
  }
60350
- absPath = import_node_path44.default.join(file.cwd, pathParam);
60525
+ absPath = import_node_path45.default.join(file.cwd, pathParam);
60351
60526
  } else {
60352
60527
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
60353
60528
  return true;
@@ -60434,7 +60609,7 @@ function withCtx(ctx, body) {
60434
60609
  function streamFile(res, absPath, logger) {
60435
60610
  let stat;
60436
60611
  try {
60437
- stat = import_node_fs36.default.statSync(absPath);
60612
+ stat = import_node_fs37.default.statSync(absPath);
60438
60613
  } catch (err) {
60439
60614
  const code = err?.code;
60440
60615
  if (code === "ENOENT") {
@@ -60449,7 +60624,7 @@ function streamFile(res, absPath, logger) {
60449
60624
  return;
60450
60625
  }
60451
60626
  const mime = lookupMime(absPath);
60452
- const basename2 = import_node_path44.default.basename(absPath);
60627
+ const basename2 = import_node_path45.default.basename(absPath);
60453
60628
  res.writeHead(200, {
60454
60629
  "Content-Type": mime,
60455
60630
  "Content-Length": String(stat.size),
@@ -60457,7 +60632,7 @@ function streamFile(res, absPath, logger) {
60457
60632
  // 防止浏览器把任意 mime 当 html 渲染
60458
60633
  "X-Content-Type-Options": "nosniff"
60459
60634
  });
60460
- const stream = import_node_fs36.default.createReadStream(absPath);
60635
+ const stream = import_node_fs37.default.createReadStream(absPath);
60461
60636
  stream.on("error", (err) => {
60462
60637
  logger?.warn("streamFile read error", { absPath, err: err.message });
60463
60638
  res.destroy();
@@ -60466,8 +60641,8 @@ function streamFile(res, absPath, logger) {
60466
60641
  }
60467
60642
 
60468
60643
  // src/attachment/gc.ts
60469
- var import_node_fs37 = __toESM(require("fs"), 1);
60470
- var import_node_path45 = __toESM(require("path"), 1);
60644
+ var import_node_fs38 = __toESM(require("fs"), 1);
60645
+ var import_node_path46 = __toESM(require("path"), 1);
60471
60646
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
60472
60647
  function runAttachmentGc(args) {
60473
60648
  const now = (args.now ?? Date.now)();
@@ -60476,12 +60651,12 @@ function runAttachmentGc(args) {
60476
60651
  for (const { scope, sessionId } of args.sessionScopes) {
60477
60652
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
60478
60653
  if (entry.stale) continue;
60479
- if (import_node_path45.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
60654
+ if (import_node_path46.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
60480
60655
  }
60481
60656
  }
60482
60657
  const visited = /* @__PURE__ */ new Set();
60483
60658
  for (const { scope, sessionId } of args.sessionScopes) {
60484
- const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path45.default.join(
60659
+ const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path46.default.join(
60485
60660
  args.dataDir,
60486
60661
  "sessions",
60487
60662
  ...scopeSubPath(scope).map(safeFileName),
@@ -60494,28 +60669,28 @@ function runAttachmentGc(args) {
60494
60669
  return true;
60495
60670
  });
60496
60671
  for (const rootDir of roots) {
60497
- const attRoot = import_node_path45.default.join(rootDir, ".attachments");
60672
+ const attRoot = import_node_path46.default.join(rootDir, ".attachments");
60498
60673
  let hashDirs;
60499
60674
  try {
60500
- hashDirs = import_node_fs37.default.readdirSync(attRoot);
60675
+ hashDirs = import_node_fs38.default.readdirSync(attRoot);
60501
60676
  } catch (err) {
60502
60677
  if (err.code === "ENOENT") continue;
60503
60678
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
60504
60679
  continue;
60505
60680
  }
60506
60681
  for (const hashDir of hashDirs) {
60507
- const hashDirAbs = import_node_path45.default.join(attRoot, hashDir);
60682
+ const hashDirAbs = import_node_path46.default.join(attRoot, hashDir);
60508
60683
  let files;
60509
60684
  try {
60510
- files = import_node_fs37.default.readdirSync(hashDirAbs);
60685
+ files = import_node_fs38.default.readdirSync(hashDirAbs);
60511
60686
  } catch {
60512
60687
  continue;
60513
60688
  }
60514
60689
  for (const name of files) {
60515
- const file = import_node_path45.default.join(hashDirAbs, name);
60690
+ const file = import_node_path46.default.join(hashDirAbs, name);
60516
60691
  let stat;
60517
60692
  try {
60518
- stat = import_node_fs37.default.statSync(file);
60693
+ stat = import_node_fs38.default.statSync(file);
60519
60694
  } catch {
60520
60695
  continue;
60521
60696
  }
@@ -60524,18 +60699,18 @@ function runAttachmentGc(args) {
60524
60699
  if (age < ttlMs) continue;
60525
60700
  if (liveAbs.has(file)) continue;
60526
60701
  try {
60527
- import_node_fs37.default.unlinkSync(file);
60702
+ import_node_fs38.default.unlinkSync(file);
60528
60703
  } catch (err) {
60529
60704
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
60530
60705
  }
60531
60706
  }
60532
60707
  try {
60533
- if (import_node_fs37.default.readdirSync(hashDirAbs).length === 0) import_node_fs37.default.rmdirSync(hashDirAbs);
60708
+ if (import_node_fs38.default.readdirSync(hashDirAbs).length === 0) import_node_fs38.default.rmdirSync(hashDirAbs);
60534
60709
  } catch {
60535
60710
  }
60536
60711
  }
60537
60712
  try {
60538
- if (import_node_fs37.default.readdirSync(attRoot).length === 0) import_node_fs37.default.rmdirSync(attRoot);
60713
+ if (import_node_fs38.default.readdirSync(attRoot).length === 0) import_node_fs38.default.rmdirSync(attRoot);
60539
60714
  } catch {
60540
60715
  }
60541
60716
  }
@@ -60543,8 +60718,8 @@ function runAttachmentGc(args) {
60543
60718
  }
60544
60719
 
60545
60720
  // src/attachment/group.ts
60546
- var import_node_fs38 = __toESM(require("fs"), 1);
60547
- var import_node_path46 = __toESM(require("path"), 1);
60721
+ var import_node_fs39 = __toESM(require("fs"), 1);
60722
+ var import_node_path47 = __toESM(require("path"), 1);
60548
60723
  var import_node_crypto11 = __toESM(require("crypto"), 1);
60549
60724
  init_protocol();
60550
60725
  var GroupFileStore = class {
@@ -60556,11 +60731,11 @@ var GroupFileStore = class {
60556
60731
  this.logger = opts.logger;
60557
60732
  }
60558
60733
  rootForScope(scope) {
60559
- return import_node_path46.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
60734
+ return import_node_path47.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
60560
60735
  }
60561
60736
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
60562
60737
  filePath(scope, sessionId) {
60563
- return import_node_path46.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
60738
+ return import_node_path47.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
60564
60739
  }
60565
60740
  cacheKey(scope, sessionId) {
60566
60741
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -60569,7 +60744,7 @@ var GroupFileStore = class {
60569
60744
  readFile(scope, sessionId) {
60570
60745
  const file = this.filePath(scope, sessionId);
60571
60746
  try {
60572
- const raw = import_node_fs38.default.readFileSync(file, "utf8");
60747
+ const raw = import_node_fs39.default.readFileSync(file, "utf8");
60573
60748
  const parsed = JSON.parse(raw);
60574
60749
  if (!Array.isArray(parsed)) {
60575
60750
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -60595,10 +60770,10 @@ var GroupFileStore = class {
60595
60770
  }
60596
60771
  writeFile(scope, sessionId, entries) {
60597
60772
  const file = this.filePath(scope, sessionId);
60598
- import_node_fs38.default.mkdirSync(import_node_path46.default.dirname(file), { recursive: true });
60773
+ import_node_fs39.default.mkdirSync(import_node_path47.default.dirname(file), { recursive: true });
60599
60774
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
60600
- import_node_fs38.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
60601
- import_node_fs38.default.renameSync(tmp, file);
60775
+ import_node_fs39.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
60776
+ import_node_fs39.default.renameSync(tmp, file);
60602
60777
  }
60603
60778
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
60604
60779
  list(scope, sessionId) {
@@ -60684,10 +60859,10 @@ var GroupFileStore = class {
60684
60859
  };
60685
60860
 
60686
60861
  // src/discovery/state-file.ts
60687
- var import_node_fs39 = __toESM(require("fs"), 1);
60688
- var import_node_path47 = __toESM(require("path"), 1);
60862
+ var import_node_fs40 = __toESM(require("fs"), 1);
60863
+ var import_node_path48 = __toESM(require("path"), 1);
60689
60864
  function defaultStateFilePath(dataDir) {
60690
- return import_node_path47.default.join(dataDir, "state.json");
60865
+ return import_node_path48.default.join(dataDir, "state.json");
60691
60866
  }
60692
60867
  function isPidAlive(pid) {
60693
60868
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -60709,7 +60884,7 @@ var StateFileManager = class {
60709
60884
  }
60710
60885
  read() {
60711
60886
  try {
60712
- const raw = import_node_fs39.default.readFileSync(this.file, "utf8");
60887
+ const raw = import_node_fs40.default.readFileSync(this.file, "utf8");
60713
60888
  const parsed = JSON.parse(raw);
60714
60889
  return parsed;
60715
60890
  } catch {
@@ -60723,20 +60898,20 @@ var StateFileManager = class {
60723
60898
  return { status: "stale", existing };
60724
60899
  }
60725
60900
  write(state) {
60726
- import_node_fs39.default.mkdirSync(import_node_path47.default.dirname(this.file), { recursive: true });
60901
+ import_node_fs40.default.mkdirSync(import_node_path48.default.dirname(this.file), { recursive: true });
60727
60902
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
60728
- import_node_fs39.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
60729
- import_node_fs39.default.renameSync(tmp, this.file);
60903
+ import_node_fs40.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
60904
+ import_node_fs40.default.renameSync(tmp, this.file);
60730
60905
  if (process.platform !== "win32") {
60731
60906
  try {
60732
- import_node_fs39.default.chmodSync(this.file, 384);
60907
+ import_node_fs40.default.chmodSync(this.file, 384);
60733
60908
  } catch {
60734
60909
  }
60735
60910
  }
60736
60911
  }
60737
60912
  delete() {
60738
60913
  try {
60739
- import_node_fs39.default.unlinkSync(this.file);
60914
+ import_node_fs40.default.unlinkSync(this.file);
60740
60915
  } catch {
60741
60916
  }
60742
60917
  }
@@ -60750,14 +60925,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
60750
60925
  }
60751
60926
 
60752
60927
  // src/tunnel/tunnel-manager.ts
60753
- var import_node_fs43 = __toESM(require("fs"), 1);
60754
- var import_node_path51 = __toESM(require("path"), 1);
60928
+ var import_node_fs44 = __toESM(require("fs"), 1);
60929
+ var import_node_path52 = __toESM(require("path"), 1);
60755
60930
  var import_node_crypto12 = __toESM(require("crypto"), 1);
60756
60931
  var import_node_child_process12 = require("child_process");
60757
60932
 
60758
60933
  // src/tunnel/tunnel-store.ts
60759
- var import_node_fs40 = __toESM(require("fs"), 1);
60760
- var import_node_path48 = __toESM(require("path"), 1);
60934
+ var import_node_fs41 = __toESM(require("fs"), 1);
60935
+ var import_node_path49 = __toESM(require("path"), 1);
60761
60936
  var TunnelStore = class {
60762
60937
  constructor(filePath) {
60763
60938
  this.filePath = filePath;
@@ -60765,7 +60940,7 @@ var TunnelStore = class {
60765
60940
  filePath;
60766
60941
  async get() {
60767
60942
  try {
60768
- const raw = await import_node_fs40.default.promises.readFile(this.filePath, "utf8");
60943
+ const raw = await import_node_fs41.default.promises.readFile(this.filePath, "utf8");
60769
60944
  const obj = JSON.parse(raw);
60770
60945
  if (!isPersistedTunnel(obj)) return null;
60771
60946
  return obj;
@@ -60776,22 +60951,22 @@ var TunnelStore = class {
60776
60951
  }
60777
60952
  }
60778
60953
  async set(v2) {
60779
- const dir = import_node_path48.default.dirname(this.filePath);
60780
- await import_node_fs40.default.promises.mkdir(dir, { recursive: true });
60954
+ const dir = import_node_path49.default.dirname(this.filePath);
60955
+ await import_node_fs41.default.promises.mkdir(dir, { recursive: true });
60781
60956
  const data = JSON.stringify(v2, null, 2);
60782
60957
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
60783
- await import_node_fs40.default.promises.writeFile(tmp, data, { mode: 384 });
60958
+ await import_node_fs41.default.promises.writeFile(tmp, data, { mode: 384 });
60784
60959
  if (process.platform !== "win32") {
60785
60960
  try {
60786
- await import_node_fs40.default.promises.chmod(tmp, 384);
60961
+ await import_node_fs41.default.promises.chmod(tmp, 384);
60787
60962
  } catch {
60788
60963
  }
60789
60964
  }
60790
- await import_node_fs40.default.promises.rename(tmp, this.filePath);
60965
+ await import_node_fs41.default.promises.rename(tmp, this.filePath);
60791
60966
  }
60792
60967
  async clear() {
60793
60968
  try {
60794
- await import_node_fs40.default.promises.unlink(this.filePath);
60969
+ await import_node_fs41.default.promises.unlink(this.filePath);
60795
60970
  } catch (err) {
60796
60971
  const code = err?.code;
60797
60972
  if (code !== "ENOENT") throw err;
@@ -60886,9 +61061,9 @@ function escape(v2) {
60886
61061
  }
60887
61062
 
60888
61063
  // src/tunnel/frpc-binary.ts
60889
- var import_node_fs41 = __toESM(require("fs"), 1);
60890
- var import_node_os14 = __toESM(require("os"), 1);
60891
- var import_node_path49 = __toESM(require("path"), 1);
61064
+ var import_node_fs42 = __toESM(require("fs"), 1);
61065
+ var import_node_os15 = __toESM(require("os"), 1);
61066
+ var import_node_path50 = __toESM(require("path"), 1);
60892
61067
  var import_node_child_process10 = require("child_process");
60893
61068
  var import_node_stream3 = require("stream");
60894
61069
  var import_promises9 = require("stream/promises");
@@ -60920,20 +61095,20 @@ function frpcDownloadUrl(version2, p2) {
60920
61095
  }
60921
61096
  async function ensureFrpcBinary(opts) {
60922
61097
  if (opts.override) {
60923
- if (!import_node_fs41.default.existsSync(opts.override)) {
61098
+ if (!import_node_fs42.default.existsSync(opts.override)) {
60924
61099
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
60925
61100
  }
60926
61101
  return opts.override;
60927
61102
  }
60928
61103
  const version2 = opts.version ?? FRPC_VERSION;
60929
61104
  const platform = opts.platform ?? detectPlatform();
60930
- const binDir = import_node_path49.default.join(opts.dataDir, "bin");
60931
- import_node_fs41.default.mkdirSync(binDir, { recursive: true });
61105
+ const binDir = import_node_path50.default.join(opts.dataDir, "bin");
61106
+ import_node_fs42.default.mkdirSync(binDir, { recursive: true });
60932
61107
  cleanupStaleArtifacts(binDir);
60933
- const stableBin = import_node_path49.default.join(binDir, "frpc");
60934
- if (import_node_fs41.default.existsSync(stableBin)) return stableBin;
61108
+ const stableBin = import_node_path50.default.join(binDir, "frpc");
61109
+ if (import_node_fs42.default.existsSync(stableBin)) return stableBin;
60935
61110
  const partialBin = `${stableBin}.partial`;
60936
- const tarballPath = import_node_path49.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
61111
+ const tarballPath = import_node_path50.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
60937
61112
  try {
60938
61113
  const url = frpcDownloadUrl(version2, platform);
60939
61114
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -60942,8 +61117,8 @@ async function ensureFrpcBinary(opts) {
60942
61117
  } else {
60943
61118
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
60944
61119
  }
60945
- import_node_fs41.default.chmodSync(partialBin, 493);
60946
- import_node_fs41.default.renameSync(partialBin, stableBin);
61120
+ import_node_fs42.default.chmodSync(partialBin, 493);
61121
+ import_node_fs42.default.renameSync(partialBin, stableBin);
60947
61122
  } finally {
60948
61123
  safeUnlink(tarballPath);
60949
61124
  safeUnlink(partialBin);
@@ -60953,15 +61128,15 @@ async function ensureFrpcBinary(opts) {
60953
61128
  function cleanupStaleArtifacts(binDir) {
60954
61129
  let entries;
60955
61130
  try {
60956
- entries = import_node_fs41.default.readdirSync(binDir);
61131
+ entries = import_node_fs42.default.readdirSync(binDir);
60957
61132
  } catch {
60958
61133
  return;
60959
61134
  }
60960
61135
  for (const name of entries) {
60961
61136
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
60962
- const full = import_node_path49.default.join(binDir, name);
61137
+ const full = import_node_path50.default.join(binDir, name);
60963
61138
  try {
60964
- import_node_fs41.default.rmSync(full, { recursive: true, force: true });
61139
+ import_node_fs42.default.rmSync(full, { recursive: true, force: true });
60965
61140
  } catch {
60966
61141
  }
60967
61142
  }
@@ -60969,7 +61144,7 @@ function cleanupStaleArtifacts(binDir) {
60969
61144
  }
60970
61145
  function safeUnlink(p2) {
60971
61146
  try {
60972
- import_node_fs41.default.unlinkSync(p2);
61147
+ import_node_fs42.default.unlinkSync(p2);
60973
61148
  } catch {
60974
61149
  }
60975
61150
  }
@@ -60980,13 +61155,13 @@ async function downloadToFile(url, dest, fetchImpl) {
60980
61155
  if (!res.ok || !res.body) {
60981
61156
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
60982
61157
  }
60983
- const out = import_node_fs41.default.createWriteStream(dest);
61158
+ const out = import_node_fs42.default.createWriteStream(dest);
60984
61159
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
60985
61160
  await (0, import_promises9.pipeline)(nodeStream, out);
60986
61161
  }
60987
61162
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
60988
- const work = import_node_path49.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
60989
- import_node_fs41.default.mkdirSync(work, { recursive: true });
61163
+ const work = import_node_path50.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
61164
+ import_node_fs42.default.mkdirSync(work, { recursive: true });
60990
61165
  try {
60991
61166
  await new Promise((resolve9, reject) => {
60992
61167
  const proc = (0, import_node_child_process10.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -60994,32 +61169,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
60994
61169
  proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
60995
61170
  });
60996
61171
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
60997
- const src = import_node_path49.default.join(work, dirName, "frpc");
60998
- if (!import_node_fs41.default.existsSync(src)) {
61172
+ const src = import_node_path50.default.join(work, dirName, "frpc");
61173
+ if (!import_node_fs42.default.existsSync(src)) {
60999
61174
  throw new Error(`frpc not found inside tarball at ${src}`);
61000
61175
  }
61001
- import_node_fs41.default.copyFileSync(src, destBin);
61176
+ import_node_fs42.default.copyFileSync(src, destBin);
61002
61177
  } finally {
61003
- import_node_fs41.default.rmSync(work, { recursive: true, force: true });
61178
+ import_node_fs42.default.rmSync(work, { recursive: true, force: true });
61004
61179
  }
61005
61180
  }
61006
61181
 
61007
61182
  // src/tunnel/frpc-process.ts
61008
- var import_node_fs42 = __toESM(require("fs"), 1);
61009
- var import_node_path50 = __toESM(require("path"), 1);
61183
+ var import_node_fs43 = __toESM(require("fs"), 1);
61184
+ var import_node_path51 = __toESM(require("path"), 1);
61010
61185
  var import_node_child_process11 = require("child_process");
61011
61186
  function frpcPidFilePath(dataDir) {
61012
- return import_node_path50.default.join(dataDir, "frpc.pid");
61187
+ return import_node_path51.default.join(dataDir, "frpc.pid");
61013
61188
  }
61014
61189
  function writeFrpcPid(dataDir, pid) {
61015
61190
  try {
61016
- import_node_fs42.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
61191
+ import_node_fs43.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
61017
61192
  } catch {
61018
61193
  }
61019
61194
  }
61020
61195
  function clearFrpcPid(dataDir) {
61021
61196
  try {
61022
- import_node_fs42.default.unlinkSync(frpcPidFilePath(dataDir));
61197
+ import_node_fs43.default.unlinkSync(frpcPidFilePath(dataDir));
61023
61198
  } catch {
61024
61199
  }
61025
61200
  }
@@ -61035,7 +61210,7 @@ function defaultIsPidAlive(pid) {
61035
61210
  }
61036
61211
  function defaultReadPidFile(file) {
61037
61212
  try {
61038
- return import_node_fs42.default.readFileSync(file, "utf8");
61213
+ return import_node_fs43.default.readFileSync(file, "utf8");
61039
61214
  } catch {
61040
61215
  return null;
61041
61216
  }
@@ -61051,7 +61226,7 @@ function defaultSleep2(ms) {
61051
61226
  }
61052
61227
  async function killStaleFrpc(deps) {
61053
61228
  const pidFile = frpcPidFilePath(deps.dataDir);
61054
- const tomlPath = import_node_path50.default.join(deps.dataDir, "frpc.toml");
61229
+ const tomlPath = import_node_path51.default.join(deps.dataDir, "frpc.toml");
61055
61230
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
61056
61231
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
61057
61232
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -61075,7 +61250,7 @@ async function killStaleFrpc(deps) {
61075
61250
  }
61076
61251
  if (victims.size === 0) {
61077
61252
  try {
61078
- import_node_fs42.default.unlinkSync(pidFile);
61253
+ import_node_fs43.default.unlinkSync(pidFile);
61079
61254
  } catch {
61080
61255
  }
61081
61256
  return;
@@ -61086,7 +61261,7 @@ async function killStaleFrpc(deps) {
61086
61261
  }
61087
61262
  await sleep2(deps.reapWaitMs ?? 300);
61088
61263
  try {
61089
- import_node_fs42.default.unlinkSync(pidFile);
61264
+ import_node_fs43.default.unlinkSync(pidFile);
61090
61265
  } catch {
61091
61266
  }
61092
61267
  }
@@ -61123,7 +61298,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
61123
61298
  var TunnelManager = class {
61124
61299
  constructor(deps) {
61125
61300
  this.deps = deps;
61126
- this.store = deps.store ?? new TunnelStore(import_node_path51.default.join(deps.dataDir, "tunnel.json"));
61301
+ this.store = deps.store ?? new TunnelStore(import_node_path52.default.join(deps.dataDir, "tunnel.json"));
61127
61302
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
61128
61303
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
61129
61304
  }
@@ -61250,7 +61425,7 @@ var TunnelManager = class {
61250
61425
  dataDir: this.deps.dataDir,
61251
61426
  override: this.deps.frpcBinaryOverride ?? void 0
61252
61427
  });
61253
- const tomlPath = import_node_path51.default.join(this.deps.dataDir, "frpc.toml");
61428
+ const tomlPath = import_node_path52.default.join(this.deps.dataDir, "frpc.toml");
61254
61429
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto12.default.randomBytes(3).toString("hex")}`;
61255
61430
  const toml = buildFrpcToml({
61256
61431
  serverAddr: t.frpsHost,
@@ -61261,14 +61436,14 @@ var TunnelManager = class {
61261
61436
  localPort,
61262
61437
  logLevel: "info"
61263
61438
  });
61264
- await import_node_fs43.default.promises.writeFile(tomlPath, toml, { mode: 384 });
61439
+ await import_node_fs44.default.promises.writeFile(tomlPath, toml, { mode: 384 });
61265
61440
  const proc = (this.deps.spawnImpl ?? import_node_child_process12.spawn)(frpcBin, ["-c", tomlPath], {
61266
61441
  stdio: ["ignore", "pipe", "pipe"]
61267
61442
  });
61268
- const logDir = import_node_path51.default.join(this.deps.dataDir, "log");
61269
- import_node_fs43.default.mkdirSync(logDir, { recursive: true });
61270
- const logFilePath = import_node_path51.default.join(logDir, "frpc.log");
61271
- const logStream = import_node_fs43.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
61443
+ const logDir = import_node_path52.default.join(this.deps.dataDir, "log");
61444
+ import_node_fs44.default.mkdirSync(logDir, { recursive: true });
61445
+ const logFilePath = import_node_path52.default.join(logDir, "frpc.log");
61446
+ const logStream = import_node_fs44.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
61272
61447
  logStream.on("error", () => {
61273
61448
  });
61274
61449
  const tee = (chunk) => {
@@ -61350,28 +61525,28 @@ async function waitForFrpcReady(proc, timeoutMs) {
61350
61525
  }
61351
61526
 
61352
61527
  // src/tunnel/device-key.ts
61353
- var import_node_os15 = __toESM(require("os"), 1);
61354
- var import_node_path52 = __toESM(require("path"), 1);
61528
+ var import_node_os16 = __toESM(require("os"), 1);
61529
+ var import_node_path53 = __toESM(require("path"), 1);
61355
61530
  var import_node_crypto13 = __toESM(require("crypto"), 1);
61356
61531
  var DERIVE_SALT = "clawd-tunnel-device-v1";
61357
61532
  function deriveStableDeviceKey(opts = {}) {
61358
- const hostname = opts.hostname ?? import_node_os15.default.hostname();
61359
- const uid = opts.uid ?? (typeof import_node_os15.default.userInfo === "function" ? import_node_os15.default.userInfo().uid : 0);
61360
- const home = opts.home ?? import_node_os15.default.homedir();
61361
- const defaultDataDir = import_node_path52.default.resolve(import_node_path52.default.join(home, ".clawd"));
61362
- const normalizedDataDir = opts.dataDir ? import_node_path52.default.resolve(opts.dataDir) : null;
61533
+ const hostname = opts.hostname ?? import_node_os16.default.hostname();
61534
+ const uid = opts.uid ?? (typeof import_node_os16.default.userInfo === "function" ? import_node_os16.default.userInfo().uid : 0);
61535
+ const home = opts.home ?? import_node_os16.default.homedir();
61536
+ const defaultDataDir = import_node_path53.default.resolve(import_node_path53.default.join(home, ".clawd"));
61537
+ const normalizedDataDir = opts.dataDir ? import_node_path53.default.resolve(opts.dataDir) : null;
61363
61538
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
61364
61539
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
61365
61540
  return import_node_crypto13.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
61366
61541
  }
61367
61542
 
61368
61543
  // src/auth-store.ts
61369
- var import_node_fs44 = __toESM(require("fs"), 1);
61370
- var import_node_path53 = __toESM(require("path"), 1);
61544
+ var import_node_fs45 = __toESM(require("fs"), 1);
61545
+ var import_node_path54 = __toESM(require("path"), 1);
61371
61546
  var import_node_crypto14 = __toESM(require("crypto"), 1);
61372
61547
  var AUTH_FILE_NAME = "auth.json";
61373
61548
  function authFilePath(dataDir) {
61374
- return import_node_path53.default.join(dataDir, AUTH_FILE_NAME);
61549
+ return import_node_path54.default.join(dataDir, AUTH_FILE_NAME);
61375
61550
  }
61376
61551
  function loadOrCreateAuthFile(opts) {
61377
61552
  const file = authFilePath(opts.dataDir);
@@ -61403,7 +61578,7 @@ function defaultGenerateOwnerPrincipalId() {
61403
61578
  }
61404
61579
  function readAuthFile(file) {
61405
61580
  try {
61406
- const raw = import_node_fs44.default.readFileSync(file, "utf8");
61581
+ const raw = import_node_fs45.default.readFileSync(file, "utf8");
61407
61582
  const parsed = JSON.parse(raw);
61408
61583
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
61409
61584
  return null;
@@ -61423,26 +61598,26 @@ function readAuthFile(file) {
61423
61598
  }
61424
61599
  }
61425
61600
  function writeAuthFile(file, content) {
61426
- import_node_fs44.default.mkdirSync(import_node_path53.default.dirname(file), { recursive: true });
61427
- import_node_fs44.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
61601
+ import_node_fs45.default.mkdirSync(import_node_path54.default.dirname(file), { recursive: true });
61602
+ import_node_fs45.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
61428
61603
  try {
61429
- import_node_fs44.default.chmodSync(file, 384);
61604
+ import_node_fs45.default.chmodSync(file, 384);
61430
61605
  } catch {
61431
61606
  }
61432
61607
  }
61433
61608
 
61434
61609
  // src/owner-profile.ts
61435
- var import_node_fs45 = __toESM(require("fs"), 1);
61436
- var import_node_os16 = __toESM(require("os"), 1);
61437
- var import_node_path54 = __toESM(require("path"), 1);
61610
+ var import_node_fs46 = __toESM(require("fs"), 1);
61611
+ var import_node_os17 = __toESM(require("os"), 1);
61612
+ var import_node_path55 = __toESM(require("path"), 1);
61438
61613
  var PROFILE_FILENAME = "profile.json";
61439
61614
  function profilePath(dataDir) {
61440
- return import_node_path54.default.join(dataDir, PROFILE_FILENAME);
61615
+ return import_node_path55.default.join(dataDir, PROFILE_FILENAME);
61441
61616
  }
61442
61617
  function loadOwnerProfile(dataDir) {
61443
61618
  let raw;
61444
61619
  try {
61445
- raw = import_node_fs45.default.readFileSync(profilePath(dataDir), "utf8");
61620
+ raw = import_node_fs46.default.readFileSync(profilePath(dataDir), "utf8");
61446
61621
  } catch {
61447
61622
  return {};
61448
61623
  }
@@ -61458,11 +61633,11 @@ function loadOwnerProfile(dataDir) {
61458
61633
  }
61459
61634
  function patchOwnerProfile(dataDir, patch) {
61460
61635
  const merged = { ...loadOwnerProfile(dataDir), ...patch };
61461
- import_node_fs45.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
61636
+ import_node_fs46.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
61462
61637
  return merged;
61463
61638
  }
61464
61639
  function loadOwnerDisplayName(dataDir) {
61465
- const fallback = import_node_os16.default.userInfo().username;
61640
+ const fallback = import_node_os17.default.userInfo().username;
61466
61641
  const displayName = loadOwnerProfile(dataDir).displayName;
61467
61642
  if (typeof displayName !== "string" || displayName.length === 0) {
61468
61643
  if (displayName !== void 0) {
@@ -61474,18 +61649,18 @@ function loadOwnerDisplayName(dataDir) {
61474
61649
  }
61475
61650
 
61476
61651
  // src/feishu-auth/owner-identity-store.ts
61477
- var import_node_fs46 = __toESM(require("fs"), 1);
61478
- var import_node_path55 = __toESM(require("path"), 1);
61652
+ var import_node_fs47 = __toESM(require("fs"), 1);
61653
+ var import_node_path56 = __toESM(require("path"), 1);
61479
61654
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
61480
61655
  var OwnerIdentityStore = class {
61481
61656
  file;
61482
61657
  constructor(dataDir) {
61483
- this.file = import_node_path55.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
61658
+ this.file = import_node_path56.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
61484
61659
  }
61485
61660
  read() {
61486
61661
  let raw;
61487
61662
  try {
61488
- raw = import_node_fs46.default.readFileSync(this.file, "utf8");
61663
+ raw = import_node_fs47.default.readFileSync(this.file, "utf8");
61489
61664
  } catch {
61490
61665
  return null;
61491
61666
  }
@@ -61513,16 +61688,16 @@ var OwnerIdentityStore = class {
61513
61688
  };
61514
61689
  }
61515
61690
  write(record3) {
61516
- import_node_fs46.default.mkdirSync(import_node_path55.default.dirname(this.file), { recursive: true });
61517
- import_node_fs46.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
61691
+ import_node_fs47.default.mkdirSync(import_node_path56.default.dirname(this.file), { recursive: true });
61692
+ import_node_fs47.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
61518
61693
  try {
61519
- import_node_fs46.default.chmodSync(this.file, 384);
61694
+ import_node_fs47.default.chmodSync(this.file, 384);
61520
61695
  } catch {
61521
61696
  }
61522
61697
  }
61523
61698
  clear() {
61524
61699
  try {
61525
- import_node_fs46.default.unlinkSync(this.file);
61700
+ import_node_fs47.default.unlinkSync(this.file);
61526
61701
  } catch (err) {
61527
61702
  const code = err?.code;
61528
61703
  if (code !== "ENOENT") throw err;
@@ -61659,9 +61834,9 @@ var CentralClientError = class extends Error {
61659
61834
  code;
61660
61835
  cause;
61661
61836
  };
61662
- async function centralRequest(opts, path97, init) {
61837
+ async function centralRequest(opts, path98, init) {
61663
61838
  const f = opts.fetchImpl ?? globalThis.fetch;
61664
- const url = `${opts.api.replace(/\/+$/, "")}${path97}`;
61839
+ const url = `${opts.api.replace(/\/+$/, "")}${path98}`;
61665
61840
  const ctrl = new AbortController();
61666
61841
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
61667
61842
  let res;
@@ -62132,8 +62307,8 @@ function verifyConnectToken(args) {
62132
62307
  }
62133
62308
 
62134
62309
  // src/feishu-auth/server-key.ts
62135
- var fs63 = __toESM(require("fs"), 1);
62136
- var path68 = __toESM(require("path"), 1);
62310
+ var fs64 = __toESM(require("fs"), 1);
62311
+ var path69 = __toESM(require("path"), 1);
62137
62312
  var FILE_NAME2 = "server-signing-key.json";
62138
62313
  var ServerKeyStore = class {
62139
62314
  constructor(dataDir) {
@@ -62141,12 +62316,12 @@ var ServerKeyStore = class {
62141
62316
  }
62142
62317
  dataDir;
62143
62318
  filePath() {
62144
- return path68.join(this.dataDir, FILE_NAME2);
62319
+ return path69.join(this.dataDir, FILE_NAME2);
62145
62320
  }
62146
62321
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
62147
62322
  read() {
62148
62323
  try {
62149
- const raw = fs63.readFileSync(this.filePath(), "utf8");
62324
+ const raw = fs64.readFileSync(this.filePath(), "utf8");
62150
62325
  const parsed = JSON.parse(raw);
62151
62326
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
62152
62327
  return parsed.publicKeyPem;
@@ -62161,12 +62336,12 @@ var ServerKeyStore = class {
62161
62336
  publicKeyPem,
62162
62337
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
62163
62338
  };
62164
- fs63.mkdirSync(this.dataDir, { recursive: true });
62165
- fs63.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
62339
+ fs64.mkdirSync(this.dataDir, { recursive: true });
62340
+ fs64.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
62166
62341
  }
62167
62342
  clear() {
62168
62343
  try {
62169
- fs63.unlinkSync(this.filePath());
62344
+ fs64.unlinkSync(this.filePath());
62170
62345
  } catch {
62171
62346
  }
62172
62347
  }
@@ -62176,19 +62351,19 @@ var ServerKeyStore = class {
62176
62351
  init_protocol();
62177
62352
 
62178
62353
  // src/handlers/index.ts
62179
- var import_node_path71 = __toESM(require("path"), 1);
62354
+ var import_node_path72 = __toESM(require("path"), 1);
62180
62355
 
62181
62356
  // src/handlers/session.ts
62182
62357
  init_protocol();
62183
62358
 
62184
62359
  // src/session/fork.ts
62185
- var import_node_fs47 = __toESM(require("fs"), 1);
62186
- var import_node_os17 = __toESM(require("os"), 1);
62187
- var import_node_path56 = __toESM(require("path"), 1);
62360
+ var import_node_fs48 = __toESM(require("fs"), 1);
62361
+ var import_node_os18 = __toESM(require("os"), 1);
62362
+ var import_node_path57 = __toESM(require("path"), 1);
62188
62363
  var import_node_crypto16 = require("crypto");
62189
62364
  init_claude_history();
62190
62365
  function readJsonlEntries(file) {
62191
- const raw = import_node_fs47.default.readFileSync(file, "utf8");
62366
+ const raw = import_node_fs48.default.readFileSync(file, "utf8");
62192
62367
  const out = [];
62193
62368
  for (const line of raw.split("\n")) {
62194
62369
  const t = line.trim();
@@ -62201,19 +62376,19 @@ function readJsonlEntries(file) {
62201
62376
  return out;
62202
62377
  }
62203
62378
  function forkSession(input) {
62204
- const baseDir = input.baseDir ?? import_node_path56.default.join(import_node_os17.default.homedir(), ".claude");
62205
- let projectDir = import_node_path56.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
62206
- let sourceFile = import_node_path56.default.join(projectDir, `${input.toolSessionId}.jsonl`);
62207
- if (!import_node_fs47.default.existsSync(sourceFile)) {
62379
+ const baseDir = input.baseDir ?? import_node_path57.default.join(import_node_os18.default.homedir(), ".claude");
62380
+ let projectDir = import_node_path57.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
62381
+ let sourceFile = import_node_path57.default.join(projectDir, `${input.toolSessionId}.jsonl`);
62382
+ if (!import_node_fs48.default.existsSync(sourceFile)) {
62208
62383
  const found = findTranscriptByToolSessionId(
62209
- import_node_path56.default.join(baseDir, "projects"),
62384
+ import_node_path57.default.join(baseDir, "projects"),
62210
62385
  input.toolSessionId
62211
62386
  );
62212
62387
  if (!found) {
62213
62388
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
62214
62389
  }
62215
62390
  sourceFile = found;
62216
- projectDir = import_node_path56.default.dirname(found);
62391
+ projectDir = import_node_path57.default.dirname(found);
62217
62392
  }
62218
62393
  const entries = readJsonlEntries(sourceFile);
62219
62394
  const mainEntries = entries.filter((e) => e.isSidechain !== true);
@@ -62242,27 +62417,27 @@ function forkSession(input) {
62242
62417
  }
62243
62418
  forkedLines.push(JSON.stringify(forked));
62244
62419
  }
62245
- const outDir = input.targetCwd ? import_node_path56.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
62246
- const forkedFilePath = import_node_path56.default.join(outDir, `${forkedToolSessionId}.jsonl`);
62247
- import_node_fs47.default.mkdirSync(outDir, { recursive: true });
62248
- import_node_fs47.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
62420
+ const outDir = input.targetCwd ? import_node_path57.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
62421
+ const forkedFilePath = import_node_path57.default.join(outDir, `${forkedToolSessionId}.jsonl`);
62422
+ import_node_fs48.default.mkdirSync(outDir, { recursive: true });
62423
+ import_node_fs48.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
62249
62424
  return { forkedToolSessionId, forkedFilePath };
62250
62425
  }
62251
62426
 
62252
62427
  // src/session/external-scan.ts
62253
- var import_node_fs48 = __toESM(require("fs"), 1);
62428
+ var import_node_fs49 = __toESM(require("fs"), 1);
62254
62429
  var import_promises10 = __toESM(require("fs/promises"), 1);
62255
- var import_node_os18 = __toESM(require("os"), 1);
62256
- var import_node_path57 = __toESM(require("path"), 1);
62430
+ var import_node_os19 = __toESM(require("os"), 1);
62431
+ var import_node_path58 = __toESM(require("path"), 1);
62257
62432
  var import_node_module = require("module");
62258
62433
  var import_node_child_process13 = require("child_process");
62259
62434
  var import_meta5 = {};
62260
62435
  function defaultRoots() {
62261
- const home = import_node_os18.default.homedir();
62436
+ const home = import_node_os19.default.homedir();
62262
62437
  return {
62263
- claudeProjectsDir: import_node_path57.default.join(home, ".claude", "projects"),
62264
- codexDir: import_node_path57.default.join(home, ".codex"),
62265
- clawdDir: import_node_path57.default.join(home, ".clawd")
62438
+ claudeProjectsDir: import_node_path58.default.join(home, ".claude", "projects"),
62439
+ codexDir: import_node_path58.default.join(home, ".codex"),
62440
+ clawdDir: import_node_path58.default.join(home, ".clawd")
62266
62441
  };
62267
62442
  }
62268
62443
  function width(s) {
@@ -62313,7 +62488,7 @@ function userText(msg) {
62313
62488
  }
62314
62489
  function isDir2(p2) {
62315
62490
  try {
62316
- return import_node_fs48.default.statSync(p2).isDirectory();
62491
+ return import_node_fs49.default.statSync(p2).isDirectory();
62317
62492
  } catch {
62318
62493
  return false;
62319
62494
  }
@@ -62322,7 +62497,7 @@ async function scanClaude(roots) {
62322
62497
  const out = [];
62323
62498
  let dirs;
62324
62499
  try {
62325
- dirs = import_node_fs48.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
62500
+ dirs = import_node_fs49.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
62326
62501
  } catch {
62327
62502
  return out;
62328
62503
  }
@@ -62330,16 +62505,16 @@ async function scanClaude(roots) {
62330
62505
  if (!d.isDirectory()) continue;
62331
62506
  let files;
62332
62507
  try {
62333
- files = import_node_fs48.default.readdirSync(import_node_path57.default.join(roots.claudeProjectsDir, d.name));
62508
+ files = import_node_fs49.default.readdirSync(import_node_path58.default.join(roots.claudeProjectsDir, d.name));
62334
62509
  } catch {
62335
62510
  continue;
62336
62511
  }
62337
62512
  for (const name of files) {
62338
62513
  if (!name.endsWith(".jsonl")) continue;
62339
- const file = import_node_path57.default.join(roots.claudeProjectsDir, d.name, name);
62514
+ const file = import_node_path58.default.join(roots.claudeProjectsDir, d.name, name);
62340
62515
  let st;
62341
62516
  try {
62342
- st = import_node_fs48.default.statSync(file);
62517
+ st = import_node_fs49.default.statSync(file);
62343
62518
  } catch {
62344
62519
  continue;
62345
62520
  }
@@ -62392,7 +62567,7 @@ async function scanClaude(roots) {
62392
62567
  return out;
62393
62568
  }
62394
62569
  async function countCodexTurns(rolloutPath) {
62395
- if (!rolloutPath || !import_node_fs48.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
62570
+ if (!rolloutPath || !import_node_fs49.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
62396
62571
  let turns = 0;
62397
62572
  let first = "";
62398
62573
  for await (const rec4 of jsonLines(rolloutPath)) {
@@ -62466,7 +62641,7 @@ async function codexFromRows(rows) {
62466
62641
  async function scanCodex(roots) {
62467
62642
  let dbs = [];
62468
62643
  try {
62469
- dbs = import_node_fs48.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path57.default.join(roots.codexDir, n));
62644
+ dbs = import_node_fs49.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path58.default.join(roots.codexDir, n));
62470
62645
  } catch {
62471
62646
  }
62472
62647
  if (!dbs.length) return [];
@@ -62475,14 +62650,14 @@ async function scanCodex(roots) {
62475
62650
  }
62476
62651
  async function scanExternalSessions(rootsIn) {
62477
62652
  const roots = { ...defaultRoots(), ...rootsIn };
62478
- const personaRoot = import_node_path57.default.join(roots.clawdDir, "personas");
62653
+ const personaRoot = import_node_path58.default.join(roots.clawdDir, "personas");
62479
62654
  const all = [...await scanClaude(roots), ...await scanCodex(roots)];
62480
62655
  const out = [];
62481
62656
  for (const c of all) {
62482
62657
  if (c.skip) continue;
62483
62658
  if (c.turns < 1) continue;
62484
62659
  if (!c.cwd || !isDir2(c.cwd)) continue;
62485
- if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path57.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path57.default.sep)) {
62660
+ if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path58.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path58.default.sep)) {
62486
62661
  continue;
62487
62662
  }
62488
62663
  out.push({
@@ -62499,13 +62674,13 @@ async function scanExternalSessions(rootsIn) {
62499
62674
  }
62500
62675
 
62501
62676
  // src/session/import-ledger.ts
62502
- var import_node_fs49 = __toESM(require("fs"), 1);
62503
- var import_node_path58 = __toESM(require("path"), 1);
62677
+ var import_node_fs50 = __toESM(require("fs"), 1);
62678
+ var import_node_path59 = __toESM(require("path"), 1);
62504
62679
  var LEDGER_FILENAME = "session-import-ledger.json";
62505
62680
  function readImportLedger(dataDir) {
62506
62681
  try {
62507
62682
  const parsed = JSON.parse(
62508
- import_node_fs49.default.readFileSync(import_node_path58.default.join(dataDir, LEDGER_FILENAME), "utf8")
62683
+ import_node_fs50.default.readFileSync(import_node_path59.default.join(dataDir, LEDGER_FILENAME), "utf8")
62509
62684
  );
62510
62685
  return Array.isArray(parsed) ? parsed : [];
62511
62686
  } catch {
@@ -62513,26 +62688,26 @@ function readImportLedger(dataDir) {
62513
62688
  }
62514
62689
  }
62515
62690
  function appendImportLedger(dataDir, entry) {
62516
- const file = import_node_path58.default.join(dataDir, LEDGER_FILENAME);
62691
+ const file = import_node_path59.default.join(dataDir, LEDGER_FILENAME);
62517
62692
  const entries = readImportLedger(dataDir);
62518
62693
  entries.push(entry);
62519
- import_node_fs49.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
62694
+ import_node_fs50.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
62520
62695
  }
62521
62696
 
62522
62697
  // src/tools/transcript-search.ts
62523
- var import_node_fs50 = __toESM(require("fs"), 1);
62524
- var import_node_path59 = __toESM(require("path"), 1);
62698
+ var import_node_fs51 = __toESM(require("fs"), 1);
62699
+ var import_node_path60 = __toESM(require("path"), 1);
62525
62700
  var SNIPPET_PAD = 60;
62526
62701
  var INJECTED_ENVELOPE_RE = /^<(system-reminder|command-name|command-message|command-args|local-command-stdout|local-command-stderr|task-notification|user-prompt-submit-hook|environment_context|user_instructions)\b/;
62527
62702
  var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
62528
- function asRecord(v2) {
62703
+ function asRecord2(v2) {
62529
62704
  return typeof v2 === "object" && v2 !== null ? v2 : null;
62530
62705
  }
62531
62706
  function textOfBlocks(content, types) {
62532
62707
  if (!Array.isArray(content)) return null;
62533
62708
  const parts = [];
62534
62709
  for (const block of content) {
62535
- const b2 = asRecord(block);
62710
+ const b2 = asRecord2(block);
62536
62711
  if (!b2 || typeof b2.type !== "string" || !types.includes(b2.type)) continue;
62537
62712
  const text = b2.text;
62538
62713
  if (typeof text === "string" && text !== "") parts.push(text);
@@ -62540,10 +62715,10 @@ function textOfBlocks(content, types) {
62540
62715
  return parts.length > 0 ? parts.join("\n") : null;
62541
62716
  }
62542
62717
  function lineToSearchableText(raw) {
62543
- const line = asRecord(raw);
62718
+ const line = asRecord2(raw);
62544
62719
  if (!line) return null;
62545
62720
  if (line.type === "response_item") {
62546
- const payload = asRecord(line.payload);
62721
+ const payload = asRecord2(line.payload);
62547
62722
  if (!payload || payload.type !== "message") return null;
62548
62723
  const role = payload.role;
62549
62724
  if (role !== "user" && role !== "assistant") return null;
@@ -62555,7 +62730,7 @@ function lineToSearchableText(raw) {
62555
62730
  return INJECTED_ENVELOPE_RE.test(stripped) ? null : stripped;
62556
62731
  }
62557
62732
  if (line.type !== "user" && line.type !== "assistant") return null;
62558
- const message = asRecord(line.message);
62733
+ const message = asRecord2(line.message);
62559
62734
  if (!message) return null;
62560
62735
  const content = message.content;
62561
62736
  const text = typeof content === "string" && content !== "" ? content : textOfBlocks(content, ["text"]);
@@ -62576,7 +62751,7 @@ function makeSnippet(text, at2, needleLength) {
62576
62751
  function searchTranscriptFile(file, query) {
62577
62752
  let buf;
62578
62753
  try {
62579
- buf = import_node_fs50.default.readFileSync(file);
62754
+ buf = import_node_fs51.default.readFileSync(file);
62580
62755
  } catch {
62581
62756
  return null;
62582
62757
  }
@@ -62609,12 +62784,12 @@ function createCodexRolloutLocator(roots) {
62609
62784
  const walk2 = (dir, into) => {
62610
62785
  let entries;
62611
62786
  try {
62612
- entries = import_node_fs50.default.readdirSync(dir, { withFileTypes: true });
62787
+ entries = import_node_fs51.default.readdirSync(dir, { withFileTypes: true });
62613
62788
  } catch {
62614
62789
  return;
62615
62790
  }
62616
62791
  for (const entry of entries) {
62617
- const full = import_node_path59.default.join(dir, entry.name);
62792
+ const full = import_node_path60.default.join(dir, entry.name);
62618
62793
  if (entry.isDirectory()) {
62619
62794
  walk2(full, into);
62620
62795
  continue;
@@ -62634,16 +62809,16 @@ function createCodexRolloutLocator(roots) {
62634
62809
 
62635
62810
  // src/handlers/session.ts
62636
62811
  init_protocol();
62637
- var import_node_os19 = __toESM(require("os"), 1);
62638
- var import_node_path60 = __toESM(require("path"), 1);
62812
+ var import_node_os20 = __toESM(require("os"), 1);
62813
+ var import_node_path61 = __toESM(require("path"), 1);
62639
62814
  function canReadSearchHit(ctx, file) {
62640
62815
  if (!ctx || ctx.principal.kind === "owner") return true;
62641
62816
  return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
62642
62817
  }
62643
62818
  var DEFAULT_SEARCH_LIMIT = 9;
62644
62819
  function codexRolloutRoots(dataDir) {
62645
- const roots = [import_node_path60.default.join(import_node_os19.default.homedir(), ".codex", "sessions")];
62646
- if (dataDir) roots.push(import_node_path60.default.join(dataDir, "codex-home", "sessions"));
62820
+ const roots = [import_node_path61.default.join(import_node_os20.default.homedir(), ".codex", "sessions")];
62821
+ if (dataDir) roots.push(import_node_path61.default.join(dataDir, "codex-home", "sessions"));
62647
62822
  return roots;
62648
62823
  }
62649
62824
  function buildSessionHandlers(deps) {
@@ -63192,7 +63367,7 @@ function buildPermissionHandlers(deps) {
63192
63367
  }
63193
63368
 
63194
63369
  // src/handlers/history.ts
63195
- var path75 = __toESM(require("path"), 1);
63370
+ var path76 = __toESM(require("path"), 1);
63196
63371
  init_protocol();
63197
63372
 
63198
63373
  // src/session/recent-dirs.ts
@@ -63210,7 +63385,7 @@ function listRecentDirs(store, limit = 50) {
63210
63385
  }
63211
63386
 
63212
63387
  // src/permission/persona-paths.ts
63213
- var path74 = __toESM(require("path"), 1);
63388
+ var path75 = __toESM(require("path"), 1);
63214
63389
  function getAllowedPersonaIds(grants, action) {
63215
63390
  const ids = /* @__PURE__ */ new Set();
63216
63391
  for (const g2 of grants) {
@@ -63223,42 +63398,42 @@ function getAllowedPersonaIds(grants, action) {
63223
63398
  return ids;
63224
63399
  }
63225
63400
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
63226
- const target = path74.resolve(absPath);
63401
+ const target = path75.resolve(absPath);
63227
63402
  if (userWorkDir) {
63228
- const u = path74.resolve(userWorkDir);
63229
- const usep = u.endsWith(path74.sep) ? "" : path74.sep;
63403
+ const u = path75.resolve(userWorkDir);
63404
+ const usep = u.endsWith(path75.sep) ? "" : path75.sep;
63230
63405
  if (target === u || target.startsWith(u + usep)) return true;
63231
63406
  }
63232
- const root = path74.resolve(personaRoot);
63233
- const sep4 = root.endsWith(path74.sep) ? "" : path74.sep;
63407
+ const root = path75.resolve(personaRoot);
63408
+ const sep4 = root.endsWith(path75.sep) ? "" : path75.sep;
63234
63409
  if (!target.startsWith(root + sep4)) return false;
63235
- const rel = path74.relative(root, target);
63410
+ const rel = path75.relative(root, target);
63236
63411
  if (!rel || rel.startsWith("..")) return false;
63237
- const personaId2 = rel.split(path74.sep)[0];
63412
+ const personaId2 = rel.split(path75.sep)[0];
63238
63413
  if (!personaId2) return false;
63239
63414
  const allowed = getAllowedPersonaIds(grants, action);
63240
63415
  if (allowed === "*") return true;
63241
63416
  return allowed.has(personaId2);
63242
63417
  }
63243
63418
  function personaIdFromPath(absPath, personaRoot) {
63244
- const root = path74.resolve(personaRoot);
63245
- const target = path74.resolve(absPath);
63246
- const sep4 = root.endsWith(path74.sep) ? "" : path74.sep;
63419
+ const root = path75.resolve(personaRoot);
63420
+ const target = path75.resolve(absPath);
63421
+ const sep4 = root.endsWith(path75.sep) ? "" : path75.sep;
63247
63422
  if (!target.startsWith(root + sep4)) return null;
63248
- const rel = path74.relative(root, target);
63423
+ const rel = path75.relative(root, target);
63249
63424
  if (!rel || rel.startsWith("..")) return null;
63250
- const id = rel.split(path74.sep)[0];
63425
+ const id = rel.split(path75.sep)[0];
63251
63426
  return id || null;
63252
63427
  }
63253
63428
  function isPathWithin(dir, absPath) {
63254
- const d = path74.resolve(dir);
63255
- const t = path74.resolve(absPath);
63256
- const sep4 = d.endsWith(path74.sep) ? "" : path74.sep;
63429
+ const d = path75.resolve(dir);
63430
+ const t = path75.resolve(absPath);
63431
+ const sep4 = d.endsWith(path75.sep) ? "" : path75.sep;
63257
63432
  return t === d || t.startsWith(d + sep4);
63258
63433
  }
63259
63434
  function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
63260
63435
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
63261
- return personaIdFromPath(path74.resolve(absPath), personaRoot) === personaId2;
63436
+ return personaIdFromPath(path75.resolve(absPath), personaRoot) === personaId2;
63262
63437
  }
63263
63438
 
63264
63439
  // src/handlers/history.ts
@@ -63311,7 +63486,7 @@ function buildHistoryHandlers(deps) {
63311
63486
  if (!pid) return false;
63312
63487
  return isGuestPathAllowed(
63313
63488
  ctx.grants,
63314
- path75.join(personaRoot, pid),
63489
+ path76.join(personaRoot, pid),
63315
63490
  personaRoot,
63316
63491
  "read",
63317
63492
  userWorkDir
@@ -63323,7 +63498,7 @@ function buildHistoryHandlers(deps) {
63323
63498
  };
63324
63499
  const list = async (frame, _client, ctx) => {
63325
63500
  const args = HistoryListArgs.parse(frame);
63326
- assertGuestPath(ctx, path75.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
63501
+ assertGuestPath(ctx, path76.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
63327
63502
  const sessions = await history.listSessions(args);
63328
63503
  return { response: { type: "history:list", sessions } };
63329
63504
  };
@@ -63371,14 +63546,14 @@ function buildHistoryHandlers(deps) {
63371
63546
  };
63372
63547
  const subagents = async (frame, _client, ctx) => {
63373
63548
  const args = HistorySubagentsArgs.parse(frame);
63374
- assertGuestPath(ctx, path75.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
63549
+ assertGuestPath(ctx, path76.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
63375
63550
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
63376
63551
  const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
63377
63552
  return { response: { type: "history:subagents", subagents: subs } };
63378
63553
  };
63379
63554
  const subagentRead = async (frame, _client, ctx) => {
63380
63555
  const args = HistorySubagentReadArgs.parse(frame);
63381
- assertGuestPath(ctx, path75.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
63556
+ assertGuestPath(ctx, path76.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
63382
63557
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
63383
63558
  const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
63384
63559
  return { response: { type: "history:subagent-read", ...res } };
@@ -63388,7 +63563,7 @@ function buildHistoryHandlers(deps) {
63388
63563
  if (ctx?.principal.kind === "guest" && personaRoot) {
63389
63564
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
63390
63565
  const filtered = dirs.filter(
63391
- (d) => isGuestPathAllowed(ctx.grants, path75.resolve(d.cwd), personaRoot, "read", userWorkDir)
63566
+ (d) => isGuestPathAllowed(ctx.grants, path76.resolve(d.cwd), personaRoot, "read", userWorkDir)
63392
63567
  );
63393
63568
  return { response: { type: "history:recentDirs", dirs: filtered } };
63394
63569
  }
@@ -63405,17 +63580,17 @@ function buildHistoryHandlers(deps) {
63405
63580
  }
63406
63581
 
63407
63582
  // src/handlers/projects.ts
63408
- var fs68 = __toESM(require("fs"), 1);
63409
- var os21 = __toESM(require("os"), 1);
63410
- var path76 = __toESM(require("path"), 1);
63583
+ var fs69 = __toESM(require("fs"), 1);
63584
+ var os22 = __toESM(require("os"), 1);
63585
+ var path77 = __toESM(require("path"), 1);
63411
63586
  var import_node_child_process14 = require("child_process");
63412
63587
  init_protocol();
63413
- var DEFAULT_PROJECTS_ROOT = path76.join(os21.homedir(), "Documents", "ChatGPT");
63588
+ var DEFAULT_PROJECTS_ROOT = path77.join(os22.homedir(), "Documents", "ChatGPT");
63414
63589
  function allocateDir(root, name) {
63415
- let candidate = path76.join(root, name);
63590
+ let candidate = path77.join(root, name);
63416
63591
  let n = 2;
63417
- while (fs68.existsSync(candidate)) {
63418
- candidate = path76.join(root, `${name} ${n}`);
63592
+ while (fs69.existsSync(candidate)) {
63593
+ candidate = path77.join(root, `${name} ${n}`);
63419
63594
  n += 1;
63420
63595
  }
63421
63596
  return candidate;
@@ -63443,7 +63618,7 @@ function buildProjectHandlers(deps) {
63443
63618
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
63444
63619
  }
63445
63620
  try {
63446
- if (!fs68.statSync(args.path).isDirectory()) throw new Error("not dir");
63621
+ if (!fs69.statSync(args.path).isDirectory()) throw new Error("not dir");
63447
63622
  } catch {
63448
63623
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
63449
63624
  }
@@ -63459,7 +63634,7 @@ function buildProjectHandlers(deps) {
63459
63634
  let target;
63460
63635
  if (args.path) {
63461
63636
  try {
63462
- if (!fs68.statSync(args.path).isDirectory()) throw new Error("not dir");
63637
+ if (!fs69.statSync(args.path).isDirectory()) throw new Error("not dir");
63463
63638
  } catch {
63464
63639
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
63465
63640
  }
@@ -63467,15 +63642,15 @@ function buildProjectHandlers(deps) {
63467
63642
  } else {
63468
63643
  const name = args.name;
63469
63644
  try {
63470
- fs68.mkdirSync(root, { recursive: true });
63645
+ fs69.mkdirSync(root, { recursive: true });
63471
63646
  target = allocateDir(root, name);
63472
- fs68.mkdirSync(target);
63647
+ fs69.mkdirSync(target);
63473
63648
  } catch (err) {
63474
63649
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
63475
63650
  }
63476
63651
  const git2 = (0, import_node_child_process14.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
63477
63652
  if (git2.status !== 0) {
63478
- fs68.rmSync(target, { recursive: true, force: true });
63653
+ fs69.rmSync(target, { recursive: true, force: true });
63479
63654
  throw new ClawdError(
63480
63655
  ERROR_CODES.INVALID_CWD,
63481
63656
  `git init \u5931\u8D25\uFF08${git2.error ? String(git2.error) : `exit ${git2.status}`}\uFF09: ${target}`
@@ -63500,8 +63675,8 @@ function buildProjectHandlers(deps) {
63500
63675
  }
63501
63676
 
63502
63677
  // src/handlers/workspace.ts
63503
- var path77 = __toESM(require("path"), 1);
63504
- var os22 = __toESM(require("os"), 1);
63678
+ var path78 = __toESM(require("path"), 1);
63679
+ var os23 = __toESM(require("os"), 1);
63505
63680
  init_protocol();
63506
63681
  init_protocol();
63507
63682
  function buildEnabledPluginNames(personaManager, personaId2) {
@@ -63541,23 +63716,23 @@ function buildWorkspaceHandlers(deps) {
63541
63716
  const list = async (frame, _client, ctx) => {
63542
63717
  const args = WorkspaceListArgs.parse(frame);
63543
63718
  const isGuest = ctx?.principal.kind === "guest";
63544
- const fallbackCwd = isGuest && personaRoot ? personaRoot : os22.homedir();
63545
- const resolvedCwd = path77.resolve(args.cwd ?? fallbackCwd);
63546
- const target = args.path ? path77.resolve(resolvedCwd, args.path) : resolvedCwd;
63719
+ const fallbackCwd = isGuest && personaRoot ? personaRoot : os23.homedir();
63720
+ const resolvedCwd = path78.resolve(args.cwd ?? fallbackCwd);
63721
+ const target = args.path ? path78.resolve(resolvedCwd, args.path) : resolvedCwd;
63547
63722
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
63548
63723
  const res = workspace.list({ ...args, cwd: resolvedCwd });
63549
63724
  return { response: { type: "workspace:list", ...res } };
63550
63725
  };
63551
63726
  const read = async (frame, _client, ctx) => {
63552
63727
  const args = WorkspaceReadArgs.parse(frame);
63553
- const target = path77.isAbsolute(args.path) ? path77.resolve(args.path) : path77.resolve(args.cwd, args.path);
63728
+ const target = path78.isAbsolute(args.path) ? path78.resolve(args.path) : path78.resolve(args.cwd, args.path);
63554
63729
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
63555
63730
  const res = workspace.read(args);
63556
63731
  return { response: { type: "workspace:read", ...res } };
63557
63732
  };
63558
63733
  const skillsList = async (frame, _client, ctx) => {
63559
63734
  const args = SkillsListArgs.parse(frame);
63560
- const cwdAbs = path77.resolve(args.cwd);
63735
+ const cwdAbs = path78.resolve(args.cwd);
63561
63736
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
63562
63737
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
63563
63738
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -63569,7 +63744,7 @@ function buildWorkspaceHandlers(deps) {
63569
63744
  };
63570
63745
  const agentsList = async (frame, _client, ctx) => {
63571
63746
  const args = AgentsListArgs.parse(frame);
63572
- const cwdAbs = path77.resolve(args.cwd);
63747
+ const cwdAbs = path78.resolve(args.cwd);
63573
63748
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
63574
63749
  if (args.tool === "codex") {
63575
63750
  return { response: { type: "agents:list", agents: [] } };
@@ -63591,20 +63766,20 @@ function buildWorkspaceHandlers(deps) {
63591
63766
  }
63592
63767
 
63593
63768
  // src/handlers/git.ts
63594
- var path79 = __toESM(require("path"), 1);
63769
+ var path80 = __toESM(require("path"), 1);
63595
63770
  init_protocol();
63596
63771
  init_protocol();
63597
63772
 
63598
63773
  // src/workspace/git.ts
63599
63774
  var import_node_child_process15 = require("child_process");
63600
- var import_node_fs51 = __toESM(require("fs"), 1);
63601
- var import_node_path61 = __toESM(require("path"), 1);
63775
+ var import_node_fs52 = __toESM(require("fs"), 1);
63776
+ var import_node_path62 = __toESM(require("path"), 1);
63602
63777
  var import_node_util = require("util");
63603
63778
  var pexec = (0, import_node_util.promisify)(import_node_child_process15.execFile);
63604
63779
  function normalizePath(p2) {
63605
- const resolved = import_node_path61.default.resolve(p2);
63780
+ const resolved = import_node_path62.default.resolve(p2);
63606
63781
  try {
63607
- return import_node_fs51.default.realpathSync(resolved);
63782
+ return import_node_fs52.default.realpathSync(resolved);
63608
63783
  } catch {
63609
63784
  return resolved;
63610
63785
  }
@@ -63678,7 +63853,7 @@ async function listGitBranches(cwd) {
63678
63853
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
63679
63854
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
63680
63855
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
63681
- if (!isGuestPathAllowed(ctx.grants, path79.resolve(cwd), personaRoot, "read", userWorkDir)) {
63856
+ if (!isGuestPathAllowed(ctx.grants, path80.resolve(cwd), personaRoot, "read", userWorkDir)) {
63682
63857
  throw new ClawdError(
63683
63858
  ERROR_CODES.UNAUTHORIZED,
63684
63859
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -64248,7 +64423,7 @@ function buildFeishuAuthHandlers(deps) {
64248
64423
  }
64249
64424
 
64250
64425
  // src/handlers/meta.ts
64251
- var import_node_os20 = __toESM(require("os"), 1);
64426
+ var import_node_os21 = __toESM(require("os"), 1);
64252
64427
  init_protocol();
64253
64428
 
64254
64429
  // src/handlers/method-grants.ts
@@ -64551,21 +64726,21 @@ function computeMethodAccess(args) {
64551
64726
  }
64552
64727
 
64553
64728
  // src/version.ts
64554
- var version = "0.2.484".length > 0 ? "0.2.484" : "dev";
64729
+ var version = "0.2.486".length > 0 ? "0.2.486" : "dev";
64555
64730
 
64556
64731
  // src/cli-probe/probe.ts
64557
- var fs70 = __toESM(require("fs"), 1);
64558
- var path80 = __toESM(require("path"), 1);
64732
+ var fs71 = __toESM(require("fs"), 1);
64733
+ var path81 = __toESM(require("path"), 1);
64559
64734
  var PKG_NAME = "@clawos-dev/clawd";
64560
64735
  var BIN_NAME = "clawd";
64561
64736
  var MAX_PARENT_HOPS = 5;
64562
64737
  function probeGlobalCli(pathEnv) {
64563
64738
  if (!pathEnv) return null;
64564
- for (const dir of pathEnv.split(path80.delimiter)) {
64739
+ for (const dir of pathEnv.split(path81.delimiter)) {
64565
64740
  if (!dir) continue;
64566
64741
  let real;
64567
64742
  try {
64568
- real = fs70.realpathSync(path80.join(dir, BIN_NAME));
64743
+ real = fs71.realpathSync(path81.join(dir, BIN_NAME));
64569
64744
  } catch {
64570
64745
  continue;
64571
64746
  }
@@ -64575,15 +64750,15 @@ function probeGlobalCli(pathEnv) {
64575
64750
  return null;
64576
64751
  }
64577
64752
  function readOwnPackageVersion(entryPath) {
64578
- let dir = path80.dirname(entryPath);
64753
+ let dir = path81.dirname(entryPath);
64579
64754
  for (let i = 0; i < MAX_PARENT_HOPS; i++) {
64580
64755
  try {
64581
- const raw = fs70.readFileSync(path80.join(dir, "package.json"), "utf8");
64756
+ const raw = fs71.readFileSync(path81.join(dir, "package.json"), "utf8");
64582
64757
  const pkg = JSON.parse(raw);
64583
64758
  if (pkg.name !== PKG_NAME) return null;
64584
64759
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
64585
64760
  } catch {
64586
- const parent = path80.dirname(dir);
64761
+ const parent = path81.dirname(dir);
64587
64762
  if (parent === dir) return null;
64588
64763
  dir = parent;
64589
64764
  }
@@ -64619,7 +64794,7 @@ function buildReadyFrame(deps, client) {
64619
64794
  return {
64620
64795
  version,
64621
64796
  protocolVersion: PROTOCOL_VERSION,
64622
- hostname: import_node_os20.default.hostname(),
64797
+ hostname: import_node_os21.default.hostname(),
64623
64798
  os: process.platform,
64624
64799
  tools,
64625
64800
  runningSessions: info.runningSessions,
@@ -64755,7 +64930,7 @@ function buildPersonaHandlers(deps) {
64755
64930
  }
64756
64931
 
64757
64932
  // src/handlers/attachment.ts
64758
- var import_node_path62 = __toESM(require("path"), 1);
64933
+ var import_node_path63 = __toESM(require("path"), 1);
64759
64934
  init_protocol();
64760
64935
  init_protocol();
64761
64936
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -64835,12 +65010,12 @@ function buildAttachmentHandlers(deps) {
64835
65010
  `session ${args.sessionId} scope unresolved`
64836
65011
  );
64837
65012
  }
64838
- const cwdAbs = import_node_path62.default.resolve(sessionFile.cwd);
64839
- const candidateAbs = import_node_path62.default.isAbsolute(args.relPath) ? import_node_path62.default.resolve(args.relPath) : import_node_path62.default.resolve(cwdAbs, args.relPath);
65013
+ const cwdAbs = import_node_path63.default.resolve(sessionFile.cwd);
65014
+ const candidateAbs = import_node_path63.default.isAbsolute(args.relPath) ? import_node_path63.default.resolve(args.relPath) : import_node_path63.default.resolve(cwdAbs, args.relPath);
64840
65015
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
64841
65016
  const entries = deps.groupFileStore.list(scope, args.sessionId);
64842
65017
  const entry = entries.find((e) => {
64843
- const storedAbs = import_node_path62.default.isAbsolute(e.relPath) ? import_node_path62.default.resolve(e.relPath) : import_node_path62.default.resolve(cwdAbs, e.relPath);
65018
+ const storedAbs = import_node_path63.default.isAbsolute(e.relPath) ? import_node_path63.default.resolve(e.relPath) : import_node_path63.default.resolve(cwdAbs, e.relPath);
64844
65019
  return storedAbs === candidateAbs && !e.stale;
64845
65020
  });
64846
65021
  if (!entry) {
@@ -64865,7 +65040,7 @@ function buildAttachmentHandlers(deps) {
64865
65040
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
64866
65041
  const f = deps.sessionStore.read(sessionId);
64867
65042
  if (!f) return;
64868
- assertGuestAttachmentPath(ctx, import_node_path62.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
65043
+ assertGuestAttachmentPath(ctx, import_node_path63.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
64869
65044
  }
64870
65045
  const groupAdd = async (frame, _client, ctx) => {
64871
65046
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -64880,8 +65055,8 @@ function buildAttachmentHandlers(deps) {
64880
65055
  if (!scope) {
64881
65056
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
64882
65057
  }
64883
- const cwdAbs = import_node_path62.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
64884
- const candidateAbs = import_node_path62.default.isAbsolute(args.relPath) ? import_node_path62.default.resolve(args.relPath) : import_node_path62.default.resolve(cwdAbs, args.relPath);
65058
+ const cwdAbs = import_node_path63.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
65059
+ const candidateAbs = import_node_path63.default.isAbsolute(args.relPath) ? import_node_path63.default.resolve(args.relPath) : import_node_path63.default.resolve(cwdAbs, args.relPath);
64885
65060
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
64886
65061
  const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
64887
65062
  const size = 0;
@@ -64940,19 +65115,19 @@ function buildAttachmentHandlers(deps) {
64940
65115
 
64941
65116
  // src/handlers/extension.ts
64942
65117
  var import_promises14 = __toESM(require("fs/promises"), 1);
64943
- var import_node_path67 = __toESM(require("path"), 1);
65118
+ var import_node_path68 = __toESM(require("path"), 1);
64944
65119
  init_protocol();
64945
65120
 
64946
65121
  // src/extension/bundle-zip.ts
64947
65122
  var import_promises11 = __toESM(require("fs/promises"), 1);
64948
- var import_node_path63 = __toESM(require("path"), 1);
65123
+ var import_node_path64 = __toESM(require("path"), 1);
64949
65124
  var import_node_crypto17 = __toESM(require("crypto"), 1);
64950
65125
  var import_jszip2 = __toESM(require_lib3(), 1);
64951
65126
  async function bundleExtensionDir(dir) {
64952
65127
  const entries = await listFilesSorted(dir);
64953
65128
  const zip = new import_jszip2.default();
64954
65129
  for (const rel of entries) {
64955
- const abs = import_node_path63.default.join(dir, rel);
65130
+ const abs = import_node_path64.default.join(dir, rel);
64956
65131
  const content = await import_promises11.default.readFile(abs);
64957
65132
  zip.file(rel, content, { date: FIXED_DATE });
64958
65133
  }
@@ -64973,7 +65148,7 @@ async function listFilesSorted(rootDir) {
64973
65148
  return out;
64974
65149
  }
64975
65150
  async function walk(absRoot, relPrefix, out) {
64976
- const dirAbs = import_node_path63.default.join(absRoot, relPrefix);
65151
+ const dirAbs = import_node_path64.default.join(absRoot, relPrefix);
64977
65152
  const entries = await import_promises11.default.readdir(dirAbs, { withFileTypes: true });
64978
65153
  for (const e of entries) {
64979
65154
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -65027,25 +65202,25 @@ function computePublishCheck(args) {
65027
65202
 
65028
65203
  // src/extension/install-flow.ts
65029
65204
  var import_promises12 = __toESM(require("fs/promises"), 1);
65030
- var import_node_path65 = __toESM(require("path"), 1);
65031
- var import_node_os22 = __toESM(require("os"), 1);
65205
+ var import_node_path66 = __toESM(require("path"), 1);
65206
+ var import_node_os23 = __toESM(require("os"), 1);
65032
65207
  var import_node_crypto18 = __toESM(require("crypto"), 1);
65033
65208
  var import_jszip3 = __toESM(require_lib3(), 1);
65034
65209
 
65035
65210
  // src/extension/paths.ts
65036
- var import_node_os21 = __toESM(require("os"), 1);
65037
- var import_node_path64 = __toESM(require("path"), 1);
65211
+ var import_node_os22 = __toESM(require("os"), 1);
65212
+ var import_node_path65 = __toESM(require("path"), 1);
65038
65213
  function clawdHomeRoot(override) {
65039
- return override ?? process.env.CLAWD_HOME ?? import_node_path64.default.join(import_node_os21.default.homedir(), ".clawd");
65214
+ return override ?? process.env.CLAWD_HOME ?? import_node_path65.default.join(import_node_os22.default.homedir(), ".clawd");
65040
65215
  }
65041
65216
  function extensionsRoot(override) {
65042
- return import_node_path64.default.join(clawdHomeRoot(override), "extensions");
65217
+ return import_node_path65.default.join(clawdHomeRoot(override), "extensions");
65043
65218
  }
65044
65219
  function publishedChannelsFile(override) {
65045
- return import_node_path64.default.join(clawdHomeRoot(override), "extensions-published.json");
65220
+ return import_node_path65.default.join(clawdHomeRoot(override), "extensions-published.json");
65046
65221
  }
65047
65222
  function bundleCacheRoot(override) {
65048
- return import_node_path64.default.join(clawdHomeRoot(override), "extension-bundles");
65223
+ return import_node_path65.default.join(clawdHomeRoot(override), "extension-bundles");
65049
65224
  }
65050
65225
 
65051
65226
  // src/extension/install-flow.ts
@@ -65072,7 +65247,7 @@ async function installFromChannel(args, deps) {
65072
65247
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
65073
65248
  }
65074
65249
  for (const name of Object.keys(zip.files)) {
65075
- if (name.includes("..") || name.startsWith("/") || import_node_path65.default.isAbsolute(name)) {
65250
+ if (name.includes("..") || name.startsWith("/") || import_node_path66.default.isAbsolute(name)) {
65076
65251
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
65077
65252
  }
65078
65253
  }
@@ -65104,7 +65279,7 @@ async function installFromChannel(args, deps) {
65104
65279
  );
65105
65280
  }
65106
65281
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
65107
- const destDir = import_node_path65.default.join(deps.extensionsRoot, localExtId);
65282
+ const destDir = import_node_path66.default.join(deps.extensionsRoot, localExtId);
65108
65283
  let destExists = false;
65109
65284
  try {
65110
65285
  await import_promises12.default.access(destDir);
@@ -65118,16 +65293,16 @@ async function installFromChannel(args, deps) {
65118
65293
  );
65119
65294
  }
65120
65295
  const stage = await import_promises12.default.mkdtemp(
65121
- import_node_path65.default.join(import_node_os22.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
65296
+ import_node_path66.default.join(import_node_os23.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
65122
65297
  );
65123
65298
  try {
65124
65299
  for (const [name, entry] of Object.entries(zip.files)) {
65125
- const dest = import_node_path65.default.join(stage, name);
65300
+ const dest = import_node_path66.default.join(stage, name);
65126
65301
  if (entry.dir) {
65127
65302
  await import_promises12.default.mkdir(dest, { recursive: true });
65128
65303
  continue;
65129
65304
  }
65130
- await import_promises12.default.mkdir(import_node_path65.default.dirname(dest), { recursive: true });
65305
+ await import_promises12.default.mkdir(import_node_path66.default.dirname(dest), { recursive: true });
65131
65306
  if (name === "manifest.json") {
65132
65307
  const rewritten = { ...parsed.data, id: localExtId };
65133
65308
  await import_promises12.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -65148,8 +65323,8 @@ async function installFromChannel(args, deps) {
65148
65323
 
65149
65324
  // src/extension/update-flow.ts
65150
65325
  var import_promises13 = __toESM(require("fs/promises"), 1);
65151
- var import_node_path66 = __toESM(require("path"), 1);
65152
- var import_node_os23 = __toESM(require("os"), 1);
65326
+ var import_node_path67 = __toESM(require("path"), 1);
65327
+ var import_node_os24 = __toESM(require("os"), 1);
65153
65328
  var import_node_crypto19 = __toESM(require("crypto"), 1);
65154
65329
  var import_jszip4 = __toESM(require_lib3(), 1);
65155
65330
  var UpdateError = class extends Error {
@@ -65165,11 +65340,11 @@ async function updateFromChannel(args, deps) {
65165
65340
  channelRef.extId,
65166
65341
  channelRef.ownerPrincipalId
65167
65342
  );
65168
- const liveDir = import_node_path66.default.join(deps.extensionsRoot, localExtId);
65343
+ const liveDir = import_node_path67.default.join(deps.extensionsRoot, localExtId);
65169
65344
  const prevDir = `${liveDir}.prev`;
65170
65345
  let existingVersion;
65171
65346
  try {
65172
- const raw = await import_promises13.default.readFile(import_node_path66.default.join(liveDir, "manifest.json"), "utf8");
65347
+ const raw = await import_promises13.default.readFile(import_node_path67.default.join(liveDir, "manifest.json"), "utf8");
65173
65348
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
65174
65349
  if (!parsed2.success) {
65175
65350
  throw new UpdateError(
@@ -65202,7 +65377,7 @@ async function updateFromChannel(args, deps) {
65202
65377
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
65203
65378
  }
65204
65379
  for (const name of Object.keys(zip.files)) {
65205
- if (name.includes("..") || name.startsWith("/") || import_node_path66.default.isAbsolute(name)) {
65380
+ if (name.includes("..") || name.startsWith("/") || import_node_path67.default.isAbsolute(name)) {
65206
65381
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
65207
65382
  }
65208
65383
  }
@@ -65237,16 +65412,16 @@ async function updateFromChannel(args, deps) {
65237
65412
  await import_promises13.default.rm(prevDir, { recursive: true, force: true });
65238
65413
  await import_promises13.default.rename(liveDir, prevDir);
65239
65414
  const stage = await import_promises13.default.mkdtemp(
65240
- import_node_path66.default.join(import_node_os23.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
65415
+ import_node_path67.default.join(import_node_os24.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
65241
65416
  );
65242
65417
  try {
65243
65418
  for (const [name, entry] of Object.entries(zip.files)) {
65244
- const dest = import_node_path66.default.join(stage, name);
65419
+ const dest = import_node_path67.default.join(stage, name);
65245
65420
  if (entry.dir) {
65246
65421
  await import_promises13.default.mkdir(dest, { recursive: true });
65247
65422
  continue;
65248
65423
  }
65249
- await import_promises13.default.mkdir(import_node_path66.default.dirname(dest), { recursive: true });
65424
+ await import_promises13.default.mkdir(import_node_path67.default.dirname(dest), { recursive: true });
65250
65425
  if (name === "manifest.json") {
65251
65426
  const rewritten = { ...parsed.data, id: localExtId };
65252
65427
  await import_promises13.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -65313,7 +65488,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
65313
65488
  );
65314
65489
  }
65315
65490
  }
65316
- const manifestPath = import_node_path67.default.join(root, extId, "manifest.json");
65491
+ const manifestPath = import_node_path68.default.join(root, extId, "manifest.json");
65317
65492
  const manifest = await readManifest(root, extId);
65318
65493
  const next = { ...manifest, version: newVersion };
65319
65494
  const tmp = `${manifestPath}.tmp`;
@@ -65321,7 +65496,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
65321
65496
  await import_promises14.default.rename(tmp, manifestPath);
65322
65497
  }
65323
65498
  async function readManifest(root, extId) {
65324
- const file = import_node_path67.default.join(root, extId, "manifest.json");
65499
+ const file = import_node_path68.default.join(root, extId, "manifest.json");
65325
65500
  let raw;
65326
65501
  try {
65327
65502
  raw = await import_promises14.default.readFile(file, "utf8");
@@ -65405,7 +65580,7 @@ function buildExtensionHandlers(deps) {
65405
65580
  };
65406
65581
  async function buildSnapshotMeta(extId) {
65407
65582
  const manifest = await readManifest(deps.root, extId);
65408
- const { sha256, buffer } = await bundleExtensionDir(import_node_path67.default.join(deps.root, extId));
65583
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path68.default.join(deps.root, extId));
65409
65584
  return { manifest, contentHash: sha256, buffer };
65410
65585
  }
65411
65586
  const publish = async (frame, _client, ctx) => {
@@ -65648,8 +65823,8 @@ var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
65648
65823
 
65649
65824
  // src/handlers/app-builder.ts
65650
65825
  init_protocol();
65651
- var import_node_path68 = require("path");
65652
- var import_node_fs52 = require("fs");
65826
+ var import_node_path69 = require("path");
65827
+ var import_node_fs53 = require("fs");
65653
65828
  var DEFAULT_TEMPLATE = "nestjs-react";
65654
65829
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
65655
65830
  function buildAppBuilderHandlers(deps) {
@@ -65722,7 +65897,7 @@ function buildAppBuilderHandlers(deps) {
65722
65897
  async function listAllUsersProjects() {
65723
65898
  if (!deps.usersRoot || !deps.getStore) return [];
65724
65899
  const getStore = deps.getStore;
65725
- const userIds = await import_node_fs52.promises.readdir(deps.usersRoot).catch(() => []);
65900
+ const userIds = await import_node_fs53.promises.readdir(deps.usersRoot).catch(() => []);
65726
65901
  const perUser = await Promise.all(
65727
65902
  userIds.map((uid) => getStore(uid).list().catch(() => []))
65728
65903
  );
@@ -65795,13 +65970,13 @@ function buildAppBuilderHandlers(deps) {
65795
65970
  const created = await deps.createProjectOnDisk({
65796
65971
  store: userStore,
65797
65972
  name: f.name,
65798
- templateSrcDir: (0, import_node_path68.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE),
65799
- scaffoldScript: (0, import_node_path68.join)(deps.deployKitRoot, "scripts", "new-extension.sh"),
65973
+ templateSrcDir: (0, import_node_path69.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE),
65974
+ scaffoldScript: (0, import_node_path69.join)(deps.deployKitRoot, "scripts", "new-extension.sh"),
65800
65975
  reservedPorts,
65801
65976
  // 凭据只进 scaffold 子进程的 env,且**只给这个 persona 的 kit 模板声明要的那几个变量**
65802
65977
  // (M1b Step 5)。整表塞进去粒度只到「进程」——那会把 service-role key 交给一个用不到
65803
65978
  // 它的脚本。new-extension.sh 用它把模板的 `${VAR}` 渲成项目可跑的 server/.env。
65804
- extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path68.join)(personaRoot, "extension-kit")),
65979
+ extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path69.join)(personaRoot, "extension-kit")),
65805
65980
  ...deps.logger ? { logger: deps.logger } : {}
65806
65981
  });
65807
65982
  project = created.project;
@@ -66000,7 +66175,7 @@ function buildAppBuilderHandlers(deps) {
66000
66175
  await userStore.clearPublishJob(args.name);
66001
66176
  }
66002
66177
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
66003
- const scriptPath = (0, import_node_path68.join)(deps.deployKitRoot, "scripts", "publish.sh");
66178
+ const scriptPath = (0, import_node_path69.join)(deps.deployKitRoot, "scripts", "publish.sh");
66004
66179
  deps.logger?.info("app-builder.publish.start", {
66005
66180
  name: args.name,
66006
66181
  sessionId: boundSession.sessionId,
@@ -66016,7 +66191,7 @@ function buildAppBuilderHandlers(deps) {
66016
66191
  // 凭据只进 publish.sh 这个子进程的 env,且只给它的 kit 模板声明要的那几个变量
66017
66192
  // (M1b Step 5)。那个进程里跑着 `eval "$BUILD_CMD"`——项目自带的构建命令会继承这份
66018
66193
  // env,多给一个变量就是多交一个凭据给它。personaRoot 上面已按绑定 session 的 persona 解析。
66019
- extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path68.join)(personaRoot, "extension-kit")),
66194
+ extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path69.join)(personaRoot, "extension-kit")),
66020
66195
  hooks: {
66021
66196
  // 元数据每次写盘(publishJob 起落 / prodUrl 回填)后重推一帧:UI 渲染 PublishProgress
66022
66197
  // 三段 checklist 依赖 project.publishJob.status==='in-flight',而 publishJob 字段只有
@@ -66549,20 +66724,20 @@ function mapPrState(state, isDraft) {
66549
66724
  if (state === "CLOSED") return "closed";
66550
66725
  return isDraft === true ? "draft" : "open";
66551
66726
  }
66552
- function asRecord2(v2) {
66727
+ function asRecord3(v2) {
66553
66728
  return typeof v2 === "object" && v2 !== null ? v2 : {};
66554
66729
  }
66555
66730
  function lastCommitRollup(node) {
66556
- const first = asRecord2(node.commits).nodes?.[0];
66557
- return asRecord2(asRecord2(first).commit).statusCheckRollup;
66731
+ const first = asRecord3(node.commits).nodes?.[0];
66732
+ return asRecord3(asRecord3(first).commit).statusCheckRollup;
66558
66733
  }
66559
66734
  function parsePrListResponse(json) {
66560
- const nodes = asRecord2(asRecord2(asRecord2(json).data).search).nodes ?? [];
66735
+ const nodes = asRecord3(asRecord3(asRecord3(json).data).search).nodes ?? [];
66561
66736
  const items = [];
66562
66737
  for (const raw of nodes) {
66563
- const n = asRecord2(raw);
66738
+ const n = asRecord3(raw);
66564
66739
  if (typeof n.number !== "number") continue;
66565
- const nameWithOwner = String(asRecord2(n.repository).nameWithOwner ?? "");
66740
+ const nameWithOwner = String(asRecord3(n.repository).nameWithOwner ?? "");
66566
66741
  const slash = nameWithOwner.indexOf("/");
66567
66742
  if (slash <= 0) continue;
66568
66743
  const rollup = lastCommitRollup(n);
@@ -66576,27 +66751,27 @@ function parsePrListResponse(json) {
66576
66751
  additions: typeof n.additions === "number" ? n.additions : 0,
66577
66752
  deletions: typeof n.deletions === "number" ? n.deletions : 0,
66578
66753
  updatedAt: String(n.updatedAt ?? ""),
66579
- author: String(asRecord2(n.author).login ?? ""),
66580
- checksRollup: rollup == null ? "none" : mapRollupState(asRecord2(rollup).state)
66754
+ author: String(asRecord3(n.author).login ?? ""),
66755
+ checksRollup: rollup == null ? "none" : mapRollupState(asRecord3(rollup).state)
66581
66756
  });
66582
66757
  }
66583
66758
  return items;
66584
66759
  }
66585
66760
  function parsePrDetailResponse(json, repoRef) {
66586
- const pr = asRecord2(asRecord2(asRecord2(json).data).repository).pullRequest;
66761
+ const pr = asRecord3(asRecord3(asRecord3(json).data).repository).pullRequest;
66587
66762
  if (pr == null || typeof pr !== "object") return null;
66588
- const n = asRecord2(pr);
66763
+ const n = asRecord3(pr);
66589
66764
  const rollup = lastCommitRollup(n);
66590
- const contextNodes = asRecord2(asRecord2(rollup).contexts).nodes ?? [];
66765
+ const contextNodes = asRecord3(asRecord3(rollup).contexts).nodes ?? [];
66591
66766
  const checks = [];
66592
66767
  for (const c of contextNodes) {
66593
- const mapped = mapCheckNode(asRecord2(c));
66768
+ const mapped = mapCheckNode(asRecord3(c));
66594
66769
  if (mapped) checks.push(mapped);
66595
66770
  }
66596
- const reviewerNodes = asRecord2(n.reviewRequests).nodes ?? [];
66597
- const reviewers = reviewerNodes.map((r) => String(asRecord2(asRecord2(r).requestedReviewer).login ?? "")).filter((s) => s !== "");
66771
+ const reviewerNodes = asRecord3(n.reviewRequests).nodes ?? [];
66772
+ const reviewers = reviewerNodes.map((r) => String(asRecord3(asRecord3(r).requestedReviewer).login ?? "")).filter((s) => s !== "");
66598
66773
  const mergeable = n.mergeable === "MERGEABLE" ? "mergeable" : n.mergeable === "CONFLICTING" ? "conflicting" : "unknown";
66599
- const commentCountRaw = asRecord2(n.comments).totalCount;
66774
+ const commentCountRaw = asRecord3(n.comments).totalCount;
66600
66775
  return {
66601
66776
  owner: repoRef.owner,
66602
66777
  repo: repoRef.repo,
@@ -66604,7 +66779,7 @@ function parsePrDetailResponse(json, repoRef) {
66604
66779
  title: String(n.title ?? ""),
66605
66780
  body: String(n.body ?? ""),
66606
66781
  state: mapPrState(n.state, n.isDraft),
66607
- author: String(asRecord2(n.author).login ?? ""),
66782
+ author: String(asRecord3(n.author).login ?? ""),
66608
66783
  updatedAt: String(n.updatedAt ?? ""),
66609
66784
  headRef: String(n.headRefName ?? ""),
66610
66785
  baseRef: String(n.baseRefName ?? ""),
@@ -66614,7 +66789,7 @@ function parsePrDetailResponse(json, repoRef) {
66614
66789
  mergeable,
66615
66790
  reviewers,
66616
66791
  commentCount: typeof commentCountRaw === "number" ? commentCountRaw : 0,
66617
- checksRollup: rollup == null ? "none" : mapRollupState(asRecord2(rollup).state),
66792
+ checksRollup: rollup == null ? "none" : mapRollupState(asRecord3(rollup).state),
66618
66793
  checks
66619
66794
  };
66620
66795
  }
@@ -66752,7 +66927,7 @@ function buildVisitorHandlers(deps) {
66752
66927
 
66753
66928
  // src/extension/registry.ts
66754
66929
  var import_promises16 = __toESM(require("fs/promises"), 1);
66755
- var import_node_path69 = __toESM(require("path"), 1);
66930
+ var import_node_path70 = __toESM(require("path"), 1);
66756
66931
  async function loadAll(root) {
66757
66932
  let entries;
66758
66933
  try {
@@ -66765,13 +66940,13 @@ async function loadAll(root) {
66765
66940
  for (const ent of entries) {
66766
66941
  if (!ent.isDirectory()) continue;
66767
66942
  if (ent.name.startsWith(".")) continue;
66768
- records.push(await loadOne(import_node_path69.default.join(root, ent.name), ent.name));
66943
+ records.push(await loadOne(import_node_path70.default.join(root, ent.name), ent.name));
66769
66944
  }
66770
66945
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
66771
66946
  return records;
66772
66947
  }
66773
66948
  async function loadOne(dir, dirName) {
66774
- const manifestPath = import_node_path69.default.join(dir, "manifest.json");
66949
+ const manifestPath = import_node_path70.default.join(dir, "manifest.json");
66775
66950
  let raw;
66776
66951
  try {
66777
66952
  raw = await import_promises16.default.readFile(manifestPath, "utf8");
@@ -66816,7 +66991,7 @@ async function loadOne(dir, dirName) {
66816
66991
 
66817
66992
  // src/extension/uninstall.ts
66818
66993
  var import_promises17 = __toESM(require("fs/promises"), 1);
66819
- var import_node_path70 = __toESM(require("path"), 1);
66994
+ var import_node_path71 = __toESM(require("path"), 1);
66820
66995
  var UninstallError = class extends Error {
66821
66996
  constructor(code, message) {
66822
66997
  super(message);
@@ -66825,7 +67000,7 @@ var UninstallError = class extends Error {
66825
67000
  code;
66826
67001
  };
66827
67002
  async function uninstall(deps) {
66828
- const dir = import_node_path70.default.join(deps.root, deps.extId);
67003
+ const dir = import_node_path71.default.join(deps.root, deps.extId);
66829
67004
  try {
66830
67005
  await import_promises17.default.access(dir);
66831
67006
  } catch {
@@ -66843,14 +67018,14 @@ init_protocol();
66843
67018
 
66844
67019
  // src/peer-ops/run-command.ts
66845
67020
  var import_node_child_process17 = require("child_process");
66846
- var import_node_os24 = __toESM(require("os"), 1);
67021
+ var import_node_os25 = __toESM(require("os"), 1);
66847
67022
  var DEFAULT_TIMEOUT_MS6 = 3e4;
66848
67023
  var MAX_TIMEOUT_MS = 3e5;
66849
67024
  var MAX_OUTPUT_BYTES = 1048576;
66850
67025
  function runCommand2(command, opts = {}) {
66851
67026
  const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS6, MAX_TIMEOUT_MS);
66852
67027
  return new Promise((resolve9) => {
66853
- const child = (0, import_node_child_process17.spawn)("bash", ["-c", command], { cwd: import_node_os24.default.homedir() });
67028
+ const child = (0, import_node_child_process17.spawn)("bash", ["-c", command], { cwd: import_node_os25.default.homedir() });
66854
67029
  const out = [];
66855
67030
  const err = [];
66856
67031
  let outBytes = 0;
@@ -67061,7 +67236,7 @@ function buildMethodHandlers(deps) {
67061
67236
  broadcast: deps.broadcastToOwners
67062
67237
  }),
67063
67238
  ...buildMasterHandlers({
67064
- authorityTablePath: import_node_path71.default.join(deps.masterDataDir, "master-authority.json")
67239
+ authorityTablePath: import_node_path72.default.join(deps.masterDataDir, "master-authority.json")
67065
67240
  }),
67066
67241
  ...buildTopicHandlers({
67067
67242
  topicStore: deps.topicStore,
@@ -67097,18 +67272,18 @@ init_claude();
67097
67272
 
67098
67273
  // src/tools/shell-path.ts
67099
67274
  var import_node_child_process18 = require("child_process");
67100
- var import_node_os25 = __toESM(require("os"), 1);
67275
+ var import_node_os26 = __toESM(require("os"), 1);
67101
67276
  function refreshPathFromLoginShell() {
67102
67277
  if (process.platform === "win32") return;
67103
- const shell = process.env.SHELL ?? import_node_os25.default.userInfo().shell ?? "/bin/zsh";
67278
+ const shell = process.env.SHELL ?? import_node_os26.default.userInfo().shell ?? "/bin/zsh";
67104
67279
  try {
67105
67280
  const out = (0, import_node_child_process18.execFileSync)(shell, ["-ilc", 'command echo -n "$PATH"'], {
67106
67281
  encoding: "utf8",
67107
67282
  timeout: 3e3,
67108
67283
  stdio: ["ignore", "pipe", "ignore"]
67109
67284
  });
67110
- const path97 = out.trim();
67111
- if (path97) process.env.PATH = path97;
67285
+ const path98 = out.trim();
67286
+ if (path98) process.env.PATH = path98;
67112
67287
  } catch {
67113
67288
  }
67114
67289
  }
@@ -67232,9 +67407,9 @@ function buildOnboardingHandlers(deps) {
67232
67407
  }
67233
67408
 
67234
67409
  // src/app-builder-plugin/project-store.ts
67235
- var import_node_fs53 = require("fs");
67410
+ var import_node_fs54 = require("fs");
67236
67411
  var import_node_child_process20 = require("child_process");
67237
- var import_node_path72 = require("path");
67412
+ var import_node_path73 = require("path");
67238
67413
  init_protocol();
67239
67414
  var PROJECTS_DIR = "projects";
67240
67415
  var META_FILE = ".clawd-project.json";
@@ -67264,19 +67439,19 @@ var ProjectStore = class {
67264
67439
  }
67265
67440
  /** projects/<name>/.clawd-project.json 路径 */
67266
67441
  metaPath(name) {
67267
- return (0, import_node_path72.join)(this.projectsRoot(), name, META_FILE);
67442
+ return (0, import_node_path73.join)(this.projectsRoot(), name, META_FILE);
67268
67443
  }
67269
67444
  /** projects/<name>/ 目录路径(cwd 用) */
67270
67445
  projectDir(name) {
67271
- return (0, import_node_path72.join)(this.projectsRoot(), name);
67446
+ return (0, import_node_path73.join)(this.projectsRoot(), name);
67272
67447
  }
67273
67448
  projectsRoot() {
67274
- return (0, import_node_path72.join)(this.root, PROJECTS_DIR);
67449
+ return (0, import_node_path73.join)(this.root, PROJECTS_DIR);
67275
67450
  }
67276
67451
  async list() {
67277
67452
  let entries;
67278
67453
  try {
67279
- entries = await import_node_fs53.promises.readdir(this.projectsRoot());
67454
+ entries = await import_node_fs54.promises.readdir(this.projectsRoot());
67280
67455
  } catch (err) {
67281
67456
  if (err.code === "ENOENT") return [];
67282
67457
  throw err;
@@ -67284,7 +67459,7 @@ var ProjectStore = class {
67284
67459
  const out = [];
67285
67460
  for (const name of entries) {
67286
67461
  try {
67287
- const raw = await import_node_fs53.promises.readFile(this.metaPath(name), "utf8");
67462
+ const raw = await import_node_fs54.promises.readFile(this.metaPath(name), "utf8");
67288
67463
  const json = JSON.parse(raw);
67289
67464
  let migrated = false;
67290
67465
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -67295,7 +67470,7 @@ var ProjectStore = class {
67295
67470
  if (parsed.success) {
67296
67471
  out.push(parsed.data);
67297
67472
  if (migrated) {
67298
- void import_node_fs53.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
67473
+ void import_node_fs54.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
67299
67474
  });
67300
67475
  }
67301
67476
  }
@@ -67339,8 +67514,8 @@ var ProjectStore = class {
67339
67514
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
67340
67515
  }
67341
67516
  const dir = this.projectDir(name);
67342
- await import_node_fs53.promises.mkdir(dir, { recursive: true });
67343
- await import_node_fs53.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
67517
+ await import_node_fs54.promises.mkdir(dir, { recursive: true });
67518
+ await import_node_fs54.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
67344
67519
  return meta;
67345
67520
  }
67346
67521
  /**
@@ -67385,7 +67560,7 @@ var ProjectStore = class {
67385
67560
  }
67386
67561
  async delete(name) {
67387
67562
  const dir = this.projectDir(name);
67388
- await import_node_fs53.promises.rm(dir, { recursive: true, force: true });
67563
+ await import_node_fs54.promises.rm(dir, { recursive: true, force: true });
67389
67564
  }
67390
67565
  async updatePort(name, newPort) {
67391
67566
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -67402,7 +67577,7 @@ var ProjectStore = class {
67402
67577
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
67403
67578
  }
67404
67579
  const updated = { ...target, port: newPort };
67405
- await import_node_fs53.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
67580
+ await import_node_fs54.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
67406
67581
  return updated;
67407
67582
  });
67408
67583
  }
@@ -67421,7 +67596,7 @@ var ProjectStore = class {
67421
67596
  if (!validated.success) {
67422
67597
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
67423
67598
  }
67424
- await import_node_fs53.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
67599
+ await import_node_fs54.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
67425
67600
  return validated.data;
67426
67601
  });
67427
67602
  }
@@ -67444,7 +67619,7 @@ var ProjectStore = class {
67444
67619
  if (!validated.success) {
67445
67620
  throw new Error(`invalid publishJob: ${validated.error.message}`);
67446
67621
  }
67447
- await import_node_fs53.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
67622
+ await import_node_fs54.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
67448
67623
  return validated.data;
67449
67624
  });
67450
67625
  }
@@ -67461,7 +67636,7 @@ var ProjectStore = class {
67461
67636
  if (!validated.success) {
67462
67637
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
67463
67638
  }
67464
- await import_node_fs53.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
67639
+ await import_node_fs54.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
67465
67640
  return validated.data;
67466
67641
  });
67467
67642
  }
@@ -67776,8 +67951,8 @@ var PublishJobRegistry = class {
67776
67951
 
67777
67952
  // src/app-builder-plugin/publish-job-runner.ts
67778
67953
  var import_node_child_process22 = require("child_process");
67779
- var import_node_fs54 = require("fs");
67780
- var import_node_path73 = require("path");
67954
+ var import_node_fs55 = require("fs");
67955
+ var import_node_path74 = require("path");
67781
67956
 
67782
67957
  // src/app-builder-plugin/publish-stage-parser.ts
67783
67958
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -67809,10 +67984,10 @@ async function startPublishJob(deps, args) {
67809
67984
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
67810
67985
  }
67811
67986
  const projDir = projectDir(args.name);
67812
- const logPath = (0, import_node_path73.join)(projDir, ".publish.log");
67987
+ const logPath = (0, import_node_path74.join)(projDir, ".publish.log");
67813
67988
  let logStream = null;
67814
67989
  try {
67815
- logStream = (0, import_node_fs54.createWriteStream)(logPath, { flags: "w" });
67990
+ logStream = (0, import_node_fs55.createWriteStream)(logPath, { flags: "w" });
67816
67991
  } catch {
67817
67992
  logStream = null;
67818
67993
  }
@@ -68155,10 +68330,10 @@ async function recoverInterruptedPublishJobs(store, logger) {
68155
68330
  }
68156
68331
 
68157
68332
  // src/app-builder-plugin/mcp-config.ts
68158
- var import_node_fs55 = __toESM(require("fs"), 1);
68159
- var import_node_path74 = __toESM(require("path"), 1);
68333
+ var import_node_fs56 = __toESM(require("fs"), 1);
68334
+ var import_node_path75 = __toESM(require("path"), 1);
68160
68335
  function appBuilderMcpConfigPath(dataDir) {
68161
- return import_node_path74.default.join(dataDir, "app-builder.mcp.json");
68336
+ return import_node_path75.default.join(dataDir, "app-builder.mcp.json");
68162
68337
  }
68163
68338
  function writeAppBuilderMcpConfig(args) {
68164
68339
  const cfgPath = appBuilderMcpConfigPath(args.dataDir);
@@ -68172,15 +68347,15 @@ function writeAppBuilderMcpConfig(args) {
68172
68347
  env: {
68173
68348
  CLAWD_DAEMON_TOKEN: args.daemonToken,
68174
68349
  CLAWD_DAEMON_URL: args.daemonUrl,
68175
- CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT: import_node_path74.default.join(args.deployKitScriptsDir, "new-extension.sh"),
68176
- CLAWD_APP_BUILDER_PUBLISH_SCRIPT: import_node_path74.default.join(args.deployKitScriptsDir, "publish.sh"),
68350
+ CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT: import_node_path75.default.join(args.deployKitScriptsDir, "new-extension.sh"),
68351
+ CLAWD_APP_BUILDER_PUBLISH_SCRIPT: import_node_path75.default.join(args.deployKitScriptsDir, "publish.sh"),
68177
68352
  ...args.logPath ? { CLAWD_APP_BUILDER_LOG: args.logPath } : {}
68178
68353
  }
68179
68354
  }
68180
68355
  }
68181
68356
  };
68182
- import_node_fs55.default.mkdirSync(args.dataDir, { recursive: true });
68183
- import_node_fs55.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf8");
68357
+ import_node_fs56.default.mkdirSync(args.dataDir, { recursive: true });
68358
+ import_node_fs56.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf8");
68184
68359
  return cfgPath;
68185
68360
  }
68186
68361
 
@@ -68221,7 +68396,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
68221
68396
 
68222
68397
  // src/extension/runtime.ts
68223
68398
  var import_node_child_process24 = require("child_process");
68224
- var import_node_path75 = __toESM(require("path"), 1);
68399
+ var import_node_path76 = __toESM(require("path"), 1);
68225
68400
  var import_promises18 = require("timers/promises");
68226
68401
 
68227
68402
  // src/extension/port-allocator.ts
@@ -68322,7 +68497,7 @@ var Runtime = class {
68322
68497
  /\$CLAWOS_EXT_PORT/g,
68323
68498
  String(port)
68324
68499
  );
68325
- const dir = import_node_path75.default.join(this.root, extId);
68500
+ const dir = import_node_path76.default.join(this.root, extId);
68326
68501
  const env = {
68327
68502
  ...process.env,
68328
68503
  CLAWOS_EXT_PORT: String(port),
@@ -68434,7 +68609,7 @@ ${handle.stderrTail}`
68434
68609
 
68435
68610
  // src/extension/published-channels.ts
68436
68611
  var import_promises19 = __toESM(require("fs/promises"), 1);
68437
- var import_node_path76 = __toESM(require("path"), 1);
68612
+ var import_node_path77 = __toESM(require("path"), 1);
68438
68613
  init_zod();
68439
68614
  var PublishedChannelsError = class extends Error {
68440
68615
  constructor(code, message) {
@@ -68533,7 +68708,7 @@ var PublishedChannelStore = class {
68533
68708
  )
68534
68709
  };
68535
68710
  const tmp = `${this.filePath}.tmp`;
68536
- await import_promises19.default.mkdir(import_node_path76.default.dirname(this.filePath), { recursive: true });
68711
+ await import_promises19.default.mkdir(import_node_path77.default.dirname(this.filePath), { recursive: true });
68537
68712
  await import_promises19.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
68538
68713
  await import_promises19.default.rename(tmp, this.filePath);
68539
68714
  }
@@ -68541,7 +68716,7 @@ var PublishedChannelStore = class {
68541
68716
 
68542
68717
  // src/extension/bundle-cache.ts
68543
68718
  var import_promises20 = __toESM(require("fs/promises"), 1);
68544
- var import_node_path77 = __toESM(require("path"), 1);
68719
+ var import_node_path78 = __toESM(require("path"), 1);
68545
68720
  var BundleCache = class {
68546
68721
  constructor(rootDir) {
68547
68722
  this.rootDir = rootDir;
@@ -68550,14 +68725,14 @@ var BundleCache = class {
68550
68725
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
68551
68726
  async write(snapshotHash, buffer) {
68552
68727
  await import_promises20.default.mkdir(this.rootDir, { recursive: true });
68553
- const file = import_node_path77.default.join(this.rootDir, `${snapshotHash}.zip`);
68728
+ const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
68554
68729
  const tmp = `${file}.tmp`;
68555
68730
  await import_promises20.default.writeFile(tmp, buffer, { mode: 384 });
68556
68731
  await import_promises20.default.rename(tmp, file);
68557
68732
  }
68558
68733
  /** Returns the bundle bytes, or null when the file doesn't exist. */
68559
68734
  async read(snapshotHash) {
68560
- const file = import_node_path77.default.join(this.rootDir, `${snapshotHash}.zip`);
68735
+ const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
68561
68736
  try {
68562
68737
  return await import_promises20.default.readFile(file);
68563
68738
  } catch (e) {
@@ -68567,7 +68742,7 @@ var BundleCache = class {
68567
68742
  }
68568
68743
  /** Idempotent — missing file is not an error. */
68569
68744
  async delete(snapshotHash) {
68570
- const file = import_node_path77.default.join(this.rootDir, `${snapshotHash}.zip`);
68745
+ const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
68571
68746
  await import_promises20.default.rm(file, { force: true });
68572
68747
  }
68573
68748
  };
@@ -68588,26 +68763,26 @@ async function startDaemon(config) {
68588
68763
  },
68589
68764
  source: "daemon",
68590
68765
  sampling: logShippingCfg.sampling,
68591
- homeDir: import_node_os26.default.homedir()
68766
+ homeDir: import_node_os27.default.homedir()
68592
68767
  });
68593
- const logDir = import_node_path78.default.join(config.dataDir, "log");
68594
- import_node_fs56.default.mkdirSync(logDir, { recursive: true });
68768
+ const logDir = import_node_path79.default.join(config.dataDir, "log");
68769
+ import_node_fs57.default.mkdirSync(logDir, { recursive: true });
68595
68770
  const logger = createLogger({
68596
68771
  level: config.logLevel,
68597
- file: import_node_path78.default.join(logDir, "clawd.log"),
68772
+ file: import_node_path79.default.join(logDir, "clawd.log"),
68598
68773
  logClient
68599
68774
  });
68600
68775
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
68601
68776
  const screenIdleProbeLogger = createFileOnlyLogger({
68602
- file: import_node_path78.default.join(logDir, "screen-idle-probe.log"),
68777
+ file: import_node_path79.default.join(logDir, "screen-idle-probe.log"),
68603
68778
  level: "debug"
68604
68779
  });
68605
68780
  logger.info("screen-idle probe logger enabled", {
68606
- file: import_node_path78.default.join(logDir, "screen-idle-probe.log")
68781
+ file: import_node_path79.default.join(logDir, "screen-idle-probe.log")
68607
68782
  });
68608
68783
  const CAP_TARGETS = [
68609
- import_node_path78.default.join(logDir, "clawd.log"),
68610
- import_node_path78.default.join(logDir, "screen-idle-probe.log")
68784
+ import_node_path79.default.join(logDir, "clawd.log"),
68785
+ import_node_path79.default.join(logDir, "screen-idle-probe.log")
68611
68786
  ];
68612
68787
  const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
68613
68788
  const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
@@ -68729,8 +68904,8 @@ async function startDaemon(config) {
68729
68904
  const agents = new AgentsScanner();
68730
68905
  const history = new ClaudeHistoryReader();
68731
68906
  let transport = null;
68732
- const personaStore = new PersonaStore(import_node_path78.default.join(config.dataDir, "personas"));
68733
- const usersRoot = import_node_path78.default.join(config.dataDir, "users");
68907
+ const personaStore = new PersonaStore(import_node_path79.default.join(config.dataDir, "personas"));
68908
+ const usersRoot = import_node_path79.default.join(config.dataDir, "users");
68734
68909
  const defaultsRoot = findDefaultsRoot(logger);
68735
68910
  if (defaultsRoot) {
68736
68911
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -68754,7 +68929,7 @@ async function startDaemon(config) {
68754
68929
  retirePersonaBuilder({ store: personaStore, logger });
68755
68930
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
68756
68931
  const dispatchStore = createDispatchStore({
68757
- filePath: import_node_path78.default.join(config.dataDir, "dispatch.json"),
68932
+ filePath: import_node_path79.default.join(config.dataDir, "dispatch.json"),
68758
68933
  now: () => Date.now(),
68759
68934
  onFlushError: (err) => logger.error("dispatch store flush failed", {
68760
68935
  reason: err instanceof Error ? err.message : String(err)
@@ -68763,7 +68938,7 @@ async function startDaemon(config) {
68763
68938
  await dispatchStore.load();
68764
68939
  dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
68765
68940
  const channelStore = createChannelStore({
68766
- filePath: import_node_path78.default.join(config.dataDir, "channels.json"),
68941
+ filePath: import_node_path79.default.join(config.dataDir, "channels.json"),
68767
68942
  now: () => Date.now(),
68768
68943
  genId: () => `ch-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
68769
68944
  onFlushError: (err) => logger.error("channel store flush failed", {
@@ -68772,7 +68947,7 @@ async function startDaemon(config) {
68772
68947
  });
68773
68948
  await channelStore.load();
68774
68949
  const topicStore = createTopicStore({
68775
- filePath: import_node_path78.default.join(config.dataDir, "topics.json"),
68950
+ filePath: import_node_path79.default.join(config.dataDir, "topics.json"),
68776
68951
  now: () => Date.now(),
68777
68952
  genId: () => `tp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
68778
68953
  onFlushError: (err) => logger.error("topic store flush failed", {
@@ -68799,28 +68974,28 @@ async function startDaemon(config) {
68799
68974
  });
68800
68975
  }
68801
68976
  });
68802
- const here = typeof __dirname === "string" ? __dirname : import_node_path78.default.dirname((0, import_node_url5.fileURLToPath)(import_meta8.url));
68977
+ const here = typeof __dirname === "string" ? __dirname : import_node_path79.default.dirname((0, import_node_url5.fileURLToPath)(import_meta8.url));
68803
68978
  const mcpConfigs = [];
68804
68979
  const secretsBundleRoot = findSecretsBundleRoot(logger);
68805
- const localSecretsDir = import_node_path78.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
68980
+ const localSecretsDir = import_node_path79.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
68806
68981
  const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
68807
68982
  const resolvePersonaMcpConfig = (personaId2) => renderPersonaMcpSecrets({
68808
68983
  personaId: personaId2,
68809
- personaDir: import_node_path78.default.join(config.dataDir, "personas", personaId2),
68984
+ personaDir: import_node_path79.default.join(config.dataDir, "personas", personaId2),
68810
68985
  secrets: readSecrets(),
68811
- outDir: import_node_path78.default.join(config.dataDir, "persona-mcp"),
68986
+ outDir: import_node_path79.default.join(config.dataDir, "persona-mcp"),
68812
68987
  logger
68813
68988
  });
68814
68989
  const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
68815
68990
  const dispatchServerCandidates = [
68816
- import_node_path78.default.join(here, "dispatch", "mcp-server.cjs"),
68991
+ import_node_path79.default.join(here, "dispatch", "mcp-server.cjs"),
68817
68992
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
68818
- import_node_path78.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
68993
+ import_node_path79.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
68819
68994
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
68820
68995
  ];
68821
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
68996
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs57.default.existsSync(p2));
68822
68997
  if (dispatchServerScriptPath) {
68823
- const dispatchLogPath = import_node_path78.default.join(logDir, "dispatch-mcp-server.log");
68998
+ const dispatchLogPath = import_node_path79.default.join(logDir, "dispatch-mcp-server.log");
68824
68999
  const dispatchCfgPath = writeDispatchMcpConfig({
68825
69000
  dataDir: config.dataDir,
68826
69001
  serverScriptPath: dispatchServerScriptPath,
@@ -68840,12 +69015,12 @@ async function startDaemon(config) {
68840
69015
  });
68841
69016
  }
68842
69017
  const ticketServerCandidates = [
68843
- import_node_path78.default.join(here, "ticket", "mcp-server.cjs"),
68844
- import_node_path78.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
69018
+ import_node_path79.default.join(here, "ticket", "mcp-server.cjs"),
69019
+ import_node_path79.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
68845
69020
  ];
68846
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69021
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs57.default.existsSync(p2));
68847
69022
  if (ticketServerScriptPath) {
68848
- const ticketLogPath = import_node_path78.default.join(logDir, "ticket-mcp-server.log");
69023
+ const ticketLogPath = import_node_path79.default.join(logDir, "ticket-mcp-server.log");
68849
69024
  const ticketCfgPath = writeTicketMcpConfig({
68850
69025
  dataDir: config.dataDir,
68851
69026
  serverScriptPath: ticketServerScriptPath,
@@ -68867,12 +69042,12 @@ async function startDaemon(config) {
68867
69042
  });
68868
69043
  }
68869
69044
  const shiftServerCandidates = [
68870
- import_node_path78.default.join(here, "shift", "mcp-server.cjs"),
68871
- import_node_path78.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
69045
+ import_node_path79.default.join(here, "shift", "mcp-server.cjs"),
69046
+ import_node_path79.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
68872
69047
  ];
68873
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69048
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs57.default.existsSync(p2));
68874
69049
  if (shiftServerScriptPath) {
68875
- const shiftLogPath = import_node_path78.default.join(logDir, "shift-mcp-server.log");
69050
+ const shiftLogPath = import_node_path79.default.join(logDir, "shift-mcp-server.log");
68876
69051
  const shiftCfgPath = await writeShiftMcpConfig({
68877
69052
  dataDir: config.dataDir,
68878
69053
  serverScriptPath: shiftServerScriptPath,
@@ -68893,12 +69068,12 @@ async function startDaemon(config) {
68893
69068
  );
68894
69069
  }
68895
69070
  const inboxServerCandidates = [
68896
- import_node_path78.default.join(here, "inbox", "mcp-server.cjs"),
68897
- import_node_path78.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
69071
+ import_node_path79.default.join(here, "inbox", "mcp-server.cjs"),
69072
+ import_node_path79.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
68898
69073
  ];
68899
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69074
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs57.default.existsSync(p2));
68900
69075
  if (inboxServerScriptPath) {
68901
- const inboxLogPath = import_node_path78.default.join(logDir, "inbox-mcp-server.log");
69076
+ const inboxLogPath = import_node_path79.default.join(logDir, "inbox-mcp-server.log");
68902
69077
  const inboxCfgPath = await writeInboxMcpConfig({
68903
69078
  dataDir: config.dataDir,
68904
69079
  serverScriptPath: inboxServerScriptPath,
@@ -68919,10 +69094,10 @@ async function startDaemon(config) {
68919
69094
  );
68920
69095
  }
68921
69096
  const peerOpsServerCandidates = [
68922
- import_node_path78.default.join(here, "peer-ops", "mcp-server.cjs"),
68923
- import_node_path78.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
69097
+ import_node_path79.default.join(here, "peer-ops", "mcp-server.cjs"),
69098
+ import_node_path79.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
68924
69099
  ];
68925
- const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69100
+ const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs57.default.existsSync(p2));
68926
69101
  if (peerOpsServerScriptPath) {
68927
69102
  const peerOpsCfgPath = writePeerOpsMcpConfig({
68928
69103
  dataDir: config.dataDir,
@@ -68942,12 +69117,12 @@ async function startDaemon(config) {
68942
69117
  );
68943
69118
  }
68944
69119
  const rpcToolServerCandidates = [
68945
- import_node_path78.default.join(here, "rpc-tool", "mcp-server.cjs"),
68946
- import_node_path78.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
69120
+ import_node_path79.default.join(here, "rpc-tool", "mcp-server.cjs"),
69121
+ import_node_path79.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
68947
69122
  ];
68948
- const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69123
+ const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs57.default.existsSync(p2));
68949
69124
  if (rpcToolServerScriptPath) {
68950
- const rpcToolLogPath = import_node_path78.default.join(logDir, "rpc-tool-mcp-server.log");
69125
+ const rpcToolLogPath = import_node_path79.default.join(logDir, "rpc-tool-mcp-server.log");
68951
69126
  const rpcToolCfgPath = writeRpcToolMcpConfig({
68952
69127
  dataDir: config.dataDir,
68953
69128
  serverScriptPath: rpcToolServerScriptPath,
@@ -68968,18 +69143,18 @@ async function startDaemon(config) {
68968
69143
  );
68969
69144
  }
68970
69145
  const appBuilderServerCandidates = [
68971
- import_node_path78.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
68972
- import_node_path78.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
69146
+ import_node_path79.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
69147
+ import_node_path79.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
68973
69148
  ];
68974
- const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69149
+ const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs57.default.existsSync(p2));
68975
69150
  if (appBuilderServerScriptPath) {
68976
- const appBuilderLogPath = import_node_path78.default.join(logDir, "app-builder-mcp-server.log");
69151
+ const appBuilderLogPath = import_node_path79.default.join(logDir, "app-builder-mcp-server.log");
68977
69152
  const appBuilderCfgPath = writeAppBuilderMcpConfig({
68978
69153
  dataDir: config.dataDir,
68979
69154
  serverScriptPath: appBuilderServerScriptPath,
68980
69155
  daemonToken: resolvedAuthToken,
68981
69156
  daemonUrl: mcpDaemonUrl,
68982
- deployKitScriptsDir: import_node_path78.default.join(config.dataDir, "deploy-kit", "scripts"),
69157
+ deployKitScriptsDir: import_node_path79.default.join(config.dataDir, "deploy-kit", "scripts"),
68983
69158
  logPath: appBuilderLogPath
68984
69159
  });
68985
69160
  mcpConfigs.push({ id: "app-builder", path: appBuilderCfgPath, personas: APP_BUILDER_PERSONAS });
@@ -68995,7 +69170,7 @@ async function startDaemon(config) {
68995
69170
  );
68996
69171
  }
68997
69172
  const shiftStore = createShiftStore({
68998
- filePath: import_node_path78.default.join(config.dataDir, "shift.json"),
69173
+ filePath: import_node_path79.default.join(config.dataDir, "shift.json"),
68999
69174
  ownerIdProvider: () => ownerPrincipalId,
69000
69175
  now: () => Date.now()
69001
69176
  });
@@ -69017,7 +69192,7 @@ async function startDaemon(config) {
69017
69192
  getAdapter,
69018
69193
  historyReader: history,
69019
69194
  dataDir: config.dataDir,
69020
- personaRoot: import_node_path78.default.join(config.dataDir, "personas"),
69195
+ personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
69021
69196
  // dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
69022
69197
  // personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
69023
69198
  getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
@@ -69074,10 +69249,10 @@ async function startDaemon(config) {
69074
69249
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
69075
69250
  attachmentGroup: {
69076
69251
  onFileEdit: (input) => {
69077
- const absPath = import_node_path78.default.isAbsolute(input.relPath) ? input.relPath : import_node_path78.default.join(input.cwd, input.relPath);
69252
+ const absPath = import_node_path79.default.isAbsolute(input.relPath) ? input.relPath : import_node_path79.default.join(input.cwd, input.relPath);
69078
69253
  let size = 0;
69079
69254
  try {
69080
- size = import_node_fs56.default.statSync(absPath).size;
69255
+ size = import_node_fs57.default.statSync(absPath).size;
69081
69256
  } catch (err) {
69082
69257
  logger.warn("attachment.onFileEdit stat failed", {
69083
69258
  sessionId: input.sessionId,
@@ -69107,9 +69282,9 @@ async function startDaemon(config) {
69107
69282
  logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
69108
69283
  }
69109
69284
  const projectsStore = new ProjectsStore({
69110
- file: import_node_path78.default.join(config.dataDir, "projects.json"),
69285
+ file: import_node_path79.default.join(config.dataDir, "projects.json"),
69111
69286
  clawdDir: config.dataDir,
69112
- codexStateFile: import_node_path78.default.join(import_node_os26.default.homedir(), ".codex", ".codex-global-state.json"),
69287
+ codexStateFile: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex", ".codex-global-state.json"),
69113
69288
  logger
69114
69289
  });
69115
69290
  const observer = new SessionObserver({
@@ -69169,13 +69344,13 @@ async function startDaemon(config) {
69169
69344
  screenIdleProbeLogger
69170
69345
  }) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
69171
69346
  registerAdapter("claude", claudeAdapter);
69172
- const codexIsolatedHome = import_node_path78.default.join(config.dataDir, "codex-home");
69347
+ const codexIsolatedHome = import_node_path79.default.join(config.dataDir, "codex-home");
69173
69348
  try {
69174
- import_node_fs56.default.mkdirSync(codexIsolatedHome, { recursive: true });
69349
+ import_node_fs57.default.mkdirSync(codexIsolatedHome, { recursive: true });
69175
69350
  for (const f of ["auth.json", "config.toml"]) {
69176
- const link = import_node_path78.default.join(codexIsolatedHome, f);
69177
- const target = import_node_path78.default.join(import_node_os26.default.homedir(), ".codex", f);
69178
- if (!import_node_fs56.default.existsSync(link) && import_node_fs56.default.existsSync(target)) import_node_fs56.default.symlinkSync(target, link);
69351
+ const link = import_node_path79.default.join(codexIsolatedHome, f);
69352
+ const target = import_node_path79.default.join(import_node_os27.default.homedir(), ".codex", f);
69353
+ if (!import_node_fs57.default.existsSync(link) && import_node_fs57.default.existsSync(target)) import_node_fs57.default.symlinkSync(target, link);
69179
69354
  }
69180
69355
  } catch (err) {
69181
69356
  logger.warn("codex isolated home setup failed", { err: String(err) });
@@ -69188,11 +69363,11 @@ async function startDaemon(config) {
69188
69363
  // projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
69189
69364
  codexHomeFor: (cwd) => resolveCodexHome({
69190
69365
  cwd,
69191
- personaRoot: import_node_path78.default.join(config.dataDir, "personas"),
69366
+ personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
69192
69367
  // 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
69193
69368
  // Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
69194
69369
  projectPaths: projectsStore.listMerged().map((x) => x.path),
69195
- sharedHome: import_node_path78.default.join(import_node_os26.default.homedir(), ".codex"),
69370
+ sharedHome: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex"),
69196
69371
  isolatedHome: codexIsolatedHome
69197
69372
  })
69198
69373
  })
@@ -69477,11 +69652,11 @@ async function startDaemon(config) {
69477
69652
  // 'persona/<pid>/owner',default 走 'default'。
69478
69653
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
69479
69654
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
69480
- personaRoot: import_node_path78.default.join(config.dataDir, "personas"),
69655
+ personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
69481
69656
  usersRoot
69482
69657
  },
69483
69658
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
69484
- personaRoot: import_node_path78.default.join(config.dataDir, "personas"),
69659
+ personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
69485
69660
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
69486
69661
  usersRoot,
69487
69662
  // v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
@@ -69588,11 +69763,11 @@ async function startDaemon(config) {
69588
69763
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
69589
69764
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
69590
69765
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
69591
- appBuilderPersonaRoot: import_node_path78.default.join(config.dataDir, "personas", "persona-app-builder"),
69766
+ appBuilderPersonaRoot: import_node_path79.default.join(config.dataDir, "personas", "persona-app-builder"),
69592
69767
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
69593
- deployKitRoot: import_node_path78.default.join(config.dataDir, "deploy-kit"),
69768
+ deployKitRoot: import_node_path79.default.join(config.dataDir, "deploy-kit"),
69594
69769
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
69595
- resolvePersonaRoot: (personaId2) => import_node_path78.default.join(config.dataDir, "personas", personaId2),
69770
+ resolvePersonaRoot: (personaId2) => import_node_path79.default.join(config.dataDir, "personas", personaId2),
69596
69771
  // 凭据表(M1b Step 5):与 MCP 那条同一张表、同一个来源,只是交付给另一个子进程。
69597
69772
  readSecrets,
69598
69773
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
@@ -69649,7 +69824,7 @@ async function startDaemon(config) {
69649
69824
  sourceSessionId: args.sourceSessionId
69650
69825
  });
69651
69826
  const sourceFile = manager.findOwnedSession(args.sourceSessionId);
69652
- const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os26.default.homedir());
69827
+ const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os27.default.homedir());
69653
69828
  logger.info("dispatch.spawnB.source-resolved", {
69654
69829
  dispatchId: args.dispatchId,
69655
69830
  sourceJsonlPath,
@@ -69776,7 +69951,7 @@ async function startDaemon(config) {
69776
69951
  });
69777
69952
  shiftScheduler.start();
69778
69953
  logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
69779
- const larkBotStore = createLarkBotBindingStore(import_node_path78.default.join(config.dataDir, "personas"));
69954
+ const larkBotStore = createLarkBotBindingStore(import_node_path79.default.join(config.dataDir, "personas"));
69780
69955
  const larkBotCloud = createLarkBotCloudClient({
69781
69956
  api: config.clawosApi ?? DEFAULT_CLAWOS_API,
69782
69957
  apiKey: resolveClawdTicketsApiKey(),
@@ -69790,7 +69965,7 @@ async function startDaemon(config) {
69790
69965
  store: larkBotStore,
69791
69966
  fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
69792
69967
  // 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
69793
- mediaRootFor: (chatId) => import_node_path78.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
69968
+ mediaRootFor: (chatId) => import_node_path79.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
69794
69969
  isShuttingDown: () => larkDraining,
69795
69970
  logger: {
69796
69971
  warn: (msg) => logger.warn(msg),
@@ -70095,8 +70270,8 @@ async function startDaemon(config) {
70095
70270
  const lines = [
70096
70271
  `Tunnel: ${r.url}`,
70097
70272
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
70098
- `Frpc config: ${import_node_path78.default.join(config.dataDir, "frpc.toml")}`,
70099
- `Frpc log: ${import_node_path78.default.join(logDir, "frpc.log")}`
70273
+ `Frpc config: ${import_node_path79.default.join(config.dataDir, "frpc.toml")}`,
70274
+ `Frpc log: ${import_node_path79.default.join(logDir, "frpc.log")}`
70100
70275
  ];
70101
70276
  const width2 = Math.max(...lines.map((l) => l.length));
70102
70277
  const bar = "\u2550".repeat(width2 + 4);
@@ -70109,8 +70284,8 @@ ${bar}
70109
70284
 
70110
70285
  `);
70111
70286
  try {
70112
- const connectPath = import_node_path78.default.join(config.dataDir, "connect.txt");
70113
- import_node_fs56.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
70287
+ const connectPath = import_node_path79.default.join(config.dataDir, "connect.txt");
70288
+ import_node_fs57.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
70114
70289
  } catch {
70115
70290
  }
70116
70291
  } catch (err) {
@@ -70197,9 +70372,9 @@ ${bar}
70197
70372
  };
70198
70373
  }
70199
70374
  function migrateDropPersonsDir(dataDir) {
70200
- const dir = import_node_path78.default.join(dataDir, "persons");
70375
+ const dir = import_node_path79.default.join(dataDir, "persons");
70201
70376
  try {
70202
- import_node_fs56.default.rmSync(dir, { recursive: true, force: true });
70377
+ import_node_fs57.default.rmSync(dir, { recursive: true, force: true });
70203
70378
  } catch {
70204
70379
  }
70205
70380
  }