@clawos-dev/clawd 0.2.463 → 0.2.465

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: path98, errorMaps, issueData } = params;
454
- const fullPath = [...path98, ...issueData.path || []];
453
+ const { data, path: path99, errorMaps, issueData } = params;
454
+ const fullPath = [...path99, ...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, path98, key) {
765
+ constructor(parent, value, path99, key) {
766
766
  this._cachedPath = [];
767
767
  this.parent = parent;
768
768
  this.data = value;
769
- this._path = path98;
769
+ this._path = path99;
770
770
  this._key = key;
771
771
  }
772
772
  get path() {
@@ -9905,8 +9905,8 @@ var require_req = __commonJS({
9905
9905
  if (req.originalUrl) {
9906
9906
  _req.url = req.originalUrl;
9907
9907
  } else {
9908
- const path98 = req.path;
9909
- _req.url = typeof path98 === "string" ? path98 : req.url ? req.url.path || req.url : void 0;
9908
+ const path99 = req.path;
9909
+ _req.url = typeof path99 === "string" ? path99 : req.url ? req.url.path || req.url : void 0;
9910
9910
  }
9911
9911
  if (req.query) {
9912
9912
  _req.query = req.query;
@@ -10071,14 +10071,14 @@ var require_redact = __commonJS({
10071
10071
  }
10072
10072
  return obj;
10073
10073
  }
10074
- function parsePath(path98) {
10074
+ function parsePath(path99) {
10075
10075
  const parts = [];
10076
10076
  let current = "";
10077
10077
  let inBrackets = false;
10078
10078
  let inQuotes = false;
10079
10079
  let quoteChar = "";
10080
- for (let i = 0; i < path98.length; i++) {
10081
- const char = path98[i];
10080
+ for (let i = 0; i < path99.length; i++) {
10081
+ const char = path99[i];
10082
10082
  if (!inBrackets && char === ".") {
10083
10083
  if (current) {
10084
10084
  parts.push(current);
@@ -10209,10 +10209,10 @@ var require_redact = __commonJS({
10209
10209
  return current;
10210
10210
  }
10211
10211
  function redactPaths(obj, paths, censor, remove = false) {
10212
- for (const path98 of paths) {
10213
- const parts = parsePath(path98);
10212
+ for (const path99 of paths) {
10213
+ const parts = parsePath(path99);
10214
10214
  if (parts.includes("*")) {
10215
- redactWildcardPath(obj, parts, censor, path98, remove);
10215
+ redactWildcardPath(obj, parts, censor, path99, remove);
10216
10216
  } else {
10217
10217
  if (remove) {
10218
10218
  removeKey(obj, parts);
@@ -10297,8 +10297,8 @@ var require_redact = __commonJS({
10297
10297
  }
10298
10298
  } else {
10299
10299
  if (afterWildcard.includes("*")) {
10300
- const wrappedCensor = typeof censor === "function" ? (value, path98) => {
10301
- const fullPath = [...pathArray.slice(0, pathLength), ...path98];
10300
+ const wrappedCensor = typeof censor === "function" ? (value, path99) => {
10301
+ const fullPath = [...pathArray.slice(0, pathLength), ...path99];
10302
10302
  return censor(value, fullPath);
10303
10303
  } : censor;
10304
10304
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -10333,8 +10333,8 @@ var require_redact = __commonJS({
10333
10333
  return null;
10334
10334
  }
10335
10335
  const pathStructure = /* @__PURE__ */ new Map();
10336
- for (const path98 of pathsToClone) {
10337
- const parts = parsePath(path98);
10336
+ for (const path99 of pathsToClone) {
10337
+ const parts = parsePath(path99);
10338
10338
  let current = pathStructure;
10339
10339
  for (let i = 0; i < parts.length; i++) {
10340
10340
  const part = parts[i];
@@ -10386,24 +10386,24 @@ var require_redact = __commonJS({
10386
10386
  }
10387
10387
  return cloneSelectively(obj, pathStructure);
10388
10388
  }
10389
- function validatePath(path98) {
10390
- if (typeof path98 !== "string") {
10389
+ function validatePath(path99) {
10390
+ if (typeof path99 !== "string") {
10391
10391
  throw new Error("Paths must be (non-empty) strings");
10392
10392
  }
10393
- if (path98 === "") {
10393
+ if (path99 === "") {
10394
10394
  throw new Error("Invalid redaction path ()");
10395
10395
  }
10396
- if (path98.includes("..")) {
10397
- throw new Error(`Invalid redaction path (${path98})`);
10396
+ if (path99.includes("..")) {
10397
+ throw new Error(`Invalid redaction path (${path99})`);
10398
10398
  }
10399
- if (path98.includes(",")) {
10400
- throw new Error(`Invalid redaction path (${path98})`);
10399
+ if (path99.includes(",")) {
10400
+ throw new Error(`Invalid redaction path (${path99})`);
10401
10401
  }
10402
10402
  let bracketCount = 0;
10403
10403
  let inQuotes = false;
10404
10404
  let quoteChar = "";
10405
- for (let i = 0; i < path98.length; i++) {
10406
- const char = path98[i];
10405
+ for (let i = 0; i < path99.length; i++) {
10406
+ const char = path99[i];
10407
10407
  if ((char === '"' || char === "'") && bracketCount > 0) {
10408
10408
  if (!inQuotes) {
10409
10409
  inQuotes = true;
@@ -10417,20 +10417,20 @@ var require_redact = __commonJS({
10417
10417
  } else if (char === "]" && !inQuotes) {
10418
10418
  bracketCount--;
10419
10419
  if (bracketCount < 0) {
10420
- throw new Error(`Invalid redaction path (${path98})`);
10420
+ throw new Error(`Invalid redaction path (${path99})`);
10421
10421
  }
10422
10422
  }
10423
10423
  }
10424
10424
  if (bracketCount !== 0) {
10425
- throw new Error(`Invalid redaction path (${path98})`);
10425
+ throw new Error(`Invalid redaction path (${path99})`);
10426
10426
  }
10427
10427
  }
10428
10428
  function validatePaths(paths) {
10429
10429
  if (!Array.isArray(paths)) {
10430
10430
  throw new TypeError("paths must be an array");
10431
10431
  }
10432
- for (const path98 of paths) {
10433
- validatePath(path98);
10432
+ for (const path99 of paths) {
10433
+ validatePath(path99);
10434
10434
  }
10435
10435
  }
10436
10436
  function slowRedact(options = {}) {
@@ -10598,8 +10598,8 @@ var require_redaction = __commonJS({
10598
10598
  if (shape[k2] === null) {
10599
10599
  o[k2] = (value) => topCensor(value, [k2]);
10600
10600
  } else {
10601
- const wrappedCensor = typeof censor === "function" ? (value, path98) => {
10602
- return censor(value, [k2, ...path98]);
10601
+ const wrappedCensor = typeof censor === "function" ? (value, path99) => {
10602
+ return censor(value, [k2, ...path99]);
10603
10603
  } : censor;
10604
10604
  o[k2] = Redact({
10605
10605
  paths: shape[k2],
@@ -10817,10 +10817,10 @@ var require_atomic_sleep = __commonJS({
10817
10817
  var require_sonic_boom = __commonJS({
10818
10818
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
10819
10819
  "use strict";
10820
- var fs87 = require("fs");
10820
+ var fs88 = require("fs");
10821
10821
  var EventEmitter3 = require("events");
10822
10822
  var inherits = require("util").inherits;
10823
- var path98 = require("path");
10823
+ var path99 = require("path");
10824
10824
  var sleep2 = require_atomic_sleep();
10825
10825
  var assert = require("assert");
10826
10826
  var BUSY_WRITE_TIMEOUT = 100;
@@ -10874,20 +10874,20 @@ var require_sonic_boom = __commonJS({
10874
10874
  const mode = sonic.mode;
10875
10875
  if (sonic.sync) {
10876
10876
  try {
10877
- if (sonic.mkdir) fs87.mkdirSync(path98.dirname(file), { recursive: true });
10878
- const fd = fs87.openSync(file, flags, mode);
10877
+ if (sonic.mkdir) fs88.mkdirSync(path99.dirname(file), { recursive: true });
10878
+ const fd = fs88.openSync(file, flags, mode);
10879
10879
  fileOpened(null, fd);
10880
10880
  } catch (err) {
10881
10881
  fileOpened(err);
10882
10882
  throw err;
10883
10883
  }
10884
10884
  } else if (sonic.mkdir) {
10885
- fs87.mkdir(path98.dirname(file), { recursive: true }, (err) => {
10885
+ fs88.mkdir(path99.dirname(file), { recursive: true }, (err) => {
10886
10886
  if (err) return fileOpened(err);
10887
- fs87.open(file, flags, mode, fileOpened);
10887
+ fs88.open(file, flags, mode, fileOpened);
10888
10888
  });
10889
10889
  } else {
10890
- fs87.open(file, flags, mode, fileOpened);
10890
+ fs88.open(file, flags, mode, fileOpened);
10891
10891
  }
10892
10892
  }
10893
10893
  function SonicBoom(opts) {
@@ -10928,8 +10928,8 @@ var require_sonic_boom = __commonJS({
10928
10928
  this.flush = flushBuffer;
10929
10929
  this.flushSync = flushBufferSync;
10930
10930
  this._actualWrite = actualWriteBuffer;
10931
- fsWriteSync = () => fs87.writeSync(this.fd, this._writingBuf);
10932
- fsWrite = () => fs87.write(this.fd, this._writingBuf, this.release);
10931
+ fsWriteSync = () => fs88.writeSync(this.fd, this._writingBuf);
10932
+ fsWrite = () => fs88.write(this.fd, this._writingBuf, this.release);
10933
10933
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
10934
10934
  this._writingBuf = "";
10935
10935
  this.write = write;
@@ -10938,15 +10938,15 @@ var require_sonic_boom = __commonJS({
10938
10938
  this._actualWrite = actualWrite;
10939
10939
  fsWriteSync = () => {
10940
10940
  if (Buffer.isBuffer(this._writingBuf)) {
10941
- return fs87.writeSync(this.fd, this._writingBuf);
10941
+ return fs88.writeSync(this.fd, this._writingBuf);
10942
10942
  }
10943
- return fs87.writeSync(this.fd, this._writingBuf, "utf8");
10943
+ return fs88.writeSync(this.fd, this._writingBuf, "utf8");
10944
10944
  };
10945
10945
  fsWrite = () => {
10946
10946
  if (Buffer.isBuffer(this._writingBuf)) {
10947
- return fs87.write(this.fd, this._writingBuf, this.release);
10947
+ return fs88.write(this.fd, this._writingBuf, this.release);
10948
10948
  }
10949
- return fs87.write(this.fd, this._writingBuf, "utf8", this.release);
10949
+ return fs88.write(this.fd, this._writingBuf, "utf8", this.release);
10950
10950
  };
10951
10951
  } else {
10952
10952
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -11003,7 +11003,7 @@ var require_sonic_boom = __commonJS({
11003
11003
  }
11004
11004
  }
11005
11005
  if (this._fsync) {
11006
- fs87.fsyncSync(this.fd);
11006
+ fs88.fsyncSync(this.fd);
11007
11007
  }
11008
11008
  const len = this._len;
11009
11009
  if (this._reopening) {
@@ -11117,7 +11117,7 @@ var require_sonic_boom = __commonJS({
11117
11117
  const onDrain = () => {
11118
11118
  if (!this._fsync) {
11119
11119
  try {
11120
- fs87.fsync(this.fd, (err) => {
11120
+ fs88.fsync(this.fd, (err) => {
11121
11121
  this._flushPending = false;
11122
11122
  cb(err);
11123
11123
  });
@@ -11219,7 +11219,7 @@ var require_sonic_boom = __commonJS({
11219
11219
  const fd = this.fd;
11220
11220
  this.once("ready", () => {
11221
11221
  if (fd !== this.fd) {
11222
- fs87.close(fd, (err) => {
11222
+ fs88.close(fd, (err) => {
11223
11223
  if (err) {
11224
11224
  return this.emit("error", err);
11225
11225
  }
@@ -11268,7 +11268,7 @@ var require_sonic_boom = __commonJS({
11268
11268
  buf = this._bufs[0];
11269
11269
  }
11270
11270
  try {
11271
- const n = Buffer.isBuffer(buf) ? fs87.writeSync(this.fd, buf) : fs87.writeSync(this.fd, buf, "utf8");
11271
+ const n = Buffer.isBuffer(buf) ? fs88.writeSync(this.fd, buf) : fs88.writeSync(this.fd, buf, "utf8");
11272
11272
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
11273
11273
  buf = releasedBufObj.writingBuf;
11274
11274
  this._len = releasedBufObj.len;
@@ -11284,7 +11284,7 @@ var require_sonic_boom = __commonJS({
11284
11284
  }
11285
11285
  }
11286
11286
  try {
11287
- fs87.fsyncSync(this.fd);
11287
+ fs88.fsyncSync(this.fd);
11288
11288
  } catch {
11289
11289
  }
11290
11290
  }
@@ -11305,7 +11305,7 @@ var require_sonic_boom = __commonJS({
11305
11305
  buf = mergeBuf(this._bufs[0], this._lens[0]);
11306
11306
  }
11307
11307
  try {
11308
- const n = fs87.writeSync(this.fd, buf);
11308
+ const n = fs88.writeSync(this.fd, buf);
11309
11309
  buf = buf.subarray(n);
11310
11310
  this._len = Math.max(this._len - n, 0);
11311
11311
  if (buf.length <= 0) {
@@ -11333,13 +11333,13 @@ var require_sonic_boom = __commonJS({
11333
11333
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
11334
11334
  if (this.sync) {
11335
11335
  try {
11336
- const written = Buffer.isBuffer(this._writingBuf) ? fs87.writeSync(this.fd, this._writingBuf) : fs87.writeSync(this.fd, this._writingBuf, "utf8");
11336
+ const written = Buffer.isBuffer(this._writingBuf) ? fs88.writeSync(this.fd, this._writingBuf) : fs88.writeSync(this.fd, this._writingBuf, "utf8");
11337
11337
  release(null, written);
11338
11338
  } catch (err) {
11339
11339
  release(err);
11340
11340
  }
11341
11341
  } else {
11342
- fs87.write(this.fd, this._writingBuf, release);
11342
+ fs88.write(this.fd, this._writingBuf, release);
11343
11343
  }
11344
11344
  }
11345
11345
  function actualWriteBuffer() {
@@ -11348,7 +11348,7 @@ var require_sonic_boom = __commonJS({
11348
11348
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
11349
11349
  if (this.sync) {
11350
11350
  try {
11351
- const written = fs87.writeSync(this.fd, this._writingBuf);
11351
+ const written = fs88.writeSync(this.fd, this._writingBuf);
11352
11352
  release(null, written);
11353
11353
  } catch (err) {
11354
11354
  release(err);
@@ -11357,7 +11357,7 @@ var require_sonic_boom = __commonJS({
11357
11357
  if (kCopyBuffer) {
11358
11358
  this._writingBuf = Buffer.from(this._writingBuf);
11359
11359
  }
11360
- fs87.write(this.fd, this._writingBuf, release);
11360
+ fs88.write(this.fd, this._writingBuf, release);
11361
11361
  }
11362
11362
  }
11363
11363
  function actualClose(sonic) {
@@ -11373,12 +11373,12 @@ var require_sonic_boom = __commonJS({
11373
11373
  sonic._lens = [];
11374
11374
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
11375
11375
  try {
11376
- fs87.fsync(sonic.fd, closeWrapped);
11376
+ fs88.fsync(sonic.fd, closeWrapped);
11377
11377
  } catch {
11378
11378
  }
11379
11379
  function closeWrapped() {
11380
11380
  if (sonic.fd !== 1 && sonic.fd !== 2) {
11381
- fs87.close(sonic.fd, done);
11381
+ fs88.close(sonic.fd, done);
11382
11382
  } else {
11383
11383
  done();
11384
11384
  }
@@ -13742,7 +13742,7 @@ var require_multistream = __commonJS({
13742
13742
  var require_pino = __commonJS({
13743
13743
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
13744
13744
  "use strict";
13745
- var os32 = require("os");
13745
+ var os33 = require("os");
13746
13746
  var stdSerializers = require_pino_std_serializers();
13747
13747
  var caller = require_caller();
13748
13748
  var redaction = require_redaction();
@@ -13789,7 +13789,7 @@ var require_pino = __commonJS({
13789
13789
  } = symbols;
13790
13790
  var { epochTime, nullTime } = time;
13791
13791
  var { pid } = process;
13792
- var hostname = os32.hostname();
13792
+ var hostname = os33.hostname();
13793
13793
  var defaultErrorSerializer = stdSerializers.err;
13794
13794
  var defaultOptions2 = {
13795
13795
  level: "info",
@@ -14513,11 +14513,11 @@ var init_lib = __esm({
14513
14513
  }
14514
14514
  }
14515
14515
  },
14516
- addToPath: function addToPath(path98, added, removed, oldPosInc, options) {
14517
- var last = path98.lastComponent;
14516
+ addToPath: function addToPath(path99, added, removed, oldPosInc, options) {
14517
+ var last = path99.lastComponent;
14518
14518
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
14519
14519
  return {
14520
- oldPos: path98.oldPos + oldPosInc,
14520
+ oldPos: path99.oldPos + oldPosInc,
14521
14521
  lastComponent: {
14522
14522
  count: last.count + 1,
14523
14523
  added,
@@ -14527,7 +14527,7 @@ var init_lib = __esm({
14527
14527
  };
14528
14528
  } else {
14529
14529
  return {
14530
- oldPos: path98.oldPos + oldPosInc,
14530
+ oldPos: path99.oldPos + oldPosInc,
14531
14531
  lastComponent: {
14532
14532
  count: 1,
14533
14533
  added,
@@ -15109,10 +15109,10 @@ function attachmentToHistoryMessage(o, ts) {
15109
15109
  const memories = raw.map((m2) => {
15110
15110
  if (!m2 || typeof m2 !== "object") return null;
15111
15111
  const rec4 = m2;
15112
- const path98 = typeof rec4.path === "string" ? rec4.path : null;
15112
+ const path99 = typeof rec4.path === "string" ? rec4.path : null;
15113
15113
  const content = typeof rec4.content === "string" ? rec4.content : null;
15114
- if (!path98 || content == null) return null;
15115
- const entry = { path: path98, content };
15114
+ if (!path99 || content == null) return null;
15115
+ const entry = { path: path99, content };
15116
15116
  if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
15117
15117
  return entry;
15118
15118
  }).filter((m2) => m2 !== null);
@@ -15978,10 +15978,10 @@ function parseAttachment(obj) {
15978
15978
  const memories = raw.map((m2) => {
15979
15979
  if (!m2 || typeof m2 !== "object") return null;
15980
15980
  const rec4 = m2;
15981
- const path98 = typeof rec4.path === "string" ? rec4.path : null;
15981
+ const path99 = typeof rec4.path === "string" ? rec4.path : null;
15982
15982
  const content = typeof rec4.content === "string" ? rec4.content : null;
15983
- if (!path98 || content == null) return null;
15984
- const out = { path: path98, content };
15983
+ if (!path99 || content == null) return null;
15984
+ const out = { path: path99, content };
15985
15985
  if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
15986
15986
  return out;
15987
15987
  }).filter((m2) => m2 !== null);
@@ -23490,14 +23490,14 @@ var require_luxon = __commonJS({
23490
23490
  return normalized;
23491
23491
  }
23492
23492
  function formatOffset(offset2, format) {
23493
- const hours = Math.trunc(Math.abs(offset2 / 60)), minutes = Math.trunc(Math.abs(offset2 % 60)), sign = offset2 >= 0 ? "+" : "-";
23493
+ const hours = Math.trunc(Math.abs(offset2 / 60)), minutes = Math.trunc(Math.abs(offset2 % 60)), sign2 = offset2 >= 0 ? "+" : "-";
23494
23494
  switch (format) {
23495
23495
  case "short":
23496
- return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
23496
+ return `${sign2}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
23497
23497
  case "narrow":
23498
- return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`;
23498
+ return `${sign2}${hours}${minutes > 0 ? `:${minutes}` : ""}`;
23499
23499
  case "techie":
23500
- return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;
23500
+ return `${sign2}${padStart(hours, 2)}${padStart(minutes, 2)}`;
23501
23501
  default:
23502
23502
  throw new RangeError(`Value format ${format} is out of range for property format`);
23503
23503
  }
@@ -36955,8 +36955,8 @@ var require_utils = __commonJS({
36955
36955
  var result = transform[inputType][outputType](input);
36956
36956
  return result;
36957
36957
  };
36958
- exports2.resolve = function(path98) {
36959
- var parts = path98.split("/");
36958
+ exports2.resolve = function(path99) {
36959
+ var parts = path99.split("/");
36960
36960
  var result = [];
36961
36961
  for (var index = 0; index < parts.length; index++) {
36962
36962
  var part = parts[index];
@@ -42809,18 +42809,18 @@ var require_object = __commonJS({
42809
42809
  var object = new ZipObject(name, zipObjectContent, o);
42810
42810
  this.files[name] = object;
42811
42811
  };
42812
- var parentFolder = function(path98) {
42813
- if (path98.slice(-1) === "/") {
42814
- path98 = path98.substring(0, path98.length - 1);
42812
+ var parentFolder = function(path99) {
42813
+ if (path99.slice(-1) === "/") {
42814
+ path99 = path99.substring(0, path99.length - 1);
42815
42815
  }
42816
- var lastSlash = path98.lastIndexOf("/");
42817
- return lastSlash > 0 ? path98.substring(0, lastSlash) : "";
42816
+ var lastSlash = path99.lastIndexOf("/");
42817
+ return lastSlash > 0 ? path99.substring(0, lastSlash) : "";
42818
42818
  };
42819
- var forceTrailingSlash = function(path98) {
42820
- if (path98.slice(-1) !== "/") {
42821
- path98 += "/";
42819
+ var forceTrailingSlash = function(path99) {
42820
+ if (path99.slice(-1) !== "/") {
42821
+ path99 += "/";
42822
42822
  }
42823
- return path98;
42823
+ return path99;
42824
42824
  };
42825
42825
  var folderAdd = function(name, createFolders) {
42826
42826
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -43822,7 +43822,7 @@ var require_lib3 = __commonJS({
43822
43822
  // src/run-case/recorder.ts
43823
43823
  function startRunCaseRecorder(opts) {
43824
43824
  const now = opts.now ?? Date.now;
43825
- const dir = import_node_path80.default.dirname(opts.recordPath);
43825
+ const dir = import_node_path81.default.dirname(opts.recordPath);
43826
43826
  let stream = null;
43827
43827
  let closing = false;
43828
43828
  let closedSettled = false;
@@ -43862,12 +43862,12 @@ function startRunCaseRecorder(opts) {
43862
43862
  };
43863
43863
  return { tap, close, closed };
43864
43864
  }
43865
- var import_node_fs57, import_node_path80;
43865
+ var import_node_fs57, import_node_path81;
43866
43866
  var init_recorder = __esm({
43867
43867
  "src/run-case/recorder.ts"() {
43868
43868
  "use strict";
43869
43869
  import_node_fs57 = __toESM(require("fs"), 1);
43870
- import_node_path80 = __toESM(require("path"), 1);
43870
+ import_node_path81 = __toESM(require("path"), 1);
43871
43871
  }
43872
43872
  });
43873
43873
 
@@ -43910,7 +43910,7 @@ var init_wire = __esm({
43910
43910
  // src/run-case/controller.ts
43911
43911
  async function runController(opts) {
43912
43912
  const now = opts.now ?? Date.now;
43913
- const cwd = opts.cwd ?? (0, import_node_fs58.mkdtempSync)(import_node_path81.default.join(import_node_os28.default.tmpdir(), "clawd-runcase-"));
43913
+ const cwd = opts.cwd ?? (0, import_node_fs58.mkdtempSync)(import_node_path82.default.join(import_node_os29.default.tmpdir(), "clawd-runcase-"));
43914
43914
  const ownsCwd = opts.cwd === void 0;
43915
43915
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
43916
43916
  const spawnCtx = { cwd };
@@ -44077,13 +44077,13 @@ async function runController(opts) {
44077
44077
  }
44078
44078
  return exitCode ?? 0;
44079
44079
  }
44080
- var import_node_fs58, import_node_os28, import_node_path81;
44080
+ var import_node_fs58, import_node_os29, import_node_path82;
44081
44081
  var init_controller = __esm({
44082
44082
  "src/run-case/controller.ts"() {
44083
44083
  "use strict";
44084
44084
  import_node_fs58 = require("fs");
44085
- import_node_os28 = __toESM(require("os"), 1);
44086
- import_node_path81 = __toESM(require("path"), 1);
44085
+ import_node_os29 = __toESM(require("os"), 1);
44086
+ import_node_path82 = __toESM(require("path"), 1);
44087
44087
  init_claude();
44088
44088
  init_stdout_splitter();
44089
44089
  init_permission_stdio();
@@ -44358,10 +44358,10 @@ Env (advanced):
44358
44358
  `;
44359
44359
 
44360
44360
  // src/index.ts
44361
- var import_node_path79 = __toESM(require("path"), 1);
44361
+ var import_node_path80 = __toESM(require("path"), 1);
44362
44362
  var import_node_fs56 = __toESM(require("fs"), 1);
44363
- var import_node_os27 = __toESM(require("os"), 1);
44364
- var import_node_crypto22 = require("crypto");
44363
+ var import_node_os28 = __toESM(require("os"), 1);
44364
+ var import_node_crypto23 = require("crypto");
44365
44365
  var import_node_url5 = require("url");
44366
44366
 
44367
44367
  // src/logger.ts
@@ -51616,8 +51616,8 @@ function turnStartInput(text) {
51616
51616
  const items = [];
51617
51617
  let leftover = text;
51618
51618
  for (const m2 of text.matchAll(SKILL_RE)) {
51619
- const [marker, name, path98] = m2;
51620
- items.push({ type: "skill", name, path: path98 });
51619
+ const [marker, name, path99] = m2;
51620
+ items.push({ type: "skill", name, path: path99 });
51621
51621
  leftover = leftover.replace(marker, "");
51622
51622
  }
51623
51623
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -55169,9 +55169,87 @@ function createSecretStore(deps) {
55169
55169
  var import_promises6 = __toESM(require("fs/promises"), 1);
55170
55170
  var import_node_path32 = __toESM(require("path"), 1);
55171
55171
  var CLOUD_HOST_CONFIG_FILE = "cloud-host.json";
55172
- var REQUIRED = ["provisionDir", "gatewayUrl", "gatewayAdminKey", "gatewayApiKey", "k3sHost", "k3sKeyPath"];
55172
+ var REQUIRED = ["provisionDir", "gatewayUrl", "gatewayAdminKey", "gatewayApiKey"];
55173
55173
  var CloudHostConfigError = class extends Error {
55174
55174
  };
55175
+ var looksLikeRegistryRef = (s) => {
55176
+ const head = s.split("/")[0] ?? "";
55177
+ return s.includes("/") && (head.includes(".") || head.includes(":"));
55178
+ };
55179
+ var EXAMPLE_FILE = "cloud-host/deploy/cloud-host.json.example";
55180
+ function ghaGaps(parsed, imageRepo) {
55181
+ const gaps = [];
55182
+ if (!parsed.baseImage) {
55183
+ gaps.push({
55184
+ field: "baseImage",
55185
+ why: "persona \u5C42\u8981 FROM \u4E00\u4E2A\u5E95\u5EA7\u955C\u50CF\u3002\u5FC5\u987B\u662F\u4E0D\u53EF\u53D8\u7684 sha tag\uFF0C\u4E14\u7528**\u516C\u7F51**\u5730\u5740\u2014\u2014\u6784\u5EFA\u8DD1\u5728\u5883\u5916\u7684 runner \u4E0A\uFF0CVPC \u5730\u5740\u5B83\u89E3\u6790\u4E0D\u4E86",
55186
+ example: "registry.cn-hangzhou.aliyuncs.com/ttc-prod/clawd-persona-cloud:base-<40 \u4F4D sha>",
55187
+ where: "GitHub Actions \u91CC\u300CBuild persona-cloud base image\u300D\u6700\u8FD1\u4E00\u6B21\u6210\u529F run \u7684 Summary\uFF0C\u90A3\u5F20\u8868\u91CC\u76F4\u63A5\u7ED9\u4E86\u8FD9\u4E00\u884C"
55188
+ });
55189
+ }
55190
+ const gh2 = parsed.github;
55191
+ if (!gh2?.repo) {
55192
+ gaps.push({
55193
+ field: "github.repo",
55194
+ why: "\u5F80\u54EA\u4E2A\u4ED3\u5E93\u89E6\u53D1\u6784\u5EFA",
55195
+ example: "ottin4ttc/clawos",
55196
+ where: "\u5C31\u662F\u653E workflow \u7684\u90A3\u4E2A\u4ED3\u5E93"
55197
+ });
55198
+ }
55199
+ if (!gh2?.token) {
55200
+ gaps.push({
55201
+ field: "github.token",
55202
+ why: "\u89E6\u53D1 workflow_dispatch\u3001\u8F6E\u8BE2 run\u3001\u5931\u8D25\u65F6\u8BFB job \u65E5\u5FD7",
55203
+ example: "ghp_\u2026 / github_pat_\u2026",
55204
+ where: "`gh auth token`\uFF08classic token \u7684 `repo` scope \u5C31\u591F\uFF0C\u5DF2\u5B9E\u6D4B\u53EF\u89E6\u53D1\uFF09\uFF1B\u6216\u5EFA\u4E00\u4E2A fine-grained PAT\uFF0C\u5BF9\u8BE5\u4ED3\u5E93\u7ED9 **Actions: read and write** + **Contents: read**"
55205
+ });
55206
+ }
55207
+ const store = parsed.bundleStore;
55208
+ if (!store?.bucket || !store?.endpoint) {
55209
+ gaps.push({
55210
+ field: "bundleStore.bucket / bundleStore.endpoint",
55211
+ why: "persona \u76EE\u5F55\u7ECF\u8FD9\u4E2A\u79C1\u6709\u6876\u4E2D\u8F6C\u7ED9 runner\uFF08\u4E0D\u8D70 workflow inputs\uFF1A\u90A3\u513F\u6709 64KB \u4E0A\u9650\uFF0C\u800C\u4E14\u5165\u53C2\u4F1A\u957F\u671F\u663E\u793A\u5728 run \u9875\u9762\u4E0A\uFF09",
55212
+ example: '"bucket": "clawd-persona-bundle", "endpoint": "oss-cn-hangzhou.aliyuncs.com"',
55213
+ where: "endpoint \u7528**\u516C\u7F51**\u5730\u5740\uFF08\u4E0B\u8F7D\u65B9\u662F\u5883\u5916\u7684 runner\uFF0C\u5185\u7F51\u5730\u5740\u5B83\u8FDE\u4E0D\u4E0A\uFF09\u3002\u6876\u8981\u662F\u79C1\u6709\u7684\uFF0C\u5EFA\u8BAE\u7ED9\u4E2D\u8F6C\u524D\u7F00\u6302\u4E00\u6761\u300CN \u5929\u81EA\u52A8\u8FC7\u671F\u300D\u7684\u751F\u547D\u5468\u671F\u89C4\u5219\u515C\u5E95"
55214
+ });
55215
+ }
55216
+ if (!store?.accessKeyId || !store?.accessKeySecret) {
55217
+ gaps.push({
55218
+ field: "bundleStore.accessKeyId / bundleStore.accessKeySecret",
55219
+ why: "\u5F80\u90A3\u4E2A\u6876\u4F20\u5BF9\u8C61\u3001\u7B7E URL\u3001\u7528\u5B8C\u5220\u5BF9\u8C61",
55220
+ example: '"accessKeyId": "LTAI\u2026", "accessKeySecret": "\u2026"',
55221
+ where: "\u5EFA\u6876\u90A3\u4E2A\u963F\u91CC\u4E91\u8D26\u53F7\u4E0B\u7684 AccessKey\uFF08`~/.aliyun/config.json` \u91CC\u5C31\u6709\uFF09\u3002\u53EA\u9700\u8981\u5BF9\u8FD9\u4E00\u4E2A\u6876\u53EF\u8BFB\u5199"
55222
+ });
55223
+ }
55224
+ if (!looksLikeRegistryRef(imageRepo)) {
55225
+ gaps.push({
55226
+ field: "imageRepo",
55227
+ why: `\u73B0\u5728\u662F \`${imageRepo}\`\uFF0C\u6CA1\u6709 registry \u524D\u7F00\u3002\u8FD9\u4E2A\u503C\u4F1A**\u539F\u6837\u8FDB\u90E8\u7F72\u767B\u8BB0\u8868**\uFF0Ckubelet \u7167\u5B83\u53BB\u62C9\uFF1B\u6CA1\u524D\u7F00\u4F1A\u88AB\u89E3\u6790\u6210 \`docker.io/library/\u2026\`\uFF0C\u62A5\u51FA\u6765\u662F\u300C\u8FDE\u4E0D\u4E0A Docker Hub\u300D\u800C\u4E0D\u662F\u300C\u8282\u70B9\u4E0A\u6CA1\u8FD9\u4E2A\u955C\u50CF\u300D`,
55228
+ example: "registry-vpc.cn-hangzhou.aliyuncs.com/ttc-prod/clawd-persona-cloud",
55229
+ where: "\u8DDF baseImage \u662F**\u540C\u4E00\u4E2A ACR \u4ED3\u5E93**\uFF0C\u4F46\u8FD9\u91CC\u8981 **VPC \u5185\u7F51**\u5730\u5740\uFF08\u4E91\u5BBF\u4E3B\u6309\u5B83\u62C9\uFF09\uFF0CbaseImage \u90A3\u8FB9\u8981\u516C\u7F51\u5730\u5740\uFF08runner \u6309\u5B83\u62C9\uFF09\u3002\u522B\u5199\u53CD"
55230
+ });
55231
+ }
55232
+ return gaps;
55233
+ }
55234
+ function formatGaps(file, gaps, hasLocalCoords) {
55235
+ const lines = [
55236
+ `${file} \u8FD8\u5DEE ${gaps.length} \u9879\u624D\u80FD\u7528 buildHost=gha \u8DD1\u8BD5\u88C5\uFF08\u955C\u50CF\u5207\u6210\u300C\u5E95\u5EA7 + persona \u5C42\u300D\u4E4B\u540E\u65B0\u589E\u7684\uFF0C\u65E7\u914D\u7F6E\u5347\u4E0A\u6765\u90FD\u4F1A\u7F3A\uFF09\uFF1A`,
55237
+ ""
55238
+ ];
55239
+ for (const g2 of gaps) {
55240
+ lines.push(` \xB7 ${g2.field} \u2014\u2014 ${g2.why}`);
55241
+ lines.push(` \u793A\u4F8B\uFF1A${g2.example}`);
55242
+ lines.push(` \u4ECE\u54EA\u62FF\uFF1A${g2.where}`);
55243
+ lines.push("");
55244
+ }
55245
+ lines.push(`\u5B8C\u6574\u793A\u4F8B\u89C1 ${EXAMPLE_FILE}\u3002`);
55246
+ if (hasLocalCoords) {
55247
+ lines.push(
55248
+ '\u4E0D\u60F3\u73B0\u5728\u914D\u8FD9\u4E9B\u7684\u8BDD\uFF1A\u8FD9\u4EFD\u914D\u7F6E\u91CC\u5DF2\u7ECF\u6709 k3sHost / k3sKeyPath \u4E86\uFF0C\u52A0\u4E00\u884C `"buildHost": "local"` \u5C31\u9000\u56DE\u672C\u673A docker \u6784\u5EFA + \u4FA7\u8F7D\u90A3\u6761\u8DEF\uFF08\u8981\u672C\u673A\u6709 docker\uFF09\u3002'
55249
+ );
55250
+ }
55251
+ return lines.join("\n");
55252
+ }
55175
55253
  async function loadCloudHostConfig(dataDir) {
55176
55254
  const file = import_node_path32.default.join(dataDir, CLOUD_HOST_CONFIG_FILE);
55177
55255
  let raw;
@@ -55180,7 +55258,7 @@ async function loadCloudHostConfig(dataDir) {
55180
55258
  } catch (err) {
55181
55259
  if (err.code === "ENOENT") {
55182
55260
  throw new CloudHostConfigError(
55183
- `\u8FD8\u6CA1\u914D ${file}\u3002\u8BD5\u88C5\u8981\u77E5\u9053\u5F80\u54EA\u53F0\u673A\u5668\u63A8\u955C\u50CF\u3001\u8DDF\u54EA\u4E2A gateway \u8BF4\u8BDD\uFF0C\u5B57\u6BB5\u89C1 specs/2026-09-03-persona-cloud-m1b-trial-design.md \u7B2C\u4E94\u8282\u3002`
55261
+ `\u8FD8\u6CA1\u914D ${file}\u3002\u8BD5\u88C5\u8981\u77E5\u9053\u955C\u50CF\u5728\u54EA\u513F\u6784\u3001\u8DDF\u54EA\u4E2A gateway \u8BF4\u8BDD\uFF0C\u5B57\u6BB5\u89C1 specs/2026-09-04-persona-cloud-base-image-design.md\u3002`
55184
55262
  );
55185
55263
  }
55186
55264
  throw err;
@@ -55195,24 +55273,284 @@ async function loadCloudHostConfig(dataDir) {
55195
55273
  if (missing.length > 0) {
55196
55274
  throw new CloudHostConfigError(`${file} \u7F3A\u5B57\u6BB5\uFF1A${missing.join(" / ")}`);
55197
55275
  }
55276
+ const buildHost = parsed.buildHost === "local" ? "local" : "gha";
55277
+ const imageRepo = parsed.imageRepo ?? "clawd-persona-cloud";
55278
+ if (buildHost === "local") {
55279
+ const need = ["k3sHost", "k3sKeyPath"].filter((k2) => !parsed[k2]);
55280
+ if (need.length > 0) {
55281
+ throw new CloudHostConfigError(`${file} \u7684 buildHost \u662F local\uFF0C\u8FD8\u7F3A\uFF1A${need.join(" / ")}`);
55282
+ }
55283
+ } else {
55284
+ const gaps = ghaGaps(parsed, imageRepo);
55285
+ if (gaps.length > 0) {
55286
+ throw new CloudHostConfigError(
55287
+ formatGaps(file, gaps, Boolean(parsed.k3sHost && parsed.k3sKeyPath))
55288
+ );
55289
+ }
55290
+ }
55198
55291
  return {
55199
55292
  provisionDir: parsed.provisionDir,
55200
55293
  gatewayUrl: parsed.gatewayUrl.replace(/\/+$/, ""),
55201
55294
  gatewayAdminKey: parsed.gatewayAdminKey,
55202
55295
  gatewayApiKey: parsed.gatewayApiKey,
55203
- k3sHost: parsed.k3sHost,
55204
- k3sKeyPath: parsed.k3sKeyPath,
55205
- imageRepo: parsed.imageRepo ?? "clawd-persona-cloud",
55296
+ buildHost,
55297
+ imageRepo,
55298
+ ...parsed.baseImage ? { baseImage: parsed.baseImage } : {},
55299
+ ...parsed.github ? {
55300
+ github: {
55301
+ repo: parsed.github.repo,
55302
+ token: parsed.github.token,
55303
+ ref: parsed.github.ref ?? "release",
55304
+ workflow: parsed.github.workflow ?? "build-persona-deploy-image.yml"
55305
+ }
55306
+ } : {},
55307
+ ...parsed.bundleStore ? {
55308
+ bundleStore: {
55309
+ endpoint: parsed.bundleStore.endpoint,
55310
+ bucket: parsed.bundleStore.bucket,
55311
+ accessKeyId: parsed.bundleStore.accessKeyId,
55312
+ accessKeySecret: parsed.bundleStore.accessKeySecret,
55313
+ prefix: parsed.bundleStore.prefix ?? "persona-bundles/"
55314
+ }
55315
+ } : {},
55316
+ ...parsed.k3sHost ? { k3sHost: parsed.k3sHost } : {},
55317
+ ...parsed.k3sKeyPath ? { k3sKeyPath: parsed.k3sKeyPath } : {},
55206
55318
  trialTimeoutMs: parsed.trialTimeoutMs ?? 45 * 6e4
55207
55319
  };
55208
55320
  }
55209
55321
 
55210
55322
  // src/deploy/trial-runner.ts
55323
+ var import_promises8 = __toESM(require("fs/promises"), 1);
55324
+ var import_node_os9 = __toESM(require("os"), 1);
55325
+ var import_node_path34 = __toESM(require("path"), 1);
55326
+
55327
+ // src/deploy/bundle-store.ts
55328
+ var import_node_crypto7 = __toESM(require("crypto"), 1);
55211
55329
  var import_promises7 = __toESM(require("fs/promises"), 1);
55212
55330
  var import_node_os8 = __toESM(require("os"), 1);
55213
55331
  var import_node_path33 = __toESM(require("path"), 1);
55332
+ var import_node_child_process8 = require("child_process");
55333
+ var BUNDLE_URL_TTL_SEC = 30 * 60;
55334
+ var RUNTIME_STATE = /* @__PURE__ */ new Set(["projects", ".attachments", ".clawd/sessions"]);
55335
+ var NEVER_PERSONA = /* @__PURE__ */ new Set(["node_modules", ".git"]);
55336
+ async function stagePersonaDir(personaDir) {
55337
+ const stage = await import_promises7.default.mkdtemp(import_node_path33.default.join(import_node_os8.default.tmpdir(), "clawd-bundle-"));
55338
+ const root = import_node_path33.default.resolve(personaDir);
55339
+ await import_promises7.default.cp(root, import_node_path33.default.join(stage, "persona"), {
55340
+ recursive: true,
55341
+ dereference: true,
55342
+ filter: (src) => {
55343
+ const rel = import_node_path33.default.relative(root, import_node_path33.default.resolve(src));
55344
+ if (!rel) return true;
55345
+ return !RUNTIME_STATE.has(rel) && !NEVER_PERSONA.has(import_node_path33.default.basename(rel));
55346
+ }
55347
+ });
55348
+ return { dir: stage, cleanup: () => import_promises7.default.rm(stage, { recursive: true, force: true }) };
55349
+ }
55350
+ async function packPersonaBundle(personaDir) {
55351
+ const { dir: stage, cleanup } = await stagePersonaDir(personaDir);
55352
+ const file = import_node_path33.default.join(stage, "bundle.tgz");
55353
+ await new Promise((resolve9, reject) => {
55354
+ const child = (0, import_node_child_process8.spawn)("tar", ["-czf", file, "-C", stage, "persona"], { stdio: ["ignore", "ignore", "pipe"] });
55355
+ let err = "";
55356
+ child.stderr.on("data", (d) => {
55357
+ err += d.toString("utf8");
55358
+ });
55359
+ child.on("error", (e) => reject(new Error(`\u6253\u5305 persona \u76EE\u5F55\u8D77\u4E0D\u6765 tar\uFF1A${e.message}`)));
55360
+ child.on("close", (code) => code === 0 ? resolve9() : reject(new Error(`tar \u9000\u51FA\u7801 ${code}\uFF1A${err.slice(-500)}`)));
55361
+ });
55362
+ return { file, cleanup };
55363
+ }
55364
+ function sign(cfg, args) {
55365
+ const canonical = [
55366
+ args.method,
55367
+ args.contentMd5 ?? "",
55368
+ args.contentType ?? "",
55369
+ args.dateOrExpires,
55370
+ `/${cfg.bucket}/${args.key}`
55371
+ ].join("\n");
55372
+ return import_node_crypto7.default.createHmac("sha1", cfg.accessKeySecret).update(canonical).digest("base64");
55373
+ }
55374
+ var objectUrl = (cfg, key) => `https://${cfg.bucket}.${cfg.endpoint}/${key.split("/").map(encodeURIComponent).join("/")}`;
55375
+ async function putBundle(cfg, key, body, fetchImpl = fetch, now = () => Date.now()) {
55376
+ const date = new Date(now()).toUTCString();
55377
+ const contentType = "application/gzip";
55378
+ const contentMd5 = import_node_crypto7.default.createHash("md5").update(body).digest("base64");
55379
+ const res = await fetchImpl(objectUrl(cfg, key), {
55380
+ method: "PUT",
55381
+ headers: {
55382
+ Date: date,
55383
+ "Content-Type": contentType,
55384
+ "Content-MD5": contentMd5,
55385
+ Authorization: `OSS ${cfg.accessKeyId}:${sign(cfg, { method: "PUT", key, dateOrExpires: date, contentMd5, contentType })}`
55386
+ },
55387
+ body: new Uint8Array(body)
55388
+ });
55389
+ if (!res.ok) {
55390
+ const text = await res.text().catch(() => "");
55391
+ throw new Error(`bundle \u4F20\u4E0D\u4E0A OSS\uFF08HTTP ${res.status}\uFF09\uFF1A${text.slice(0, 400)}`);
55392
+ }
55393
+ const expires = String(Math.floor(now() / 1e3) + BUNDLE_URL_TTL_SEC);
55394
+ const sig = sign(cfg, { method: "GET", key, dateOrExpires: expires });
55395
+ const q = new URLSearchParams({
55396
+ OSSAccessKeyId: cfg.accessKeyId,
55397
+ Expires: expires,
55398
+ Signature: sig
55399
+ });
55400
+ return { key, url: `${objectUrl(cfg, key)}?${q.toString()}`, bytes: body.length };
55401
+ }
55402
+ async function removeBundle(cfg, key, fetchImpl = fetch, now = () => Date.now()) {
55403
+ const date = new Date(now()).toUTCString();
55404
+ try {
55405
+ const res = await fetchImpl(objectUrl(cfg, key), {
55406
+ method: "DELETE",
55407
+ headers: {
55408
+ Date: date,
55409
+ Authorization: `OSS ${cfg.accessKeyId}:${sign(cfg, { method: "DELETE", key, dateOrExpires: date })}`
55410
+ }
55411
+ });
55412
+ return res.ok || res.status === 404;
55413
+ } catch {
55414
+ return false;
55415
+ }
55416
+ }
55417
+
55418
+ // src/deploy/gha-build.ts
55419
+ var POLL_MS = 5e3;
55420
+ var CLAIM_TIMEOUT_MS = 12e4;
55421
+ var LOG_TAIL_CHARS = 4e3;
55422
+ var GAP_MARKER = "::clawd-build-gaps::";
55423
+ function gapsFromRunnerLog(log) {
55424
+ const i = log.lastIndexOf(GAP_MARKER);
55425
+ if (i === -1) return [];
55426
+ const line = log.slice(i + GAP_MARKER.length).split("\n")[0].trim();
55427
+ try {
55428
+ const parsed = JSON.parse(line);
55429
+ if (!Array.isArray(parsed)) return [];
55430
+ return parsed.filter((g2) => g2 && typeof g2.errorText === "string" && g2.errorText.length > 0).map((g2) => ({
55431
+ errorText: g2.errorText,
55432
+ ...g2.raw ? { raw: g2.raw } : {},
55433
+ ...g2.suggest ? { suggest: g2.suggest } : {}
55434
+ }));
55435
+ } catch {
55436
+ return [];
55437
+ }
55438
+ }
55439
+ async function gh(deps, url, init) {
55440
+ const res = await deps.fetchImpl(`https://api.github.com${url}`, {
55441
+ ...init,
55442
+ headers: {
55443
+ accept: "application/vnd.github+json",
55444
+ authorization: `Bearer ${deps.github.token}`,
55445
+ "x-github-api-version": "2022-11-28",
55446
+ ...init?.body ? { "content-type": "application/json" } : {},
55447
+ ...init?.headers
55448
+ }
55449
+ });
55450
+ if (!res.ok) {
55451
+ const text = await res.text().catch(() => "");
55452
+ throw new Error(`GitHub ${init?.method ?? "GET"} ${url} \u2192 HTTP ${res.status}\uFF1A${text.slice(0, 400)}`);
55453
+ }
55454
+ if (res.status === 204) return void 0;
55455
+ return await res.json();
55456
+ }
55457
+ async function claimRun(deps, tag) {
55458
+ const { repo: repo2, workflow } = deps.github;
55459
+ const deadline = deps.now() + CLAIM_TIMEOUT_MS;
55460
+ for (; ; ) {
55461
+ const list = await gh(
55462
+ deps,
55463
+ `/repos/${repo2}/actions/workflows/${encodeURIComponent(workflow)}/runs?event=workflow_dispatch&per_page=30`
55464
+ );
55465
+ const hit = list.workflow_runs.find((r) => [r.name, r.display_title].some((n) => typeof n === "string" && n.includes(tag)));
55466
+ if (hit) return hit;
55467
+ if (deps.now() > deadline) {
55468
+ throw new Error(
55469
+ `\u89E6\u53D1\u4E4B\u540E ${Math.round(CLAIM_TIMEOUT_MS / 1e3)}s \u6CA1\u5728 ${repo2} \u7684 ${workflow} \u91CC\u627E\u5230 run-name \u5E26 \`${tag}\` \u7684 run\u3002workflow \u6587\u4EF6\u5728\u76EE\u6807 ref \u4E0A\u5B58\u5728\u5417\uFF1F\u5B83\u7684 run-name \u91CC\u5E26 inputs.tag \u5417\uFF1F`
55470
+ );
55471
+ }
55472
+ await deps.sleep(POLL_MS);
55473
+ }
55474
+ }
55475
+ async function failureDetail(deps, run) {
55476
+ const { repo: repo2 } = deps.github;
55477
+ try {
55478
+ const jobs = await gh(
55479
+ deps,
55480
+ `/repos/${repo2}/actions/runs/${run.id}/jobs`
55481
+ );
55482
+ const failed = jobs.jobs.find((j) => j.conclusion && j.conclusion !== "success");
55483
+ if (!failed) return { raw: "", gaps: [] };
55484
+ const step = failed.steps?.find((s) => s.conclusion && s.conclusion !== "success");
55485
+ const res = await deps.fetchImpl(`https://api.github.com/repos/${repo2}/actions/jobs/${failed.id}/logs`, {
55486
+ headers: { authorization: `Bearer ${deps.github.token}`, "x-github-api-version": "2022-11-28" }
55487
+ });
55488
+ const log = res.ok ? await res.text() : "";
55489
+ return {
55490
+ gaps: gapsFromRunnerLog(log),
55491
+ raw: [
55492
+ `\u5931\u8D25\u7684\u6B65\u9AA4\uFF1A${failed.name}${step ? ` / ${step.name}` : ""}`,
55493
+ log ? log.slice(-LOG_TAIL_CHARS) : "\uFF08\u65E5\u5FD7\u53D6\u4E0D\u5230\uFF09"
55494
+ ].join("\n")
55495
+ };
55496
+ } catch (err) {
55497
+ return { raw: `\uFF08\u53D6\u5931\u8D25\u8BE6\u60C5\u65F6\u53C8\u51FA\u9519\u4E86\uFF1A${String(err)}\uFF09`, gaps: [] };
55498
+ }
55499
+ }
55500
+ async function buildOnGha(deps, args) {
55501
+ const { repo: repo2, ref, workflow } = deps.github;
55502
+ const started = deps.now();
55503
+ try {
55504
+ deps.onStage("\u5728 GitHub \u4E0A\u6392\u4E00\u6B21\u955C\u50CF\u6784\u5EFA");
55505
+ await gh(deps, `/repos/${repo2}/actions/workflows/${encodeURIComponent(workflow)}/dispatches`, {
55506
+ method: "POST",
55507
+ body: JSON.stringify({ ref, inputs: args.inputs })
55508
+ });
55509
+ } catch (err) {
55510
+ return { ok: false, errorText: `\u89E6\u53D1\u4E0D\u4E86 ${repo2} \u7684 ${workflow}\uFF1A${String(err)}` };
55511
+ }
55512
+ let run;
55513
+ try {
55514
+ run = await claimRun(deps, args.inputs.tag);
55515
+ } catch (err) {
55516
+ return { ok: false, errorText: String(err) };
55517
+ }
55518
+ deps.onStage(`\u955C\u50CF\u6784\u5EFA\u8DD1\u8D77\u6765\u4E86\uFF1A${run.html_url}`);
55519
+ const deadline = started + args.timeoutMs;
55520
+ for (; ; ) {
55521
+ if (deps.now() > deadline) {
55522
+ return {
55523
+ ok: false,
55524
+ runUrl: run.html_url,
55525
+ errorText: `\u7B49\u4E86 ${Math.round(args.timeoutMs / 6e4)} \u5206\u949F\uFF0C\u955C\u50CF\u8FD8\u6CA1\u6784\u5B8C\uFF1A${run.html_url}`
55526
+ };
55527
+ }
55528
+ await deps.sleep(POLL_MS);
55529
+ let cur;
55530
+ try {
55531
+ cur = await gh(deps, `/repos/${repo2}/actions/runs/${run.id}`);
55532
+ } catch (err) {
55533
+ deps.onStage(`\u95EE GitHub \u6784\u5EFA\u8FDB\u5C55\u6CA1\u95EE\u7740\uFF08\u4F1A\u91CD\u8BD5\uFF09\uFF1A${String(err).slice(0, 120)}`);
55534
+ continue;
55535
+ }
55536
+ if (cur.status !== "completed") continue;
55537
+ const seconds = Math.round((deps.now() - started) / 1e3);
55538
+ if (cur.conclusion === "success") return { ok: true, runUrl: cur.html_url, seconds };
55539
+ const detail = await failureDetail(deps, cur);
55540
+ return {
55541
+ ok: false,
55542
+ runUrl: cur.html_url,
55543
+ errorText: `\u955C\u50CF\u6CA1\u6784\u6210\uFF08${cur.conclusion}\uFF09\uFF1A${cur.html_url}`,
55544
+ raw: detail.raw,
55545
+ ...detail.gaps.length > 0 ? { gaps: detail.gaps } : {}
55546
+ };
55547
+ }
55548
+ }
55549
+
55550
+ // src/deploy/trial-runner.ts
55214
55551
  var RAW_TAIL_CHARS = 2e3;
55215
55552
  var GATEWAY_ADMIN_TIMEOUT_MS = 3e4;
55553
+ var MAX_BUNDLE_BYTES = 64 * 1024 * 1024;
55216
55554
  var trialStamp = (nowMs) => Math.floor(nowMs / 1e3).toString(36);
55217
55555
  var trialImageTag = (repo2, deployId, round, stamp) => `${repo2}:${trialDeployId(deployId, round, stamp)}`;
55218
55556
  var trialDeployId = (deployId, round, stamp) => `${deployId}-t${round}-${stamp}`;
@@ -55371,8 +55709,8 @@ async function* sseLines(res) {
55371
55709
  }
55372
55710
  if (buf.trim()) yield buf.trim();
55373
55711
  }
55374
- async function gatewayAdmin(deps, path98, body) {
55375
- const res = await deps.fetchImpl(`${deps.cloudHost.gatewayUrl}${path98}`, {
55712
+ async function gatewayAdmin(deps, path99, body) {
55713
+ const res = await deps.fetchImpl(`${deps.cloudHost.gatewayUrl}${path99}`, {
55376
55714
  method: "POST",
55377
55715
  headers: {
55378
55716
  "content-type": "application/json",
@@ -55385,11 +55723,11 @@ async function gatewayAdmin(deps, path98, body) {
55385
55723
  signal: AbortSignal.timeout(GATEWAY_ADMIN_TIMEOUT_MS)
55386
55724
  });
55387
55725
  const text = await res.text();
55388
- if (!res.ok) throw new Error(`gateway ${path98} \u56DE\u4E86 HTTP ${res.status}\uFF1A${text.slice(0, 300)}`);
55726
+ if (!res.ok) throw new Error(`gateway ${path99} \u56DE\u4E86 HTTP ${res.status}\uFF1A${text.slice(0, 300)}`);
55389
55727
  try {
55390
55728
  return JSON.parse(text);
55391
55729
  } catch {
55392
- throw new Error(`gateway ${path98} \u56DE\u7684\u4E0D\u662F JSON\uFF1A${text.slice(0, 300)}`);
55730
+ throw new Error(`gateway ${path99} \u56DE\u7684\u4E0D\u662F JSON\uFF1A${text.slice(0, 300)}`);
55393
55731
  }
55394
55732
  }
55395
55733
  async function registerOfficialDeployment(deps, receipt, deployerSecrets) {
@@ -55414,41 +55752,168 @@ async function registerOfficialDeployment(deps, receipt, deployerSecrets) {
55414
55752
  deployedAt: deps.now()
55415
55753
  };
55416
55754
  }
55417
- async function runTrial(deps, args) {
55418
- const { receipt, round } = args;
55755
+ async function buildViaGha(deps, args) {
55419
55756
  const { cloudHost } = deps;
55420
- const manifest = receipt.manifest;
55421
- const stamp = trialStamp(deps.now());
55422
- const trialId = trialDeployId(receipt.deployId, round, stamp);
55423
- const image = trialImageTag(cloudHost.imageRepo, receipt.deployId, round, stamp);
55424
- const appName = trialAppName(receipt.deployId);
55425
- const deadline = deps.now() + cloudHost.trialTimeoutMs;
55757
+ const store = cloudHost.bundleStore;
55758
+ const github = cloudHost.github;
55759
+ const baseImage = cloudHost.baseImage;
55760
+ if (!store || !github || !baseImage) {
55761
+ return { ok: false, gaps: [gap(
55762
+ `cloud-host.json \u7684 buildHost \u662F gha\uFF0C\u4F46\u7F3A ${[
55763
+ !github && "github",
55764
+ !store && "bundleStore",
55765
+ !baseImage && "baseImage"
55766
+ ].filter(Boolean).join(" / ")}\u3002`
55767
+ )] };
55768
+ }
55769
+ const key = `${store.prefix}${args.tag}.tgz`;
55770
+ deps.onStage("\u5728\u6253\u5305 persona \u76EE\u5F55");
55771
+ let packed;
55772
+ try {
55773
+ packed = await packPersonaBundle(args.personaDir);
55774
+ } catch (err) {
55775
+ return { ok: false, gaps: [gap(`\u6253\u4E0D\u51FA persona \u76EE\u5F55\u7684\u5305\uFF1A${String(err)}`)] };
55776
+ }
55777
+ try {
55778
+ const body = await import_promises8.default.readFile(packed.file);
55779
+ if (body.length > MAX_BUNDLE_BYTES) {
55780
+ return { ok: false, gaps: [gap(
55781
+ `persona \u76EE\u5F55\u6253\u5B8C\u5305\u8FD8\u6709 ${Math.round(body.length / 1e6)} MB\uFF0C\u8D85\u8FC7 ${MAX_BUNDLE_BYTES / 1e6} MB \u5C31\u4E0D\u4F20\u4E86\u3002\u955C\u50CF\u91CC\u53EA\u8BE5\u6709\u4EBA\u683C\uFF0C\u9879\u76EE / \u4F1A\u8BDD\u8BB0\u5F55 / \u9644\u4EF6\u8FD9\u4E9B\u8FD0\u884C\u671F\u72B6\u6001\u5728\u4E91\u4E0A\u662F\u6302\u8F7D\u5377\u3002`,
55782
+ args.personaDir
55783
+ )] };
55784
+ }
55785
+ let ref;
55786
+ try {
55787
+ ref = await putBundle(store, key, body, deps.fetchImpl, deps.now);
55788
+ } catch (err) {
55789
+ return { ok: false, gaps: [gap(`persona \u76EE\u5F55\u4F20\u4E0D\u4E0A\u4E2D\u8F6C\u4ED3\u5E93\uFF1A${String(err)}`)] };
55790
+ }
55791
+ deps.onStage(`persona \u76EE\u5F55\u9001\u4E0A\u53BB\u4E86\uFF08${Math.round(ref.bytes / 1024)} KB\uFF09`);
55792
+ const built = await buildOnGha(
55793
+ {
55794
+ github,
55795
+ fetchImpl: deps.fetchImpl,
55796
+ now: deps.now,
55797
+ sleep: deps.sleep,
55798
+ onStage: deps.onStage
55799
+ },
55800
+ {
55801
+ timeoutMs: args.timeoutMs,
55802
+ inputs: {
55803
+ tag: args.tag,
55804
+ base_image: baseImage,
55805
+ bundle_url: ref.url,
55806
+ manifest_b64: Buffer.from(JSON.stringify({ manifest: args.manifest })).toString("base64")
55807
+ }
55808
+ }
55809
+ );
55810
+ if (!built.ok) {
55811
+ return {
55812
+ ok: false,
55813
+ gaps: built.gaps?.length ? built.gaps.map((g2) => gap(g2.errorText, g2.raw ?? built.raw, g2.suggest)) : [gap(built.errorText, built.raw)]
55814
+ };
55815
+ }
55816
+ deps.logger?.info("deploy.trial.image-built", { tag: args.tag, seconds: built.seconds, run: built.runUrl });
55817
+ return { ok: true };
55818
+ } catch (err) {
55819
+ return { ok: false, gaps: [gap(`\u6784\u955C\u50CF\u8FD9\u4E00\u6B65\u8D77\u4E0D\u6765\uFF1A${String(err)}`)] };
55820
+ } finally {
55821
+ await packed.cleanup().catch(() => {
55822
+ });
55823
+ const gone = await removeBundle(store, key, deps.fetchImpl, deps.now);
55824
+ if (!gone) deps.logger?.warn("deploy.trial.bundle-not-removed", { key });
55825
+ }
55826
+ }
55827
+ async function buildLocally(deps, args) {
55828
+ const { cloudHost } = deps;
55829
+ const baseTag = `${cloudHost.imageRepo}:base-local`;
55830
+ const deadline = deps.now() + args.timeoutMs;
55426
55831
  const left = () => Math.max(3e4, deadline - deps.now());
55427
- deps.onStage("\u5728\u6309\u6E05\u5355\u6784\u955C\u50CF");
55428
- const manifestFile = import_node_path33.default.join(import_node_os8.default.tmpdir(), `clawd-trial-${receipt.deployId}-t${round}-${stamp}.json`);
55832
+ deps.onStage("\u5728\u672C\u673A\u6784\u5E95\u5EA7");
55833
+ const base = await deps.runNode(
55834
+ `${cloudHost.provisionDir}/build-image.mjs`,
55835
+ [
55836
+ "--base",
55837
+ "--manifest",
55838
+ `${cloudHost.provisionDir}/manifests/base.json`,
55839
+ "--tag",
55840
+ baseTag,
55841
+ "--platform",
55842
+ "linux/amd64",
55843
+ "--context",
55844
+ `${cloudHost.provisionDir}/build-context-base`
55845
+ ],
55846
+ { timeoutMs: left() }
55847
+ );
55848
+ if (base.code !== 0) return { ok: false, gaps: gapsFromBuildOutput(base) };
55849
+ deps.onStage("\u5728\u6309\u6E05\u5355\u6784 persona \u5C42");
55850
+ const manifestFile = import_node_path34.default.join(import_node_os9.default.tmpdir(), `clawd-trial-${args.tmpKey}.json`);
55429
55851
  let built;
55852
+ let staged;
55853
+ try {
55854
+ staged = await stagePersonaDir(args.personaDir);
55855
+ } catch (err) {
55856
+ return { ok: false, gaps: [gap(`\u7406\u4E0D\u51FA\u8981\u6253\u8FDB\u955C\u50CF\u7684 persona \u76EE\u5F55\uFF1A${String(err)}`)] };
55857
+ }
55430
55858
  try {
55431
- await import_promises7.default.writeFile(manifestFile, JSON.stringify({ manifest }, null, 2), { mode: 384 });
55859
+ await import_promises8.default.writeFile(manifestFile, JSON.stringify({ manifest: args.manifest }, null, 2), { mode: 384 });
55432
55860
  built = await deps.runNode(
55433
55861
  `${cloudHost.provisionDir}/build-image.mjs`,
55434
- ["--manifest", manifestFile, "--tag", image, "--platform", "linux/amd64"],
55862
+ [
55863
+ "--manifest",
55864
+ manifestFile,
55865
+ "--from",
55866
+ baseTag,
55867
+ "--persona-dir",
55868
+ import_node_path34.default.join(staged.dir, "persona"),
55869
+ "--tag",
55870
+ args.image,
55871
+ "--platform",
55872
+ "linux/amd64"
55873
+ ],
55435
55874
  { timeoutMs: left() }
55436
55875
  );
55437
- await import_promises7.default.rm(manifestFile, { force: true });
55876
+ await import_promises8.default.rm(manifestFile, { force: true });
55438
55877
  } catch (err) {
55439
- return { ok: false, spent: false, gaps: [gap(`\u6784\u955C\u50CF\u8FD9\u4E00\u6B65\u8D77\u4E0D\u6765\uFF1A${String(err)}`)] };
55878
+ return { ok: false, gaps: [gap(`\u6784\u955C\u50CF\u8FD9\u4E00\u6B65\u8D77\u4E0D\u6765\uFF1A${String(err)}`)] };
55879
+ } finally {
55880
+ await staged.cleanup().catch(() => {
55881
+ });
55440
55882
  }
55441
- if (built.code !== 0) return { ok: false, spent: false, gaps: gapsFromBuildOutput(built) };
55883
+ if (built.code !== 0) return { ok: false, gaps: gapsFromBuildOutput(built) };
55442
55884
  deps.onStage("\u628A\u955C\u50CF\u63A8\u5230\u4E91\u4E0A\u90A3\u53F0\u673A\u5668");
55885
+ if (!cloudHost.k3sHost || !cloudHost.k3sKeyPath) {
55886
+ return { ok: false, gaps: [gap("cloud-host.json \u7684 buildHost \u662F local\uFF0C\u4F46\u7F3A k3sHost / k3sKeyPath\u3002")] };
55887
+ }
55443
55888
  const pushed = await deps.runNode(
55444
55889
  `${cloudHost.provisionDir}/push-to-k3s.mjs`,
55445
- ["--host", cloudHost.k3sHost, "--key", cloudHost.k3sKeyPath, "--image", image],
55890
+ ["--host", cloudHost.k3sHost, "--key", cloudHost.k3sKeyPath, "--image", args.image],
55446
55891
  { timeoutMs: left() }
55447
55892
  );
55448
55893
  if (pushed.code !== 0) {
55449
- return { ok: false, spent: false, gaps: [gap(`\u955C\u50CF\u63A8\u4E0D\u4E0A\u53BB\uFF08\u9000\u51FA\u7801 ${pushed.code}\uFF09\u3002`, `${pushed.stdout}
55894
+ return { ok: false, gaps: [gap(`\u955C\u50CF\u63A8\u4E0D\u4E0A\u53BB\uFF08\u9000\u51FA\u7801 ${pushed.code}\uFF09\u3002`, `${pushed.stdout}
55450
55895
  ${pushed.stderr}`)] };
55451
55896
  }
55897
+ return { ok: true };
55898
+ }
55899
+ async function runTrial(deps, args) {
55900
+ const { receipt, round } = args;
55901
+ const { cloudHost } = deps;
55902
+ const manifest = receipt.manifest;
55903
+ const stamp = trialStamp(deps.now());
55904
+ const trialId = trialDeployId(receipt.deployId, round, stamp);
55905
+ const image = trialImageTag(cloudHost.imageRepo, receipt.deployId, round, stamp);
55906
+ const appName = trialAppName(receipt.deployId);
55907
+ const deadline = deps.now() + cloudHost.trialTimeoutMs;
55908
+ const left = () => Math.max(3e4, deadline - deps.now());
55909
+ const buildOutcome = cloudHost.buildHost === "local" ? await buildLocally(deps, {
55910
+ manifest,
55911
+ personaDir: args.personaDir,
55912
+ image,
55913
+ timeoutMs: left(),
55914
+ tmpKey: `${receipt.deployId}-t${round}-${stamp}`
55915
+ }) : await buildViaGha(deps, { manifest, personaDir: args.personaDir, tag: trialId, timeoutMs: left() });
55916
+ if (!buildOutcome.ok) return { ok: false, spent: false, gaps: buildOutcome.gaps };
55452
55917
  deps.onStage("\u5728\u4E91\u4E0A\u767B\u8BB0\u8FD9\u6B21\u8BD5\u88C5");
55453
55918
  try {
55454
55919
  await gatewayAdmin(deps, "/admin/deployments", {
@@ -55514,10 +55979,10 @@ ${pushed.stderr}`)] };
55514
55979
  }
55515
55980
 
55516
55981
  // src/deploy/run-node.ts
55517
- var import_node_child_process8 = require("child_process");
55982
+ var import_node_child_process9 = require("child_process");
55518
55983
  async function runNodeScript(script, args, timeoutMs) {
55519
55984
  return await new Promise((resolve9, reject) => {
55520
- const child = (0, import_node_child_process8.spawn)(process.execPath, [script, ...args], { stdio: ["ignore", "pipe", "pipe"] });
55985
+ const child = (0, import_node_child_process9.spawn)(process.execPath, [script, ...args], { stdio: ["ignore", "pipe", "pipe"] });
55521
55986
  let stdout = "";
55522
55987
  let stderr = "";
55523
55988
  child.stdout.on("data", (d) => {
@@ -55960,9 +56425,9 @@ async function refreshTunnelUrlOnStartup(deps) {
55960
56425
 
55961
56426
  // src/lark-bot-connector/binding-store.ts
55962
56427
  var import_node_fs28 = __toESM(require("fs"), 1);
55963
- var import_node_path34 = __toESM(require("path"), 1);
56428
+ var import_node_path35 = __toESM(require("path"), 1);
55964
56429
  function createLarkBotBindingStore(personaRoot) {
55965
- const filePath = (personaId2) => import_node_path34.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
56430
+ const filePath = (personaId2) => import_node_path35.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
55966
56431
  const read = (personaId2) => {
55967
56432
  const file = filePath(personaId2);
55968
56433
  if (!import_node_fs28.default.existsSync(file)) return null;
@@ -55976,7 +56441,7 @@ function createLarkBotBindingStore(personaRoot) {
55976
56441
  };
55977
56442
  const write = (personaId2, meta) => {
55978
56443
  const file = filePath(personaId2);
55979
- import_node_fs28.default.mkdirSync(import_node_path34.default.dirname(file), { recursive: true });
56444
+ import_node_fs28.default.mkdirSync(import_node_path35.default.dirname(file), { recursive: true });
55980
56445
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
55981
56446
  import_node_fs28.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
55982
56447
  import_node_fs28.default.renameSync(tmp, file);
@@ -56144,7 +56609,7 @@ function createLarkBotCloudClient(opts) {
56144
56609
 
56145
56610
  // src/lark-bot-connector/chat-router.ts
56146
56611
  var import_node_fs29 = __toESM(require("fs"), 1);
56147
- var import_node_path35 = __toESM(require("path"), 1);
56612
+ var import_node_path36 = __toESM(require("path"), 1);
56148
56613
  init_protocol();
56149
56614
  var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
56150
56615
  var LOCAL_TURN_RETRIES = 2;
@@ -56211,7 +56676,7 @@ function createLarkChatRouter(deps) {
56211
56676
  }
56212
56677
  const dir = deps.mediaRootFor(env.chatId);
56213
56678
  import_node_fs29.default.mkdirSync(dir, { recursive: true });
56214
- const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
56679
+ const p2 = import_node_path36.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
56215
56680
  import_node_fs29.default.writeFileSync(p2, r.data);
56216
56681
  lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56217
56682
  } catch (err) {
@@ -56234,7 +56699,7 @@ function createLarkChatRouter(deps) {
56234
56699
  }
56235
56700
  const dir = deps.mediaRootFor(env.chatId);
56236
56701
  import_node_fs29.default.mkdirSync(dir, { recursive: true });
56237
- const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
56702
+ const p2 = import_node_path36.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
56238
56703
  import_node_fs29.default.writeFileSync(p2, r.data);
56239
56704
  lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56240
56705
  } catch (err) {
@@ -56430,7 +56895,7 @@ ${formatLarkSpeakerReminder(speaker)}`
56430
56895
  }
56431
56896
 
56432
56897
  // src/lark-bot-connector/envelope.ts
56433
- var import_node_crypto7 = require("crypto");
56898
+ var import_node_crypto8 = require("crypto");
56434
56899
  var LARK_ENVELOPE_PREFIX = "clawdlbe1";
56435
56900
  function verifyLarkEventEnvelope(args) {
56436
56901
  const { token, publicKeyPem } = args;
@@ -56449,7 +56914,7 @@ function verifyLarkEventEnvelope(args) {
56449
56914
  const data = Buffer.from(`${prefix}.${payloadB64}`, "utf8");
56450
56915
  let sigOk = false;
56451
56916
  try {
56452
- sigOk = (0, import_node_crypto7.verify)(null, data, publicKeyPem, Buffer.from(sigB64, "base64url"));
56917
+ sigOk = (0, import_node_crypto8.verify)(null, data, publicKeyPem, Buffer.from(sigB64, "base64url"));
56453
56918
  } catch {
56454
56919
  sigOk = false;
56455
56920
  }
@@ -57324,7 +57789,7 @@ var CodexHistoryReader = class {
57324
57789
  };
57325
57790
 
57326
57791
  // src/tools/codex-skills.ts
57327
- var import_node_path36 = __toESM(require("path"), 1);
57792
+ var import_node_path37 = __toESM(require("path"), 1);
57328
57793
  function str3(v2) {
57329
57794
  return typeof v2 === "string" ? v2 : void 0;
57330
57795
  }
@@ -57339,13 +57804,13 @@ function mapSkillsListResponse(res) {
57339
57804
  const r = s ?? {};
57340
57805
  const name = str3(r.name);
57341
57806
  if (!name) continue;
57342
- const path98 = str3(r.path);
57807
+ const path99 = str3(r.path);
57343
57808
  const description = str3(r.description);
57344
57809
  const isPlugin = name.includes(":");
57345
57810
  out.push({
57346
57811
  name,
57347
57812
  source: isPlugin ? "plugin" : "project",
57348
- ...path98 ? { path: path98 } : {},
57813
+ ...path99 ? { path: path99 } : {},
57349
57814
  ...description ? { description } : {},
57350
57815
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
57351
57816
  });
@@ -57361,14 +57826,14 @@ async function listCodexSkills(cwd, deps = {}) {
57361
57826
  // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
57362
57827
  // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
57363
57828
  beforeRequest: (client) => {
57364
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path36.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
57829
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path37.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
57365
57830
  }
57366
57831
  });
57367
57832
  return mapSkillsListResponse(res);
57368
57833
  }
57369
57834
 
57370
57835
  // src/tools/codex-turn-context.ts
57371
- var import_promises8 = __toESM(require("fs/promises"), 1);
57836
+ var import_promises9 = __toESM(require("fs/promises"), 1);
57372
57837
  function parseTurnContextFromRollout(raw) {
57373
57838
  const lines = raw.split("\n");
57374
57839
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -57403,7 +57868,7 @@ async function readCodexTurnContext(args, deps = {}) {
57403
57868
  );
57404
57869
  const rolloutPath = str4(rec3(res?.thread)?.path);
57405
57870
  if (!rolloutPath) return null;
57406
- return parseTurnContextFromRollout(await import_promises8.default.readFile(rolloutPath, "utf8"));
57871
+ return parseTurnContextFromRollout(await import_promises9.default.readFile(rolloutPath, "utf8"));
57407
57872
  }
57408
57873
  function createCodexResolvedMetaHydrator(deps) {
57409
57874
  const fetchedThreadIds = /* @__PURE__ */ new Set();
@@ -57447,15 +57912,15 @@ function str4(v2) {
57447
57912
 
57448
57913
  // src/workspace/browser.ts
57449
57914
  var import_node_fs30 = __toESM(require("fs"), 1);
57450
- var import_node_os9 = __toESM(require("os"), 1);
57451
- var import_node_path37 = __toESM(require("path"), 1);
57915
+ var import_node_os10 = __toESM(require("os"), 1);
57916
+ var import_node_path38 = __toESM(require("path"), 1);
57452
57917
  init_protocol();
57453
57918
  var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
57454
57919
  function resolveInsideCwd(cwd, subpath) {
57455
- const absCwd = import_node_path37.default.resolve(cwd);
57456
- const joined = import_node_path37.default.resolve(absCwd, subpath ?? ".");
57457
- const rel = import_node_path37.default.relative(absCwd, joined);
57458
- if (rel.startsWith("..") || import_node_path37.default.isAbsolute(rel)) {
57920
+ const absCwd = import_node_path38.default.resolve(cwd);
57921
+ const joined = import_node_path38.default.resolve(absCwd, subpath ?? ".");
57922
+ const rel = import_node_path38.default.relative(absCwd, joined);
57923
+ if (rel.startsWith("..") || import_node_path38.default.isAbsolute(rel)) {
57459
57924
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
57460
57925
  }
57461
57926
  return joined;
@@ -57473,7 +57938,7 @@ function ensureCwd(cwd) {
57473
57938
  }
57474
57939
  var WorkspaceBrowser = class {
57475
57940
  list(args) {
57476
- const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os9.default.homedir();
57941
+ const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os10.default.homedir();
57477
57942
  ensureCwd(cwd);
57478
57943
  const full = resolveInsideCwd(cwd, args.path);
57479
57944
  const dirents = import_node_fs30.default.readdirSync(full, { withFileTypes: true });
@@ -57486,7 +57951,7 @@ var WorkspaceBrowser = class {
57486
57951
  mtime: ""
57487
57952
  };
57488
57953
  try {
57489
- const st = import_node_fs30.default.statSync(import_node_path37.default.join(full, d.name));
57954
+ const st = import_node_fs30.default.statSync(import_node_path38.default.join(full, d.name));
57490
57955
  entry.mtime = new Date(st.mtimeMs).toISOString();
57491
57956
  if (d.isFile()) entry.size = st.size;
57492
57957
  } catch {
@@ -57532,8 +57997,8 @@ var WorkspaceBrowser = class {
57532
57997
 
57533
57998
  // src/skills/agents-scanner.ts
57534
57999
  var import_node_fs31 = __toESM(require("fs"), 1);
57535
- var import_node_os10 = __toESM(require("os"), 1);
57536
- var import_node_path38 = __toESM(require("path"), 1);
58000
+ var import_node_os11 = __toESM(require("os"), 1);
58001
+ var import_node_path39 = __toESM(require("path"), 1);
57537
58002
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
57538
58003
  function isDirLikeSync2(p2) {
57539
58004
  try {
@@ -57571,10 +58036,10 @@ function scanAgentsDir(dir, source, seen, out) {
57571
58036
  }
57572
58037
  for (const ent of entries) {
57573
58038
  if (!ent.name.endsWith(".md")) continue;
57574
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path38.default.join(dir, ent.name)))) {
58039
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path39.default.join(dir, ent.name)))) {
57575
58040
  continue;
57576
58041
  }
57577
- const filePath = import_node_path38.default.join(dir, ent.name);
58042
+ const filePath = import_node_path39.default.join(dir, ent.name);
57578
58043
  const baseName = ent.name.replace(/\.md$/, "");
57579
58044
  if (seen.has(baseName)) continue;
57580
58045
  seen.add(baseName);
@@ -57597,7 +58062,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
57597
58062
  return;
57598
58063
  }
57599
58064
  for (const ent of entries) {
57600
- const childPath = import_node_path38.default.join(dir, ent.name);
58065
+ const childPath = import_node_path39.default.join(dir, ent.name);
57601
58066
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
57602
58067
  walk2(childPath, [...namespaces, ent.name]);
57603
58068
  continue;
@@ -57622,9 +58087,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
57622
58087
  walk2(root, []);
57623
58088
  }
57624
58089
  function readInstalledPlugins2(home) {
57625
- const pluginsDir = import_node_path38.default.join(home, ".claude", "plugins");
57626
- const v2 = import_node_path38.default.join(pluginsDir, "installed_plugins_v2.json");
57627
- const v1 = import_node_path38.default.join(pluginsDir, "installed_plugins.json");
58090
+ const pluginsDir = import_node_path39.default.join(home, ".claude", "plugins");
58091
+ const v2 = import_node_path39.default.join(pluginsDir, "installed_plugins_v2.json");
58092
+ const v1 = import_node_path39.default.join(pluginsDir, "installed_plugins.json");
57628
58093
  let raw = null;
57629
58094
  for (const candidate of [v2, v1]) {
57630
58095
  try {
@@ -57653,19 +58118,19 @@ function readInstalledPlugins2(home) {
57653
58118
  return out;
57654
58119
  }
57655
58120
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
57656
- let cur = import_node_path38.default.resolve(startCwd);
57657
- const fsRoot = import_node_path38.default.parse(cur).root;
58121
+ let cur = import_node_path39.default.resolve(startCwd);
58122
+ const fsRoot = import_node_path39.default.parse(cur).root;
57658
58123
  while (true) {
57659
- scanAgentsDir(import_node_path38.default.join(cur, ".claude", "agents"), "project", seen, out);
58124
+ scanAgentsDir(import_node_path39.default.join(cur, ".claude", "agents"), "project", seen, out);
57660
58125
  let hasGit = false;
57661
58126
  try {
57662
- hasGit = import_node_fs31.default.existsSync(import_node_path38.default.join(cur, ".git"));
58127
+ hasGit = import_node_fs31.default.existsSync(import_node_path39.default.join(cur, ".git"));
57663
58128
  } catch {
57664
58129
  }
57665
58130
  if (hasGit) return;
57666
58131
  if (cur === home) return;
57667
58132
  if (cur === fsRoot) return;
57668
- const parent = import_node_path38.default.dirname(cur);
58133
+ const parent = import_node_path39.default.dirname(cur);
57669
58134
  if (parent === cur) return;
57670
58135
  cur = parent;
57671
58136
  }
@@ -57675,7 +58140,7 @@ var AgentsScanner = class {
57675
58140
  extraPluginRoots;
57676
58141
  policyDir;
57677
58142
  constructor(opts = {}) {
57678
- this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os10.default.homedir();
58143
+ this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os11.default.homedir();
57679
58144
  this.extraPluginRoots = opts.extraPluginRoots ?? [];
57680
58145
  if (opts.policyDir !== void 0) {
57681
58146
  this.policyDir = opts.policyDir;
@@ -57700,7 +58165,7 @@ var AgentsScanner = class {
57700
58165
  }
57701
58166
  const fsBlock = [];
57702
58167
  scanAgentsDir(
57703
- import_node_path38.default.join(this.home, ".claude", "agents"),
58168
+ import_node_path39.default.join(this.home, ".claude", "agents"),
57704
58169
  "global",
57705
58170
  seen,
57706
58171
  fsBlock
@@ -57714,7 +58179,7 @@ var AgentsScanner = class {
57714
58179
  ...this.extraPluginRoots
57715
58180
  ];
57716
58181
  for (const { name, root } of plugins) {
57717
- const agentsRoot = import_node_path38.default.join(root, "agents");
58182
+ const agentsRoot = import_node_path39.default.join(root, "agents");
57718
58183
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
57719
58184
  }
57720
58185
  return [...builtinBlock, ...fsBlock];
@@ -57723,27 +58188,27 @@ var AgentsScanner = class {
57723
58188
 
57724
58189
  // src/observer/session-observer.ts
57725
58190
  var import_node_fs33 = __toESM(require("fs"), 1);
57726
- var import_node_os12 = __toESM(require("os"), 1);
57727
- var import_node_path40 = __toESM(require("path"), 1);
58191
+ var import_node_os13 = __toESM(require("os"), 1);
58192
+ var import_node_path41 = __toESM(require("path"), 1);
57728
58193
  init_claude_history();
57729
58194
 
57730
58195
  // src/observer/subagent-meta-observer.ts
57731
58196
  var import_node_fs32 = __toESM(require("fs"), 1);
57732
- var import_node_os11 = __toESM(require("os"), 1);
57733
- var import_node_path39 = __toESM(require("path"), 1);
58197
+ var import_node_os12 = __toESM(require("os"), 1);
58198
+ var import_node_path40 = __toESM(require("path"), 1);
57734
58199
  init_claude_history();
57735
58200
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
57736
58201
  var SubagentMetaObserver = class {
57737
58202
  constructor(opts) {
57738
58203
  this.opts = opts;
57739
- this.home = opts.home ?? import_node_os11.default.homedir();
58204
+ this.home = opts.home ?? import_node_os12.default.homedir();
57740
58205
  }
57741
58206
  opts;
57742
58207
  home;
57743
58208
  watches = /* @__PURE__ */ new Map();
57744
58209
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
57745
58210
  resolveSubagentDir(cwd, toolSessionId) {
57746
- return import_node_path39.default.join(
58211
+ return import_node_path40.default.join(
57747
58212
  this.home,
57748
58213
  ".claude",
57749
58214
  "projects",
@@ -57799,7 +58264,7 @@ var SubagentMetaObserver = class {
57799
58264
  if (!m2) return;
57800
58265
  const agentId = m2[1];
57801
58266
  if (w2.emitted.has(agentId)) return;
57802
- const file = import_node_path39.default.join(w2.dirPath, name);
58267
+ const file = import_node_path40.default.join(w2.dirPath, name);
57803
58268
  let raw;
57804
58269
  try {
57805
58270
  raw = import_node_fs32.default.readFileSync(file, "utf8");
@@ -57847,7 +58312,7 @@ var SubagentMetaObserver = class {
57847
58312
  var SessionObserver = class {
57848
58313
  constructor(opts) {
57849
58314
  this.opts = opts;
57850
- this.home = opts.home ?? import_node_os12.default.homedir();
58315
+ this.home = opts.home ?? import_node_os13.default.homedir();
57851
58316
  this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
57852
58317
  }
57853
58318
  opts;
@@ -57859,7 +58324,7 @@ var SessionObserver = class {
57859
58324
  metaObserver;
57860
58325
  resolveJsonlPath(cwd, toolSessionId, override) {
57861
58326
  if (override) return override;
57862
- return import_node_path40.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
58327
+ return import_node_path41.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
57863
58328
  }
57864
58329
  start(args) {
57865
58330
  this.stop(args.sessionId);
@@ -57885,10 +58350,10 @@ var SessionObserver = class {
57885
58350
  lastDeriveMs: 0
57886
58351
  };
57887
58352
  try {
57888
- import_node_fs33.default.mkdirSync(import_node_path40.default.dirname(filePath), { recursive: true });
58353
+ import_node_fs33.default.mkdirSync(import_node_path41.default.dirname(filePath), { recursive: true });
57889
58354
  } catch {
57890
58355
  }
57891
- w2.watcher = import_node_fs33.default.watch(import_node_path40.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
58356
+ w2.watcher = import_node_fs33.default.watch(import_node_path41.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
57892
58357
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
57893
58358
  this.poll(w2);
57894
58359
  });
@@ -57985,7 +58450,7 @@ var SessionObserver = class {
57985
58450
  const now = Date.now();
57986
58451
  if (now - w2.lastRelocateScanMs < 1e3) return;
57987
58452
  w2.lastRelocateScanMs = now;
57988
- const projectsRoot = import_node_path40.default.join(this.home, ".claude", "projects");
58453
+ const projectsRoot = import_node_path41.default.join(this.home, ".claude", "projects");
57989
58454
  const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
57990
58455
  if (!found || found === w2.filePath) return;
57991
58456
  try {
@@ -57994,7 +58459,7 @@ var SessionObserver = class {
57994
58459
  }
57995
58460
  w2.filePath = found;
57996
58461
  try {
57997
- w2.watcher = import_node_fs33.default.watch(import_node_path40.default.dirname(found), { persistent: false }, (_event, changedName) => {
58462
+ w2.watcher = import_node_fs33.default.watch(import_node_path41.default.dirname(found), { persistent: false }, (_event, changedName) => {
57998
58463
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
57999
58464
  this.poll(w2);
58000
58465
  });
@@ -58114,10 +58579,10 @@ function listRegistered() {
58114
58579
  }
58115
58580
 
58116
58581
  // src/tools/title-generator.ts
58117
- var import_node_child_process9 = require("child_process");
58582
+ var import_node_child_process10 = require("child_process");
58118
58583
  var import_node_fs34 = __toESM(require("fs"), 1);
58119
- var import_node_os13 = __toESM(require("os"), 1);
58120
- var import_node_path41 = __toESM(require("path"), 1);
58584
+ var import_node_os14 = __toESM(require("os"), 1);
58585
+ var import_node_path42 = __toESM(require("path"), 1);
58121
58586
  var TITLE_GEN_DIR_PREFIX = "clawd-title-";
58122
58587
  var TITLE_MODEL_BY_TOOL = {
58123
58588
  claude: "haiku",
@@ -58188,7 +58653,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
58188
58653
  if (!text) return null;
58189
58654
  let workDir;
58190
58655
  try {
58191
- workDir = import_node_fs34.default.mkdtempSync(import_node_path41.default.join(import_node_os13.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
58656
+ workDir = import_node_fs34.default.mkdtempSync(import_node_path42.default.join(import_node_os14.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
58192
58657
  } catch {
58193
58658
  return null;
58194
58659
  }
@@ -58198,8 +58663,8 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
58198
58663
  } catch {
58199
58664
  }
58200
58665
  };
58201
- const outFile = import_node_path41.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
58202
- const schemaFile = import_node_path41.default.join(workDir, "title-schema.json");
58666
+ const outFile = import_node_path42.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
58667
+ const schemaFile = import_node_path42.default.join(workDir, "title-schema.json");
58203
58668
  if (tool === "codex") {
58204
58669
  try {
58205
58670
  import_node_fs34.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
@@ -58210,7 +58675,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
58210
58675
  }
58211
58676
  const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : process.env.CODEX_BIN ?? "codex";
58212
58677
  const args = tool === "claude" ? buildClaudeTitleArgs(buildClaudeTitlePrompt(text)) : buildCodexTitleArgs(buildTitlePrompt(text), outFile, schemaFile);
58213
- const doSpawn = deps.spawnOverride ?? ((c, a, o) => (0, import_node_child_process9.spawn)(c, a, { ...o, stdio: ["ignore", "pipe", "pipe"] }));
58678
+ const doSpawn = deps.spawnOverride ?? ((c, a, o) => (0, import_node_child_process10.spawn)(c, a, { ...o, stdio: ["ignore", "pipe", "pipe"] }));
58214
58679
  const timeoutMs = deps.timeoutMs ?? DEFAULT_TITLE_GEN_TIMEOUT_MS;
58215
58680
  return await new Promise((resolve9) => {
58216
58681
  let proc;
@@ -58274,7 +58739,7 @@ var wrapper_default = import_websocket.default;
58274
58739
 
58275
58740
  // src/transport/local-ws-server.ts
58276
58741
  var import_node_http2 = __toESM(require("http"), 1);
58277
- var import_node_crypto8 = require("crypto");
58742
+ var import_node_crypto9 = require("crypto");
58278
58743
 
58279
58744
  // src/transport/preview-proxy.ts
58280
58745
  var import_node_http = __toESM(require("http"), 1);
@@ -58558,7 +59023,7 @@ var LocalWsServer = class {
58558
59023
  }
58559
59024
  }
58560
59025
  onConnection(socket, remoteAddress) {
58561
- const id = (0, import_node_crypto8.randomUUID)();
59026
+ const id = (0, import_node_crypto9.randomUUID)();
58562
59027
  const subscribedSessions = /* @__PURE__ */ new Map();
58563
59028
  const handle = {
58564
59029
  id,
@@ -58961,8 +59426,8 @@ async function authenticate(token, deps) {
58961
59426
  }
58962
59427
 
58963
59428
  // src/legacy-cleanup.ts
58964
- var fs47 = __toESM(require("fs/promises"), 1);
58965
- var path49 = __toESM(require("path"), 1);
59429
+ var fs48 = __toESM(require("fs/promises"), 1);
59430
+ var path50 = __toESM(require("path"), 1);
58966
59431
  var LEGACY_FILES = [
58967
59432
  "personal-capability.json",
58968
59433
  "received-capabilities.json",
@@ -58971,9 +59436,9 @@ var LEGACY_FILES = [
58971
59436
  async function cleanupLegacyCapabilityFiles(dataDir, logger) {
58972
59437
  const removed = [];
58973
59438
  for (const name of LEGACY_FILES) {
58974
- const p2 = path49.join(dataDir, name);
59439
+ const p2 = path50.join(dataDir, name);
58975
59440
  try {
58976
- await fs47.unlink(p2);
59441
+ await fs48.unlink(p2);
58977
59442
  removed.push(name);
58978
59443
  logger.debug("legacy capability file removed", { file: name });
58979
59444
  } catch (err) {
@@ -58985,13 +59450,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
58985
59450
  }
58986
59451
 
58987
59452
  // src/inbox/inbox-store.ts
58988
- var fs48 = __toESM(require("fs"), 1);
58989
- var path50 = __toESM(require("path"), 1);
59453
+ var fs49 = __toESM(require("fs"), 1);
59454
+ var path51 = __toESM(require("path"), 1);
58990
59455
  var INBOX_SUBDIR = "inbox";
58991
59456
  var InboxStore = class {
58992
59457
  constructor(dataDir) {
58993
59458
  this.dataDir = dataDir;
58994
- fs48.mkdirSync(this.dirPath(), { recursive: true });
59459
+ fs49.mkdirSync(this.dirPath(), { recursive: true });
58995
59460
  }
58996
59461
  dataDir;
58997
59462
  /**
@@ -59003,7 +59468,7 @@ var InboxStore = class {
59003
59468
  const file = this.filePath(peerDeviceId);
59004
59469
  let raw;
59005
59470
  try {
59006
- raw = fs48.readFileSync(file, "utf8");
59471
+ raw = fs49.readFileSync(file, "utf8");
59007
59472
  } catch (err) {
59008
59473
  if (err?.code === "ENOENT") return [];
59009
59474
  return [];
@@ -59019,7 +59484,7 @@ var InboxStore = class {
59019
59484
  const dir = this.dirPath();
59020
59485
  let entries;
59021
59486
  try {
59022
- entries = fs48.readdirSync(dir);
59487
+ entries = fs49.readdirSync(dir);
59023
59488
  } catch (err) {
59024
59489
  if (err?.code === "ENOENT") return [];
59025
59490
  return [];
@@ -59035,9 +59500,9 @@ var InboxStore = class {
59035
59500
  if (existing.some((m2) => m2.id === message.id)) return;
59036
59501
  const file = this.filePath(message.peerDeviceId);
59037
59502
  const line = JSON.stringify(message) + "\n";
59038
- fs48.appendFileSync(file, line, { mode: 384 });
59503
+ fs49.appendFileSync(file, line, { mode: 384 });
59039
59504
  try {
59040
- fs48.chmodSync(file, 384);
59505
+ fs49.chmodSync(file, 384);
59041
59506
  } catch {
59042
59507
  }
59043
59508
  }
@@ -59067,7 +59532,7 @@ var InboxStore = class {
59067
59532
  removeByPeerDeviceId(peerDeviceId) {
59068
59533
  const file = this.filePath(peerDeviceId);
59069
59534
  try {
59070
- fs48.unlinkSync(file);
59535
+ fs49.unlinkSync(file);
59071
59536
  } catch (err) {
59072
59537
  if (err?.code === "ENOENT") return;
59073
59538
  }
@@ -59076,18 +59541,18 @@ var InboxStore = class {
59076
59541
  const file = this.filePath(peerDeviceId);
59077
59542
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
59078
59543
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
59079
- fs48.writeFileSync(tmp, content, { mode: 384 });
59080
- fs48.renameSync(tmp, file);
59544
+ fs49.writeFileSync(tmp, content, { mode: 384 });
59545
+ fs49.renameSync(tmp, file);
59081
59546
  try {
59082
- fs48.chmodSync(file, 384);
59547
+ fs49.chmodSync(file, 384);
59083
59548
  } catch {
59084
59549
  }
59085
59550
  }
59086
59551
  dirPath() {
59087
- return path50.join(this.dataDir, INBOX_SUBDIR);
59552
+ return path51.join(this.dataDir, INBOX_SUBDIR);
59088
59553
  }
59089
59554
  filePath(peerDeviceId) {
59090
- return path50.join(this.dirPath(), `${peerDeviceId}.jsonl`);
59555
+ return path51.join(this.dirPath(), `${peerDeviceId}.jsonl`);
59091
59556
  }
59092
59557
  };
59093
59558
  function parseAllLines(raw) {
@@ -59175,8 +59640,8 @@ var InboxManager = class {
59175
59640
  };
59176
59641
 
59177
59642
  // src/state/contact-store.ts
59178
- var fs49 = __toESM(require("fs"), 1);
59179
- var path51 = __toESM(require("path"), 1);
59643
+ var fs50 = __toESM(require("fs"), 1);
59644
+ var path52 = __toESM(require("path"), 1);
59180
59645
  var FILE_NAME = "contacts.json";
59181
59646
  var ContactStore = class {
59182
59647
  constructor(dataDir) {
@@ -59186,10 +59651,10 @@ var ContactStore = class {
59186
59651
  contacts = /* @__PURE__ */ new Map();
59187
59652
  load() {
59188
59653
  this.contacts.clear();
59189
- const file = path51.join(this.dataDir, FILE_NAME);
59654
+ const file = path52.join(this.dataDir, FILE_NAME);
59190
59655
  let raw;
59191
59656
  try {
59192
- raw = fs49.readFileSync(file, "utf8");
59657
+ raw = fs50.readFileSync(file, "utf8");
59193
59658
  } catch (err) {
59194
59659
  if (err?.code !== "ENOENT") this.renameBak(file);
59195
59660
  return;
@@ -59270,27 +59735,27 @@ var ContactStore = class {
59270
59735
  return true;
59271
59736
  }
59272
59737
  flush() {
59273
- const file = path51.join(this.dataDir, FILE_NAME);
59738
+ const file = path52.join(this.dataDir, FILE_NAME);
59274
59739
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
59275
59740
  const content = JSON.stringify(
59276
59741
  { contacts: Array.from(this.contacts.values()) },
59277
59742
  null,
59278
59743
  2
59279
59744
  );
59280
- fs49.mkdirSync(this.dataDir, { recursive: true });
59281
- fs49.writeFileSync(tmp, content, { mode: 384 });
59282
- fs49.renameSync(tmp, file);
59745
+ fs50.mkdirSync(this.dataDir, { recursive: true });
59746
+ fs50.writeFileSync(tmp, content, { mode: 384 });
59747
+ fs50.renameSync(tmp, file);
59283
59748
  }
59284
59749
  renameBak(file) {
59285
59750
  try {
59286
- fs49.renameSync(file, `${file}.bak`);
59751
+ fs50.renameSync(file, `${file}.bak`);
59287
59752
  } catch {
59288
59753
  }
59289
59754
  }
59290
59755
  };
59291
59756
 
59292
59757
  // src/contact/connect-remote.ts
59293
- var crypto3 = __toESM(require("crypto"), 1);
59758
+ var crypto4 = __toESM(require("crypto"), 1);
59294
59759
  init_protocol();
59295
59760
  var HANDSHAKE_TIMEOUT_MS = 5e3;
59296
59761
  var RPC_TIMEOUT_MS = 5e3;
@@ -59345,7 +59810,7 @@ async function connectRemote(args) {
59345
59810
  ws.once("close", onClose);
59346
59811
  });
59347
59812
  function call(method, payload) {
59348
- const requestId = crypto3.randomUUID();
59813
+ const requestId = crypto4.randomUUID();
59349
59814
  return new Promise((resolve9, reject) => {
59350
59815
  const onMessage = (raw) => {
59351
59816
  let f;
@@ -59391,61 +59856,61 @@ async function connectRemote(args) {
59391
59856
  }
59392
59857
 
59393
59858
  // src/migrations/2026-05-20-flatten-sessions.ts
59394
- var fs50 = __toESM(require("fs"), 1);
59395
- var path52 = __toESM(require("path"), 1);
59859
+ var fs51 = __toESM(require("fs"), 1);
59860
+ var path53 = __toESM(require("path"), 1);
59396
59861
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
59397
59862
  function migrateFlattenSessions(opts) {
59398
59863
  const dataDir = opts.dataDir;
59399
59864
  const now = opts.now ?? Date.now;
59400
- const sessionsDir = path52.join(dataDir, "sessions");
59401
- const flagPath = path52.join(sessionsDir, MIGRATION_FLAG_NAME);
59865
+ const sessionsDir = path53.join(dataDir, "sessions");
59866
+ const flagPath = path53.join(sessionsDir, MIGRATION_FLAG_NAME);
59402
59867
  if (existsSync3(flagPath)) {
59403
59868
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
59404
59869
  }
59405
59870
  let movedBare = 0;
59406
59871
  let movedVmOwner = 0;
59407
59872
  let archivedListener = 0;
59408
- const defaultDir = path52.join(sessionsDir, "default");
59873
+ const defaultDir = path53.join(sessionsDir, "default");
59409
59874
  if (existsSync3(defaultDir)) {
59410
59875
  for (const entry of readdirSafe(defaultDir)) {
59411
59876
  if (!entry.endsWith(".json")) continue;
59412
- const src = path52.join(defaultDir, entry);
59413
- const dst = path52.join(sessionsDir, entry);
59414
- fs50.renameSync(src, dst);
59877
+ const src = path53.join(defaultDir, entry);
59878
+ const dst = path53.join(sessionsDir, entry);
59879
+ fs51.renameSync(src, dst);
59415
59880
  movedBare += 1;
59416
59881
  }
59417
59882
  rmdirIfEmpty(defaultDir);
59418
59883
  }
59419
59884
  for (const pid of readdirSafe(sessionsDir)) {
59420
- const personaDir = path52.join(sessionsDir, pid);
59885
+ const personaDir = path53.join(sessionsDir, pid);
59421
59886
  if (!isDir(personaDir)) continue;
59422
59887
  if (pid === "default") continue;
59423
- const ownerSrc = path52.join(personaDir, "owner");
59888
+ const ownerSrc = path53.join(personaDir, "owner");
59424
59889
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
59425
- const ownerDst = path52.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
59426
- fs50.mkdirSync(ownerDst, { recursive: true });
59890
+ const ownerDst = path53.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
59891
+ fs51.mkdirSync(ownerDst, { recursive: true });
59427
59892
  for (const file of readdirSafe(ownerSrc)) {
59428
59893
  if (!file.endsWith(".json")) continue;
59429
- fs50.renameSync(path52.join(ownerSrc, file), path52.join(ownerDst, file));
59894
+ fs51.renameSync(path53.join(ownerSrc, file), path53.join(ownerDst, file));
59430
59895
  movedVmOwner += 1;
59431
59896
  }
59432
59897
  rmdirIfEmpty(ownerSrc);
59433
59898
  }
59434
- const listenerSrc = path52.join(personaDir, "listener");
59899
+ const listenerSrc = path53.join(personaDir, "listener");
59435
59900
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
59436
- const archiveDst = path52.join(dataDir, ".legacy", `listener-${pid}`);
59437
- fs50.mkdirSync(archiveDst, { recursive: true });
59901
+ const archiveDst = path53.join(dataDir, ".legacy", `listener-${pid}`);
59902
+ fs51.mkdirSync(archiveDst, { recursive: true });
59438
59903
  for (const file of readdirSafe(listenerSrc)) {
59439
59904
  if (!file.endsWith(".json")) continue;
59440
- fs50.renameSync(path52.join(listenerSrc, file), path52.join(archiveDst, file));
59905
+ fs51.renameSync(path53.join(listenerSrc, file), path53.join(archiveDst, file));
59441
59906
  archivedListener += 1;
59442
59907
  }
59443
59908
  rmdirIfEmpty(listenerSrc);
59444
59909
  }
59445
59910
  rmdirIfEmpty(personaDir);
59446
59911
  }
59447
- fs50.mkdirSync(sessionsDir, { recursive: true });
59448
- fs50.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
59912
+ fs51.mkdirSync(sessionsDir, { recursive: true });
59913
+ fs51.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
59449
59914
  return {
59450
59915
  skipped: false,
59451
59916
  flagWritten: true,
@@ -59456,7 +59921,7 @@ function migrateFlattenSessions(opts) {
59456
59921
  }
59457
59922
  function existsSync3(p2) {
59458
59923
  try {
59459
- fs50.statSync(p2);
59924
+ fs51.statSync(p2);
59460
59925
  return true;
59461
59926
  } catch {
59462
59927
  return false;
@@ -59464,61 +59929,61 @@ function existsSync3(p2) {
59464
59929
  }
59465
59930
  function isDir(p2) {
59466
59931
  try {
59467
- return fs50.statSync(p2).isDirectory();
59932
+ return fs51.statSync(p2).isDirectory();
59468
59933
  } catch {
59469
59934
  return false;
59470
59935
  }
59471
59936
  }
59472
59937
  function readdirSafe(p2) {
59473
59938
  try {
59474
- return fs50.readdirSync(p2);
59939
+ return fs51.readdirSync(p2);
59475
59940
  } catch {
59476
59941
  return [];
59477
59942
  }
59478
59943
  }
59479
59944
  function rmdirIfEmpty(p2) {
59480
59945
  try {
59481
- fs50.rmdirSync(p2);
59946
+ fs51.rmdirSync(p2);
59482
59947
  } catch {
59483
59948
  }
59484
59949
  }
59485
59950
 
59486
59951
  // src/migrations/2026-08-18-drop-seeded-projects.ts
59487
- var fs51 = __toESM(require("fs"), 1);
59488
- var path53 = __toESM(require("path"), 1);
59952
+ var fs52 = __toESM(require("fs"), 1);
59953
+ var path54 = __toESM(require("path"), 1);
59489
59954
  var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
59490
59955
  function dropSeededProjects(opts) {
59491
- fs51.mkdirSync(opts.dataDir, { recursive: true });
59492
- const flag = path53.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
59493
- if (fs51.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
59494
- const file = path53.join(opts.dataDir, "projects.json");
59956
+ fs52.mkdirSync(opts.dataDir, { recursive: true });
59957
+ const flag = path54.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
59958
+ if (fs52.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
59959
+ const file = path54.join(opts.dataDir, "projects.json");
59495
59960
  let raw = null;
59496
59961
  let dropped = 0;
59497
59962
  try {
59498
- raw = fs51.readFileSync(file, "utf8");
59963
+ raw = fs52.readFileSync(file, "utf8");
59499
59964
  dropped = JSON.parse(raw).projects?.length ?? 0;
59500
59965
  } catch {
59501
59966
  }
59502
59967
  let backup = null;
59503
59968
  if (raw != null && dropped > 0) {
59504
- const dir = path53.join(opts.dataDir, "backups");
59505
- fs51.mkdirSync(dir, { recursive: true });
59506
- backup = path53.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
59507
- fs51.writeFileSync(backup, raw);
59969
+ const dir = path54.join(opts.dataDir, "backups");
59970
+ fs52.mkdirSync(dir, { recursive: true });
59971
+ backup = path54.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
59972
+ fs52.writeFileSync(backup, raw);
59508
59973
  }
59509
59974
  if (raw != null || dropped > 0) {
59510
- fs51.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
59975
+ fs52.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
59511
59976
  }
59512
- fs51.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
59977
+ fs52.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
59513
59978
  return { skipped: false, dropped, backup };
59514
59979
  }
59515
59980
 
59516
59981
  // src/transport/http-router.ts
59517
59982
  var import_node_fs36 = __toESM(require("fs"), 1);
59518
- var import_node_path45 = __toESM(require("path"), 1);
59983
+ var import_node_path46 = __toESM(require("path"), 1);
59519
59984
 
59520
59985
  // src/attachment/mime.ts
59521
- var import_node_path42 = __toESM(require("path"), 1);
59986
+ var import_node_path43 = __toESM(require("path"), 1);
59522
59987
  var TEXT_PLAIN = "text/plain; charset=utf-8";
59523
59988
  var EXT_TO_NATIVE_MIME = {
59524
59989
  // 图片
@@ -59625,14 +60090,14 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
59625
60090
  ".mk"
59626
60091
  ]);
59627
60092
  function lookupMime(filePathOrName) {
59628
- const ext = import_node_path42.default.extname(filePathOrName).toLowerCase();
60093
+ const ext = import_node_path43.default.extname(filePathOrName).toLowerCase();
59629
60094
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
59630
60095
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
59631
60096
  return "application/octet-stream";
59632
60097
  }
59633
60098
 
59634
60099
  // src/attachment/sign-url.ts
59635
- var import_node_crypto9 = __toESM(require("crypto"), 1);
60100
+ var import_node_crypto10 = __toESM(require("crypto"), 1);
59636
60101
  var HMAC_ALGO = "sha256";
59637
60102
  function base64urlEncode(buf) {
59638
60103
  const b2 = typeof buf === "string" ? Buffer.from(buf, "utf8") : buf;
@@ -59650,7 +60115,7 @@ function decodeAbsPathFromUrl(encoded) {
59650
60115
  var DOMAIN_PREFIX2 = "clawd-attach-v1|";
59651
60116
  function computeSig(secret, absPath, e) {
59652
60117
  const msg = e === null ? `${DOMAIN_PREFIX2}${absPath}` : `${DOMAIN_PREFIX2}${absPath}|${e}`;
59653
- return import_node_crypto9.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
60118
+ return import_node_crypto10.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
59654
60119
  }
59655
60120
  function signUrlParts(secret, absPath, ttlSeconds, now = Date.now) {
59656
60121
  const e = ttlSeconds === null ? null : Math.floor(now() / 1e3) + ttlSeconds;
@@ -59685,7 +60150,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
59685
60150
  if (provided.length !== expected.length) {
59686
60151
  return { ok: false, code: "BAD_SIG" };
59687
60152
  }
59688
- if (!import_node_crypto9.default.timingSafeEqual(provided, expected)) {
60153
+ if (!import_node_crypto10.default.timingSafeEqual(provided, expected)) {
59689
60154
  return { ok: false, code: "BAD_SIG" };
59690
60155
  }
59691
60156
  if (e !== null && now() / 1e3 > e) {
@@ -59696,9 +60161,9 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
59696
60161
 
59697
60162
  // src/attachment/upload.ts
59698
60163
  var import_node_fs35 = __toESM(require("fs"), 1);
59699
- var import_node_path43 = __toESM(require("path"), 1);
59700
- var import_node_crypto10 = __toESM(require("crypto"), 1);
59701
- var import_promises9 = require("stream/promises");
60164
+ var import_node_path44 = __toESM(require("path"), 1);
60165
+ var import_node_crypto11 = __toESM(require("crypto"), 1);
60166
+ var import_promises10 = require("stream/promises");
59702
60167
  var UploadError = class extends Error {
59703
60168
  constructor(code, message) {
59704
60169
  super(message);
@@ -59708,27 +60173,27 @@ var UploadError = class extends Error {
59708
60173
  code;
59709
60174
  };
59710
60175
  function assertValidFileName(fileName) {
59711
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path43.default.basename(fileName)) {
60176
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path44.default.basename(fileName)) {
59712
60177
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
59713
60178
  }
59714
60179
  }
59715
60180
  var HASH_PREFIX_LEN = 16;
59716
60181
  async function writeUploadedAttachment(args) {
59717
60182
  assertValidFileName(args.fileName);
59718
- const attachmentsRoot = import_node_path43.default.join(args.baseDir, ".attachments");
60183
+ const attachmentsRoot = import_node_path44.default.join(args.baseDir, ".attachments");
59719
60184
  try {
59720
60185
  import_node_fs35.default.mkdirSync(attachmentsRoot, { recursive: true });
59721
60186
  } catch (err) {
59722
60187
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
59723
60188
  }
59724
- const hasher = import_node_crypto10.default.createHash("sha256");
60189
+ const hasher = import_node_crypto11.default.createHash("sha256");
59725
60190
  let actualSize = 0;
59726
- const tmpPath = import_node_path43.default.join(
60191
+ const tmpPath = import_node_path44.default.join(
59727
60192
  attachmentsRoot,
59728
- `.upload-${process.pid}-${Date.now()}-${import_node_crypto10.default.randomBytes(4).toString("hex")}`
60193
+ `.upload-${process.pid}-${Date.now()}-${import_node_crypto11.default.randomBytes(4).toString("hex")}`
59729
60194
  );
59730
60195
  try {
59731
- await (0, import_promises9.pipeline)(
60196
+ await (0, import_promises10.pipeline)(
59732
60197
  args.body,
59733
60198
  async function* (source) {
59734
60199
  for await (const chunk of source) {
@@ -59758,7 +60223,7 @@ async function writeUploadedAttachment(args) {
59758
60223
  );
59759
60224
  }
59760
60225
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
59761
- const hashDir = import_node_path43.default.join(attachmentsRoot, attachmentId);
60226
+ const hashDir = import_node_path44.default.join(attachmentsRoot, attachmentId);
59762
60227
  let finalFileName;
59763
60228
  let hashDirExists = false;
59764
60229
  try {
@@ -59776,7 +60241,7 @@ async function writeUploadedAttachment(args) {
59776
60241
  try {
59777
60242
  import_node_fs35.default.mkdirSync(hashDir, { recursive: true });
59778
60243
  finalFileName = args.fileName;
59779
- import_node_fs35.default.renameSync(tmpPath, import_node_path43.default.join(hashDir, finalFileName));
60244
+ import_node_fs35.default.renameSync(tmpPath, import_node_path44.default.join(hashDir, finalFileName));
59780
60245
  } catch (err) {
59781
60246
  try {
59782
60247
  import_node_fs35.default.unlinkSync(tmpPath);
@@ -59785,7 +60250,7 @@ async function writeUploadedAttachment(args) {
59785
60250
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
59786
60251
  }
59787
60252
  }
59788
- const absPath = import_node_path43.default.join(hashDir, finalFileName);
60253
+ const absPath = import_node_path44.default.join(hashDir, finalFileName);
59789
60254
  const relPath = absPath;
59790
60255
  args.groupFileStore.upsert(args.scope, args.sessionId, {
59791
60256
  relPath: absPath,
@@ -59799,9 +60264,9 @@ async function writeUploadedAttachment(args) {
59799
60264
  }
59800
60265
 
59801
60266
  // src/extension/import.ts
59802
- var import_promises10 = __toESM(require("fs/promises"), 1);
59803
- var import_node_path44 = __toESM(require("path"), 1);
59804
- var import_node_os14 = __toESM(require("os"), 1);
60267
+ var import_promises11 = __toESM(require("fs/promises"), 1);
60268
+ var import_node_path45 = __toESM(require("path"), 1);
60269
+ var import_node_os15 = __toESM(require("os"), 1);
59805
60270
  var import_jszip = __toESM(require_lib3(), 1);
59806
60271
  var ImportError = class extends Error {
59807
60272
  constructor(code, message) {
@@ -59818,7 +60283,7 @@ async function importZip(buf, root) {
59818
60283
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
59819
60284
  }
59820
60285
  for (const name of Object.keys(zip.files)) {
59821
- if (name.includes("..") || name.startsWith("/") || import_node_path44.default.isAbsolute(name)) {
60286
+ if (name.includes("..") || name.startsWith("/") || import_node_path45.default.isAbsolute(name)) {
59822
60287
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
59823
60288
  }
59824
60289
  }
@@ -59851,33 +60316,33 @@ async function importZip(buf, root) {
59851
60316
  );
59852
60317
  }
59853
60318
  }
59854
- const destDir = import_node_path44.default.join(root, manifest.id);
60319
+ const destDir = import_node_path45.default.join(root, manifest.id);
59855
60320
  let destExists = false;
59856
60321
  try {
59857
- await import_promises10.default.access(destDir);
60322
+ await import_promises11.default.access(destDir);
59858
60323
  destExists = true;
59859
60324
  } catch {
59860
60325
  }
59861
60326
  if (destExists) {
59862
60327
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
59863
60328
  }
59864
- const stage = await import_promises10.default.mkdtemp(import_node_path44.default.join(import_node_os14.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
60329
+ const stage = await import_promises11.default.mkdtemp(import_node_path45.default.join(import_node_os15.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
59865
60330
  try {
59866
60331
  for (const [name, entry] of Object.entries(zip.files)) {
59867
- const dest = import_node_path44.default.join(stage, name);
60332
+ const dest = import_node_path45.default.join(stage, name);
59868
60333
  if (entry.dir) {
59869
- await import_promises10.default.mkdir(dest, { recursive: true });
60334
+ await import_promises11.default.mkdir(dest, { recursive: true });
59870
60335
  continue;
59871
60336
  }
59872
- await import_promises10.default.mkdir(import_node_path44.default.dirname(dest), { recursive: true });
60337
+ await import_promises11.default.mkdir(import_node_path45.default.dirname(dest), { recursive: true });
59873
60338
  const content = await entry.async("nodebuffer");
59874
- await import_promises10.default.writeFile(dest, content);
60339
+ await import_promises11.default.writeFile(dest, content);
59875
60340
  }
59876
- await import_promises10.default.mkdir(root, { recursive: true });
59877
- await import_promises10.default.rename(stage, destDir);
60341
+ await import_promises11.default.mkdir(root, { recursive: true });
60342
+ await import_promises11.default.rename(stage, destDir);
59878
60343
  return { extId: manifest.id };
59879
60344
  } catch (e) {
59880
- await import_promises10.default.rm(stage, { recursive: true, force: true }).catch(() => {
60345
+ await import_promises11.default.rm(stage, { recursive: true, force: true }).catch(() => {
59881
60346
  });
59882
60347
  throw e;
59883
60348
  }
@@ -59899,7 +60364,7 @@ var SHARE_UI_ASSET_MIME = {
59899
60364
  ".wasm": "application/wasm"
59900
60365
  };
59901
60366
  function shareUiAssetMime(filePath) {
59902
- const ext = import_node_path45.default.extname(filePath).toLowerCase();
60367
+ const ext = import_node_path46.default.extname(filePath).toLowerCase();
59903
60368
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
59904
60369
  }
59905
60370
  var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
@@ -59998,7 +60463,7 @@ function isValidUploadFileName(fileName) {
59998
60463
  if (fileName === "." || fileName === "..") return false;
59999
60464
  if (fileName.startsWith(".")) return false;
60000
60465
  if (fileName.includes("/") || fileName.includes("\\")) return false;
60001
- return fileName === import_node_path45.default.basename(fileName);
60466
+ return fileName === import_node_path46.default.basename(fileName);
60002
60467
  }
60003
60468
  function createHttpRouter(deps) {
60004
60469
  return async (req, res) => {
@@ -60234,7 +60699,7 @@ function createHttpRouter(deps) {
60234
60699
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
60235
60700
  return true;
60236
60701
  }
60237
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path45.default.basename(r.absPath)));
60702
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path46.default.basename(r.absPath)));
60238
60703
  return true;
60239
60704
  }
60240
60705
  const ctx = deps.authResolver.resolveFromHeader(
@@ -60355,7 +60820,7 @@ function createHttpRouter(deps) {
60355
60820
  return true;
60356
60821
  }
60357
60822
  let absPath;
60358
- if (import_node_path45.default.isAbsolute(pathParam)) {
60823
+ if (import_node_path46.default.isAbsolute(pathParam)) {
60359
60824
  absPath = pathParam;
60360
60825
  } else if (deps.sessionStore) {
60361
60826
  const file = deps.sessionStore.read(sid);
@@ -60363,7 +60828,7 @@ function createHttpRouter(deps) {
60363
60828
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
60364
60829
  return true;
60365
60830
  }
60366
- absPath = import_node_path45.default.join(file.cwd, pathParam);
60831
+ absPath = import_node_path46.default.join(file.cwd, pathParam);
60367
60832
  } else {
60368
60833
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
60369
60834
  return true;
@@ -60465,7 +60930,7 @@ function streamFile(res, absPath, logger) {
60465
60930
  return;
60466
60931
  }
60467
60932
  const mime = lookupMime(absPath);
60468
- const basename2 = import_node_path45.default.basename(absPath);
60933
+ const basename2 = import_node_path46.default.basename(absPath);
60469
60934
  res.writeHead(200, {
60470
60935
  "Content-Type": mime,
60471
60936
  "Content-Length": String(stat.size),
@@ -60483,7 +60948,7 @@ function streamFile(res, absPath, logger) {
60483
60948
 
60484
60949
  // src/attachment/gc.ts
60485
60950
  var import_node_fs37 = __toESM(require("fs"), 1);
60486
- var import_node_path46 = __toESM(require("path"), 1);
60951
+ var import_node_path47 = __toESM(require("path"), 1);
60487
60952
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
60488
60953
  function runAttachmentGc(args) {
60489
60954
  const now = (args.now ?? Date.now)();
@@ -60492,12 +60957,12 @@ function runAttachmentGc(args) {
60492
60957
  for (const { scope, sessionId } of args.sessionScopes) {
60493
60958
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
60494
60959
  if (entry.stale) continue;
60495
- if (import_node_path46.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
60960
+ if (import_node_path47.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
60496
60961
  }
60497
60962
  }
60498
60963
  const visited = /* @__PURE__ */ new Set();
60499
60964
  for (const { scope, sessionId } of args.sessionScopes) {
60500
- const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path46.default.join(
60965
+ const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path47.default.join(
60501
60966
  args.dataDir,
60502
60967
  "sessions",
60503
60968
  ...scopeSubPath(scope).map(safeFileName),
@@ -60510,7 +60975,7 @@ function runAttachmentGc(args) {
60510
60975
  return true;
60511
60976
  });
60512
60977
  for (const rootDir of roots) {
60513
- const attRoot = import_node_path46.default.join(rootDir, ".attachments");
60978
+ const attRoot = import_node_path47.default.join(rootDir, ".attachments");
60514
60979
  let hashDirs;
60515
60980
  try {
60516
60981
  hashDirs = import_node_fs37.default.readdirSync(attRoot);
@@ -60520,7 +60985,7 @@ function runAttachmentGc(args) {
60520
60985
  continue;
60521
60986
  }
60522
60987
  for (const hashDir of hashDirs) {
60523
- const hashDirAbs = import_node_path46.default.join(attRoot, hashDir);
60988
+ const hashDirAbs = import_node_path47.default.join(attRoot, hashDir);
60524
60989
  let files;
60525
60990
  try {
60526
60991
  files = import_node_fs37.default.readdirSync(hashDirAbs);
@@ -60528,7 +60993,7 @@ function runAttachmentGc(args) {
60528
60993
  continue;
60529
60994
  }
60530
60995
  for (const name of files) {
60531
- const file = import_node_path46.default.join(hashDirAbs, name);
60996
+ const file = import_node_path47.default.join(hashDirAbs, name);
60532
60997
  let stat;
60533
60998
  try {
60534
60999
  stat = import_node_fs37.default.statSync(file);
@@ -60560,8 +61025,8 @@ function runAttachmentGc(args) {
60560
61025
 
60561
61026
  // src/attachment/group.ts
60562
61027
  var import_node_fs38 = __toESM(require("fs"), 1);
60563
- var import_node_path47 = __toESM(require("path"), 1);
60564
- var import_node_crypto11 = __toESM(require("crypto"), 1);
61028
+ var import_node_path48 = __toESM(require("path"), 1);
61029
+ var import_node_crypto12 = __toESM(require("crypto"), 1);
60565
61030
  init_protocol();
60566
61031
  var GroupFileStore = class {
60567
61032
  dataDir;
@@ -60572,11 +61037,11 @@ var GroupFileStore = class {
60572
61037
  this.logger = opts.logger;
60573
61038
  }
60574
61039
  rootForScope(scope) {
60575
- return import_node_path47.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
61040
+ return import_node_path48.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
60576
61041
  }
60577
61042
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
60578
61043
  filePath(scope, sessionId) {
60579
- return import_node_path47.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
61044
+ return import_node_path48.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
60580
61045
  }
60581
61046
  cacheKey(scope, sessionId) {
60582
61047
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -60611,7 +61076,7 @@ var GroupFileStore = class {
60611
61076
  }
60612
61077
  writeFile(scope, sessionId, entries) {
60613
61078
  const file = this.filePath(scope, sessionId);
60614
- import_node_fs38.default.mkdirSync(import_node_path47.default.dirname(file), { recursive: true });
61079
+ import_node_fs38.default.mkdirSync(import_node_path48.default.dirname(file), { recursive: true });
60615
61080
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
60616
61081
  import_node_fs38.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
60617
61082
  import_node_fs38.default.renameSync(tmp, file);
@@ -60650,7 +61115,7 @@ var GroupFileStore = class {
60650
61115
  entries[idx] = next;
60651
61116
  } else {
60652
61117
  next = {
60653
- id: `gf-${import_node_crypto11.default.randomBytes(6).toString("base64url")}`,
61118
+ id: `gf-${import_node_crypto12.default.randomBytes(6).toString("base64url")}`,
60654
61119
  relPath: input.relPath,
60655
61120
  from: input.from,
60656
61121
  label: input.label,
@@ -60701,9 +61166,9 @@ var GroupFileStore = class {
60701
61166
 
60702
61167
  // src/discovery/state-file.ts
60703
61168
  var import_node_fs39 = __toESM(require("fs"), 1);
60704
- var import_node_path48 = __toESM(require("path"), 1);
61169
+ var import_node_path49 = __toESM(require("path"), 1);
60705
61170
  function defaultStateFilePath(dataDir) {
60706
- return import_node_path48.default.join(dataDir, "state.json");
61171
+ return import_node_path49.default.join(dataDir, "state.json");
60707
61172
  }
60708
61173
  function isPidAlive(pid) {
60709
61174
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -60739,7 +61204,7 @@ var StateFileManager = class {
60739
61204
  return { status: "stale", existing };
60740
61205
  }
60741
61206
  write(state) {
60742
- import_node_fs39.default.mkdirSync(import_node_path48.default.dirname(this.file), { recursive: true });
61207
+ import_node_fs39.default.mkdirSync(import_node_path49.default.dirname(this.file), { recursive: true });
60743
61208
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
60744
61209
  import_node_fs39.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
60745
61210
  import_node_fs39.default.renameSync(tmp, this.file);
@@ -60767,13 +61232,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
60767
61232
 
60768
61233
  // src/tunnel/tunnel-manager.ts
60769
61234
  var import_node_fs43 = __toESM(require("fs"), 1);
60770
- var import_node_path52 = __toESM(require("path"), 1);
60771
- var import_node_crypto12 = __toESM(require("crypto"), 1);
60772
- var import_node_child_process12 = require("child_process");
61235
+ var import_node_path53 = __toESM(require("path"), 1);
61236
+ var import_node_crypto13 = __toESM(require("crypto"), 1);
61237
+ var import_node_child_process13 = require("child_process");
60773
61238
 
60774
61239
  // src/tunnel/tunnel-store.ts
60775
61240
  var import_node_fs40 = __toESM(require("fs"), 1);
60776
- var import_node_path49 = __toESM(require("path"), 1);
61241
+ var import_node_path50 = __toESM(require("path"), 1);
60777
61242
  var TunnelStore = class {
60778
61243
  constructor(filePath) {
60779
61244
  this.filePath = filePath;
@@ -60792,7 +61257,7 @@ var TunnelStore = class {
60792
61257
  }
60793
61258
  }
60794
61259
  async set(v2) {
60795
- const dir = import_node_path49.default.dirname(this.filePath);
61260
+ const dir = import_node_path50.default.dirname(this.filePath);
60796
61261
  await import_node_fs40.default.promises.mkdir(dir, { recursive: true });
60797
61262
  const data = JSON.stringify(v2, null, 2);
60798
61263
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
@@ -60903,11 +61368,11 @@ function escape(v2) {
60903
61368
 
60904
61369
  // src/tunnel/frpc-binary.ts
60905
61370
  var import_node_fs41 = __toESM(require("fs"), 1);
60906
- var import_node_os15 = __toESM(require("os"), 1);
60907
- var import_node_path50 = __toESM(require("path"), 1);
60908
- var import_node_child_process10 = require("child_process");
61371
+ var import_node_os16 = __toESM(require("os"), 1);
61372
+ var import_node_path51 = __toESM(require("path"), 1);
61373
+ var import_node_child_process11 = require("child_process");
60909
61374
  var import_node_stream3 = require("stream");
60910
- var import_promises11 = require("stream/promises");
61375
+ var import_promises12 = require("stream/promises");
60911
61376
  var FRPC_VERSION = "0.68.0";
60912
61377
  var UnsupportedPlatformError = class extends Error {
60913
61378
  constructor(platform, arch) {
@@ -60943,13 +61408,13 @@ async function ensureFrpcBinary(opts) {
60943
61408
  }
60944
61409
  const version2 = opts.version ?? FRPC_VERSION;
60945
61410
  const platform = opts.platform ?? detectPlatform();
60946
- const binDir = import_node_path50.default.join(opts.dataDir, "bin");
61411
+ const binDir = import_node_path51.default.join(opts.dataDir, "bin");
60947
61412
  import_node_fs41.default.mkdirSync(binDir, { recursive: true });
60948
61413
  cleanupStaleArtifacts(binDir);
60949
- const stableBin = import_node_path50.default.join(binDir, "frpc");
61414
+ const stableBin = import_node_path51.default.join(binDir, "frpc");
60950
61415
  if (import_node_fs41.default.existsSync(stableBin)) return stableBin;
60951
61416
  const partialBin = `${stableBin}.partial`;
60952
- const tarballPath = import_node_path50.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
61417
+ const tarballPath = import_node_path51.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
60953
61418
  try {
60954
61419
  const url = frpcDownloadUrl(version2, platform);
60955
61420
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -60975,7 +61440,7 @@ function cleanupStaleArtifacts(binDir) {
60975
61440
  }
60976
61441
  for (const name of entries) {
60977
61442
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
60978
- const full = import_node_path50.default.join(binDir, name);
61443
+ const full = import_node_path51.default.join(binDir, name);
60979
61444
  try {
60980
61445
  import_node_fs41.default.rmSync(full, { recursive: true, force: true });
60981
61446
  } catch {
@@ -60998,19 +61463,19 @@ async function downloadToFile(url, dest, fetchImpl) {
60998
61463
  }
60999
61464
  const out = import_node_fs41.default.createWriteStream(dest);
61000
61465
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
61001
- await (0, import_promises11.pipeline)(nodeStream, out);
61466
+ await (0, import_promises12.pipeline)(nodeStream, out);
61002
61467
  }
61003
61468
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
61004
- const work = import_node_path50.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
61469
+ const work = import_node_path51.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
61005
61470
  import_node_fs41.default.mkdirSync(work, { recursive: true });
61006
61471
  try {
61007
61472
  await new Promise((resolve9, reject) => {
61008
- const proc = (0, import_node_child_process10.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
61473
+ const proc = (0, import_node_child_process11.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
61009
61474
  proc.on("error", reject);
61010
61475
  proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
61011
61476
  });
61012
61477
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
61013
- const src = import_node_path50.default.join(work, dirName, "frpc");
61478
+ const src = import_node_path51.default.join(work, dirName, "frpc");
61014
61479
  if (!import_node_fs41.default.existsSync(src)) {
61015
61480
  throw new Error(`frpc not found inside tarball at ${src}`);
61016
61481
  }
@@ -61022,10 +61487,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
61022
61487
 
61023
61488
  // src/tunnel/frpc-process.ts
61024
61489
  var import_node_fs42 = __toESM(require("fs"), 1);
61025
- var import_node_path51 = __toESM(require("path"), 1);
61026
- var import_node_child_process11 = require("child_process");
61490
+ var import_node_path52 = __toESM(require("path"), 1);
61491
+ var import_node_child_process12 = require("child_process");
61027
61492
  function frpcPidFilePath(dataDir) {
61028
- return import_node_path51.default.join(dataDir, "frpc.pid");
61493
+ return import_node_path52.default.join(dataDir, "frpc.pid");
61029
61494
  }
61030
61495
  function writeFrpcPid(dataDir, pid) {
61031
61496
  try {
@@ -61067,7 +61532,7 @@ function defaultSleep2(ms) {
61067
61532
  }
61068
61533
  async function killStaleFrpc(deps) {
61069
61534
  const pidFile = frpcPidFilePath(deps.dataDir);
61070
- const tomlPath = import_node_path51.default.join(deps.dataDir, "frpc.toml");
61535
+ const tomlPath = import_node_path52.default.join(deps.dataDir, "frpc.toml");
61071
61536
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
61072
61537
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
61073
61538
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -61109,7 +61574,7 @@ async function killStaleFrpc(deps) {
61109
61574
  async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
61110
61575
  if (process.platform === "win32") return [];
61111
61576
  return new Promise((resolve9) => {
61112
- const ps = (0, import_node_child_process11.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
61577
+ const ps = (0, import_node_child_process12.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
61113
61578
  let buf = "";
61114
61579
  ps.stdout.on("data", (c) => {
61115
61580
  buf += c.toString();
@@ -61139,7 +61604,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
61139
61604
  var TunnelManager = class {
61140
61605
  constructor(deps) {
61141
61606
  this.deps = deps;
61142
- this.store = deps.store ?? new TunnelStore(import_node_path52.default.join(deps.dataDir, "tunnel.json"));
61607
+ this.store = deps.store ?? new TunnelStore(import_node_path53.default.join(deps.dataDir, "tunnel.json"));
61143
61608
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
61144
61609
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
61145
61610
  }
@@ -61266,8 +61731,8 @@ var TunnelManager = class {
61266
61731
  dataDir: this.deps.dataDir,
61267
61732
  override: this.deps.frpcBinaryOverride ?? void 0
61268
61733
  });
61269
- const tomlPath = import_node_path52.default.join(this.deps.dataDir, "frpc.toml");
61270
- const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto12.default.randomBytes(3).toString("hex")}`;
61734
+ const tomlPath = import_node_path53.default.join(this.deps.dataDir, "frpc.toml");
61735
+ const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto13.default.randomBytes(3).toString("hex")}`;
61271
61736
  const toml = buildFrpcToml({
61272
61737
  serverAddr: t.frpsHost,
61273
61738
  serverPort: t.frpsPort,
@@ -61278,12 +61743,12 @@ var TunnelManager = class {
61278
61743
  logLevel: "info"
61279
61744
  });
61280
61745
  await import_node_fs43.default.promises.writeFile(tomlPath, toml, { mode: 384 });
61281
- const proc = (this.deps.spawnImpl ?? import_node_child_process12.spawn)(frpcBin, ["-c", tomlPath], {
61746
+ const proc = (this.deps.spawnImpl ?? import_node_child_process13.spawn)(frpcBin, ["-c", tomlPath], {
61282
61747
  stdio: ["ignore", "pipe", "pipe"]
61283
61748
  });
61284
- const logDir = import_node_path52.default.join(this.deps.dataDir, "log");
61749
+ const logDir = import_node_path53.default.join(this.deps.dataDir, "log");
61285
61750
  import_node_fs43.default.mkdirSync(logDir, { recursive: true });
61286
- const logFilePath = import_node_path52.default.join(logDir, "frpc.log");
61751
+ const logFilePath = import_node_path53.default.join(logDir, "frpc.log");
61287
61752
  const logStream = import_node_fs43.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
61288
61753
  logStream.on("error", () => {
61289
61754
  });
@@ -61366,28 +61831,28 @@ async function waitForFrpcReady(proc, timeoutMs) {
61366
61831
  }
61367
61832
 
61368
61833
  // src/tunnel/device-key.ts
61369
- var import_node_os16 = __toESM(require("os"), 1);
61370
- var import_node_path53 = __toESM(require("path"), 1);
61371
- var import_node_crypto13 = __toESM(require("crypto"), 1);
61834
+ var import_node_os17 = __toESM(require("os"), 1);
61835
+ var import_node_path54 = __toESM(require("path"), 1);
61836
+ var import_node_crypto14 = __toESM(require("crypto"), 1);
61372
61837
  var DERIVE_SALT = "clawd-tunnel-device-v1";
61373
61838
  function deriveStableDeviceKey(opts = {}) {
61374
- const hostname = opts.hostname ?? import_node_os16.default.hostname();
61375
- const uid = opts.uid ?? (typeof import_node_os16.default.userInfo === "function" ? import_node_os16.default.userInfo().uid : 0);
61376
- const home = opts.home ?? import_node_os16.default.homedir();
61377
- const defaultDataDir = import_node_path53.default.resolve(import_node_path53.default.join(home, ".clawd"));
61378
- const normalizedDataDir = opts.dataDir ? import_node_path53.default.resolve(opts.dataDir) : null;
61839
+ const hostname = opts.hostname ?? import_node_os17.default.hostname();
61840
+ const uid = opts.uid ?? (typeof import_node_os17.default.userInfo === "function" ? import_node_os17.default.userInfo().uid : 0);
61841
+ const home = opts.home ?? import_node_os17.default.homedir();
61842
+ const defaultDataDir = import_node_path54.default.resolve(import_node_path54.default.join(home, ".clawd"));
61843
+ const normalizedDataDir = opts.dataDir ? import_node_path54.default.resolve(opts.dataDir) : null;
61379
61844
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
61380
61845
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
61381
- return import_node_crypto13.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
61846
+ return import_node_crypto14.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
61382
61847
  }
61383
61848
 
61384
61849
  // src/auth-store.ts
61385
61850
  var import_node_fs44 = __toESM(require("fs"), 1);
61386
- var import_node_path54 = __toESM(require("path"), 1);
61387
- var import_node_crypto14 = __toESM(require("crypto"), 1);
61851
+ var import_node_path55 = __toESM(require("path"), 1);
61852
+ var import_node_crypto15 = __toESM(require("crypto"), 1);
61388
61853
  var AUTH_FILE_NAME = "auth.json";
61389
61854
  function authFilePath(dataDir) {
61390
- return import_node_path54.default.join(dataDir, AUTH_FILE_NAME);
61855
+ return import_node_path55.default.join(dataDir, AUTH_FILE_NAME);
61391
61856
  }
61392
61857
  function loadOrCreateAuthFile(opts) {
61393
61858
  const file = authFilePath(opts.dataDir);
@@ -61412,10 +61877,10 @@ function loadOrCreateAuthFile(opts) {
61412
61877
  return next;
61413
61878
  }
61414
61879
  function defaultGenerateToken() {
61415
- return import_node_crypto14.default.randomBytes(32).toString("base64url");
61880
+ return import_node_crypto15.default.randomBytes(32).toString("base64url");
61416
61881
  }
61417
61882
  function defaultGenerateOwnerPrincipalId() {
61418
- return `owner-${import_node_crypto14.default.randomUUID()}`;
61883
+ return `owner-${import_node_crypto15.default.randomUUID()}`;
61419
61884
  }
61420
61885
  function readAuthFile(file) {
61421
61886
  try {
@@ -61439,7 +61904,7 @@ function readAuthFile(file) {
61439
61904
  }
61440
61905
  }
61441
61906
  function writeAuthFile(file, content) {
61442
- import_node_fs44.default.mkdirSync(import_node_path54.default.dirname(file), { recursive: true });
61907
+ import_node_fs44.default.mkdirSync(import_node_path55.default.dirname(file), { recursive: true });
61443
61908
  import_node_fs44.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
61444
61909
  try {
61445
61910
  import_node_fs44.default.chmodSync(file, 384);
@@ -61449,11 +61914,11 @@ function writeAuthFile(file, content) {
61449
61914
 
61450
61915
  // src/owner-profile.ts
61451
61916
  var import_node_fs45 = __toESM(require("fs"), 1);
61452
- var import_node_os17 = __toESM(require("os"), 1);
61453
- var import_node_path55 = __toESM(require("path"), 1);
61917
+ var import_node_os18 = __toESM(require("os"), 1);
61918
+ var import_node_path56 = __toESM(require("path"), 1);
61454
61919
  var PROFILE_FILENAME = "profile.json";
61455
61920
  function profilePath(dataDir) {
61456
- return import_node_path55.default.join(dataDir, PROFILE_FILENAME);
61921
+ return import_node_path56.default.join(dataDir, PROFILE_FILENAME);
61457
61922
  }
61458
61923
  function loadOwnerProfile(dataDir) {
61459
61924
  let raw;
@@ -61478,7 +61943,7 @@ function patchOwnerProfile(dataDir, patch) {
61478
61943
  return merged;
61479
61944
  }
61480
61945
  function loadOwnerDisplayName(dataDir) {
61481
- const fallback = import_node_os17.default.userInfo().username;
61946
+ const fallback = import_node_os18.default.userInfo().username;
61482
61947
  const displayName = loadOwnerProfile(dataDir).displayName;
61483
61948
  if (typeof displayName !== "string" || displayName.length === 0) {
61484
61949
  if (displayName !== void 0) {
@@ -61491,12 +61956,12 @@ function loadOwnerDisplayName(dataDir) {
61491
61956
 
61492
61957
  // src/feishu-auth/owner-identity-store.ts
61493
61958
  var import_node_fs46 = __toESM(require("fs"), 1);
61494
- var import_node_path56 = __toESM(require("path"), 1);
61959
+ var import_node_path57 = __toESM(require("path"), 1);
61495
61960
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
61496
61961
  var OwnerIdentityStore = class {
61497
61962
  file;
61498
61963
  constructor(dataDir) {
61499
- this.file = import_node_path56.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
61964
+ this.file = import_node_path57.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
61500
61965
  }
61501
61966
  read() {
61502
61967
  let raw;
@@ -61529,7 +61994,7 @@ var OwnerIdentityStore = class {
61529
61994
  };
61530
61995
  }
61531
61996
  write(record3) {
61532
- import_node_fs46.default.mkdirSync(import_node_path56.default.dirname(this.file), { recursive: true });
61997
+ import_node_fs46.default.mkdirSync(import_node_path57.default.dirname(this.file), { recursive: true });
61533
61998
  import_node_fs46.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
61534
61999
  try {
61535
62000
  import_node_fs46.default.chmodSync(this.file, 384);
@@ -61547,7 +62012,7 @@ var OwnerIdentityStore = class {
61547
62012
  };
61548
62013
 
61549
62014
  // src/feishu-auth/login-flow.ts
61550
- var import_node_crypto15 = __toESM(require("crypto"), 1);
62015
+ var import_node_crypto16 = __toESM(require("crypto"), 1);
61551
62016
  var STATE_TTL_MS = 5 * 60 * 1e3;
61552
62017
  var LoginFlow = class {
61553
62018
  constructor(deps) {
@@ -61556,7 +62021,7 @@ var LoginFlow = class {
61556
62021
  deps;
61557
62022
  pendingStates = /* @__PURE__ */ new Map();
61558
62023
  start() {
61559
- const state = import_node_crypto15.default.randomBytes(16).toString("base64url");
62024
+ const state = import_node_crypto16.default.randomBytes(16).toString("base64url");
61560
62025
  const now = (this.deps.now ?? Date.now)();
61561
62026
  this.pendingStates.set(state, now);
61562
62027
  this.gcExpired(now);
@@ -61675,9 +62140,9 @@ var CentralClientError = class extends Error {
61675
62140
  code;
61676
62141
  cause;
61677
62142
  };
61678
- async function centralRequest(opts, path98, init) {
62143
+ async function centralRequest(opts, path99, init) {
61679
62144
  const f = opts.fetchImpl ?? globalThis.fetch;
61680
- const url = `${opts.api.replace(/\/+$/, "")}${path98}`;
62145
+ const url = `${opts.api.replace(/\/+$/, "")}${path99}`;
61681
62146
  const ctrl = new AbortController();
61682
62147
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
61683
62148
  let res;
@@ -62065,7 +62530,7 @@ function buildDeviceHandlers(deps) {
62065
62530
  }
62066
62531
 
62067
62532
  // src/feishu-auth/verify-token.ts
62068
- var crypto11 = __toESM(require("crypto"), 1);
62533
+ var crypto12 = __toESM(require("crypto"), 1);
62069
62534
  var CONNECT_TOKEN_PREFIX = "clawdtk1";
62070
62535
  function verifyConnectToken(args) {
62071
62536
  const now = args.nowSeconds ?? Math.floor(Date.now() / 1e3);
@@ -62077,7 +62542,7 @@ function verifyConnectToken(args) {
62077
62542
  const data = `${prefix}.${payloadB64}`;
62078
62543
  let signatureValid = false;
62079
62544
  try {
62080
- signatureValid = crypto11.verify(
62545
+ signatureValid = crypto12.verify(
62081
62546
  null,
62082
62547
  Buffer.from(data, "utf8"),
62083
62548
  args.publicKeyPem,
@@ -62114,8 +62579,8 @@ function verifyConnectToken(args) {
62114
62579
  }
62115
62580
 
62116
62581
  // src/feishu-auth/server-key.ts
62117
- var fs65 = __toESM(require("fs"), 1);
62118
- var path69 = __toESM(require("path"), 1);
62582
+ var fs66 = __toESM(require("fs"), 1);
62583
+ var path70 = __toESM(require("path"), 1);
62119
62584
  var FILE_NAME2 = "server-signing-key.json";
62120
62585
  var ServerKeyStore = class {
62121
62586
  constructor(dataDir) {
@@ -62123,12 +62588,12 @@ var ServerKeyStore = class {
62123
62588
  }
62124
62589
  dataDir;
62125
62590
  filePath() {
62126
- return path69.join(this.dataDir, FILE_NAME2);
62591
+ return path70.join(this.dataDir, FILE_NAME2);
62127
62592
  }
62128
62593
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
62129
62594
  read() {
62130
62595
  try {
62131
- const raw = fs65.readFileSync(this.filePath(), "utf8");
62596
+ const raw = fs66.readFileSync(this.filePath(), "utf8");
62132
62597
  const parsed = JSON.parse(raw);
62133
62598
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
62134
62599
  return parsed.publicKeyPem;
@@ -62143,12 +62608,12 @@ var ServerKeyStore = class {
62143
62608
  publicKeyPem,
62144
62609
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
62145
62610
  };
62146
- fs65.mkdirSync(this.dataDir, { recursive: true });
62147
- fs65.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
62611
+ fs66.mkdirSync(this.dataDir, { recursive: true });
62612
+ fs66.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
62148
62613
  }
62149
62614
  clear() {
62150
62615
  try {
62151
- fs65.unlinkSync(this.filePath());
62616
+ fs66.unlinkSync(this.filePath());
62152
62617
  } catch {
62153
62618
  }
62154
62619
  }
@@ -62158,16 +62623,16 @@ var ServerKeyStore = class {
62158
62623
  init_protocol();
62159
62624
 
62160
62625
  // src/handlers/index.ts
62161
- var import_node_path72 = __toESM(require("path"), 1);
62626
+ var import_node_path73 = __toESM(require("path"), 1);
62162
62627
 
62163
62628
  // src/handlers/session.ts
62164
62629
  init_protocol();
62165
62630
 
62166
62631
  // src/session/fork.ts
62167
62632
  var import_node_fs47 = __toESM(require("fs"), 1);
62168
- var import_node_os18 = __toESM(require("os"), 1);
62169
- var import_node_path57 = __toESM(require("path"), 1);
62170
- var import_node_crypto16 = require("crypto");
62633
+ var import_node_os19 = __toESM(require("os"), 1);
62634
+ var import_node_path58 = __toESM(require("path"), 1);
62635
+ var import_node_crypto17 = require("crypto");
62171
62636
  init_claude_history();
62172
62637
  function readJsonlEntries(file) {
62173
62638
  const raw = import_node_fs47.default.readFileSync(file, "utf8");
@@ -62183,19 +62648,19 @@ function readJsonlEntries(file) {
62183
62648
  return out;
62184
62649
  }
62185
62650
  function forkSession(input) {
62186
- const baseDir = input.baseDir ?? import_node_path57.default.join(import_node_os18.default.homedir(), ".claude");
62187
- let projectDir = import_node_path57.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
62188
- let sourceFile = import_node_path57.default.join(projectDir, `${input.toolSessionId}.jsonl`);
62651
+ const baseDir = input.baseDir ?? import_node_path58.default.join(import_node_os19.default.homedir(), ".claude");
62652
+ let projectDir = import_node_path58.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
62653
+ let sourceFile = import_node_path58.default.join(projectDir, `${input.toolSessionId}.jsonl`);
62189
62654
  if (!import_node_fs47.default.existsSync(sourceFile)) {
62190
62655
  const found = findTranscriptByToolSessionId(
62191
- import_node_path57.default.join(baseDir, "projects"),
62656
+ import_node_path58.default.join(baseDir, "projects"),
62192
62657
  input.toolSessionId
62193
62658
  );
62194
62659
  if (!found) {
62195
62660
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
62196
62661
  }
62197
62662
  sourceFile = found;
62198
- projectDir = import_node_path57.default.dirname(found);
62663
+ projectDir = import_node_path58.default.dirname(found);
62199
62664
  }
62200
62665
  const entries = readJsonlEntries(sourceFile);
62201
62666
  const mainEntries = entries.filter((e) => e.isSidechain !== true);
@@ -62204,7 +62669,7 @@ function forkSession(input) {
62204
62669
  throw new Error(`fork: messageUuid not found in transcript: ${input.messageUuid}`);
62205
62670
  }
62206
62671
  const sliced = mainEntries.slice(0, targetIdx + 1);
62207
- const forkedToolSessionId = (0, import_node_crypto16.randomUUID)();
62672
+ const forkedToolSessionId = (0, import_node_crypto17.randomUUID)();
62208
62673
  let parentUuid = null;
62209
62674
  const forkedLines = [];
62210
62675
  for (const entry of sliced) {
@@ -62224,8 +62689,8 @@ function forkSession(input) {
62224
62689
  }
62225
62690
  forkedLines.push(JSON.stringify(forked));
62226
62691
  }
62227
- const outDir = input.targetCwd ? import_node_path57.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
62228
- const forkedFilePath = import_node_path57.default.join(outDir, `${forkedToolSessionId}.jsonl`);
62692
+ const outDir = input.targetCwd ? import_node_path58.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
62693
+ const forkedFilePath = import_node_path58.default.join(outDir, `${forkedToolSessionId}.jsonl`);
62229
62694
  import_node_fs47.default.mkdirSync(outDir, { recursive: true });
62230
62695
  import_node_fs47.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
62231
62696
  return { forkedToolSessionId, forkedFilePath };
@@ -62233,18 +62698,18 @@ function forkSession(input) {
62233
62698
 
62234
62699
  // src/session/external-scan.ts
62235
62700
  var import_node_fs48 = __toESM(require("fs"), 1);
62236
- var import_promises12 = __toESM(require("fs/promises"), 1);
62237
- var import_node_os19 = __toESM(require("os"), 1);
62238
- var import_node_path58 = __toESM(require("path"), 1);
62701
+ var import_promises13 = __toESM(require("fs/promises"), 1);
62702
+ var import_node_os20 = __toESM(require("os"), 1);
62703
+ var import_node_path59 = __toESM(require("path"), 1);
62239
62704
  var import_node_module = require("module");
62240
- var import_node_child_process13 = require("child_process");
62705
+ var import_node_child_process14 = require("child_process");
62241
62706
  var import_meta5 = {};
62242
62707
  function defaultRoots() {
62243
- const home = import_node_os19.default.homedir();
62708
+ const home = import_node_os20.default.homedir();
62244
62709
  return {
62245
- claudeProjectsDir: import_node_path58.default.join(home, ".claude", "projects"),
62246
- codexDir: import_node_path58.default.join(home, ".codex"),
62247
- clawdDir: import_node_path58.default.join(home, ".clawd")
62710
+ claudeProjectsDir: import_node_path59.default.join(home, ".claude", "projects"),
62711
+ codexDir: import_node_path59.default.join(home, ".codex"),
62712
+ clawdDir: import_node_path59.default.join(home, ".clawd")
62248
62713
  };
62249
62714
  }
62250
62715
  function width(s) {
@@ -62272,7 +62737,7 @@ function toMs(v2) {
62272
62737
  async function* jsonLines(file) {
62273
62738
  let raw;
62274
62739
  try {
62275
- raw = await import_promises12.default.readFile(file, "utf8");
62740
+ raw = await import_promises13.default.readFile(file, "utf8");
62276
62741
  } catch {
62277
62742
  return;
62278
62743
  }
@@ -62312,13 +62777,13 @@ async function scanClaude(roots) {
62312
62777
  if (!d.isDirectory()) continue;
62313
62778
  let files;
62314
62779
  try {
62315
- files = import_node_fs48.default.readdirSync(import_node_path58.default.join(roots.claudeProjectsDir, d.name));
62780
+ files = import_node_fs48.default.readdirSync(import_node_path59.default.join(roots.claudeProjectsDir, d.name));
62316
62781
  } catch {
62317
62782
  continue;
62318
62783
  }
62319
62784
  for (const name of files) {
62320
62785
  if (!name.endsWith(".jsonl")) continue;
62321
- const file = import_node_path58.default.join(roots.claudeProjectsDir, d.name, name);
62786
+ const file = import_node_path59.default.join(roots.claudeProjectsDir, d.name, name);
62322
62787
  let st;
62323
62788
  try {
62324
62789
  st = import_node_fs48.default.statSync(file);
@@ -62405,14 +62870,14 @@ function readCodexThreads(db) {
62405
62870
  } catch {
62406
62871
  }
62407
62872
  try {
62408
- const info = (0, import_node_child_process13.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
62873
+ const info = (0, import_node_child_process14.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
62409
62874
  if (info.status !== 0) return null;
62410
62875
  const have = new Set(
62411
62876
  info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
62412
62877
  );
62413
62878
  if (!["id", "cwd", "updated_at", "thread_source"].every((c) => have.has(c))) return null;
62414
62879
  const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
62415
- const res = (0, import_node_child_process13.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
62880
+ const res = (0, import_node_child_process14.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
62416
62881
  encoding: "utf8",
62417
62882
  maxBuffer: 64 * 1024 * 1024
62418
62883
  });
@@ -62448,7 +62913,7 @@ async function codexFromRows(rows) {
62448
62913
  async function scanCodex(roots) {
62449
62914
  let dbs = [];
62450
62915
  try {
62451
- dbs = import_node_fs48.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path58.default.join(roots.codexDir, n));
62916
+ dbs = import_node_fs48.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path59.default.join(roots.codexDir, n));
62452
62917
  } catch {
62453
62918
  }
62454
62919
  if (!dbs.length) return [];
@@ -62457,14 +62922,14 @@ async function scanCodex(roots) {
62457
62922
  }
62458
62923
  async function scanExternalSessions(rootsIn) {
62459
62924
  const roots = { ...defaultRoots(), ...rootsIn };
62460
- const personaRoot = import_node_path58.default.join(roots.clawdDir, "personas");
62925
+ const personaRoot = import_node_path59.default.join(roots.clawdDir, "personas");
62461
62926
  const all = [...await scanClaude(roots), ...await scanCodex(roots)];
62462
62927
  const out = [];
62463
62928
  for (const c of all) {
62464
62929
  if (c.skip) continue;
62465
62930
  if (c.turns < 1) continue;
62466
62931
  if (!c.cwd || !isDir2(c.cwd)) continue;
62467
- 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)) {
62932
+ if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path59.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path59.default.sep)) {
62468
62933
  continue;
62469
62934
  }
62470
62935
  out.push({
@@ -62482,12 +62947,12 @@ async function scanExternalSessions(rootsIn) {
62482
62947
 
62483
62948
  // src/session/import-ledger.ts
62484
62949
  var import_node_fs49 = __toESM(require("fs"), 1);
62485
- var import_node_path59 = __toESM(require("path"), 1);
62950
+ var import_node_path60 = __toESM(require("path"), 1);
62486
62951
  var LEDGER_FILENAME = "session-import-ledger.json";
62487
62952
  function readImportLedger(dataDir) {
62488
62953
  try {
62489
62954
  const parsed = JSON.parse(
62490
- import_node_fs49.default.readFileSync(import_node_path59.default.join(dataDir, LEDGER_FILENAME), "utf8")
62955
+ import_node_fs49.default.readFileSync(import_node_path60.default.join(dataDir, LEDGER_FILENAME), "utf8")
62491
62956
  );
62492
62957
  return Array.isArray(parsed) ? parsed : [];
62493
62958
  } catch {
@@ -62495,7 +62960,7 @@ function readImportLedger(dataDir) {
62495
62960
  }
62496
62961
  }
62497
62962
  function appendImportLedger(dataDir, entry) {
62498
- const file = import_node_path59.default.join(dataDir, LEDGER_FILENAME);
62963
+ const file = import_node_path60.default.join(dataDir, LEDGER_FILENAME);
62499
62964
  const entries = readImportLedger(dataDir);
62500
62965
  entries.push(entry);
62501
62966
  import_node_fs49.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
@@ -62503,7 +62968,7 @@ function appendImportLedger(dataDir, entry) {
62503
62968
 
62504
62969
  // src/tools/transcript-search.ts
62505
62970
  var import_node_fs50 = __toESM(require("fs"), 1);
62506
- var import_node_path60 = __toESM(require("path"), 1);
62971
+ var import_node_path61 = __toESM(require("path"), 1);
62507
62972
  var SNIPPET_PAD = 60;
62508
62973
  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/;
62509
62974
  var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
@@ -62596,7 +63061,7 @@ function createCodexRolloutLocator(roots) {
62596
63061
  return;
62597
63062
  }
62598
63063
  for (const entry of entries) {
62599
- const full = import_node_path60.default.join(dir, entry.name);
63064
+ const full = import_node_path61.default.join(dir, entry.name);
62600
63065
  if (entry.isDirectory()) {
62601
63066
  walk2(full, into);
62602
63067
  continue;
@@ -62616,16 +63081,16 @@ function createCodexRolloutLocator(roots) {
62616
63081
 
62617
63082
  // src/handlers/session.ts
62618
63083
  init_protocol();
62619
- var import_node_os20 = __toESM(require("os"), 1);
62620
- var import_node_path61 = __toESM(require("path"), 1);
63084
+ var import_node_os21 = __toESM(require("os"), 1);
63085
+ var import_node_path62 = __toESM(require("path"), 1);
62621
63086
  function canReadSearchHit(ctx, file) {
62622
63087
  if (!ctx || ctx.principal.kind === "owner") return true;
62623
63088
  return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
62624
63089
  }
62625
63090
  var DEFAULT_SEARCH_LIMIT = 9;
62626
63091
  function codexRolloutRoots(dataDir) {
62627
- const roots = [import_node_path61.default.join(import_node_os20.default.homedir(), ".codex", "sessions")];
62628
- if (dataDir) roots.push(import_node_path61.default.join(dataDir, "codex-home", "sessions"));
63092
+ const roots = [import_node_path62.default.join(import_node_os21.default.homedir(), ".codex", "sessions")];
63093
+ if (dataDir) roots.push(import_node_path62.default.join(dataDir, "codex-home", "sessions"));
62629
63094
  return roots;
62630
63095
  }
62631
63096
  function buildSessionHandlers(deps) {
@@ -63174,7 +63639,7 @@ function buildPermissionHandlers(deps) {
63174
63639
  }
63175
63640
 
63176
63641
  // src/handlers/history.ts
63177
- var path76 = __toESM(require("path"), 1);
63642
+ var path77 = __toESM(require("path"), 1);
63178
63643
  init_protocol();
63179
63644
 
63180
63645
  // src/session/recent-dirs.ts
@@ -63192,7 +63657,7 @@ function listRecentDirs(store, limit = 50) {
63192
63657
  }
63193
63658
 
63194
63659
  // src/permission/persona-paths.ts
63195
- var path75 = __toESM(require("path"), 1);
63660
+ var path76 = __toESM(require("path"), 1);
63196
63661
  function getAllowedPersonaIds(grants, action) {
63197
63662
  const ids = /* @__PURE__ */ new Set();
63198
63663
  for (const g2 of grants) {
@@ -63205,42 +63670,42 @@ function getAllowedPersonaIds(grants, action) {
63205
63670
  return ids;
63206
63671
  }
63207
63672
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
63208
- const target = path75.resolve(absPath);
63673
+ const target = path76.resolve(absPath);
63209
63674
  if (userWorkDir) {
63210
- const u = path75.resolve(userWorkDir);
63211
- const usep = u.endsWith(path75.sep) ? "" : path75.sep;
63675
+ const u = path76.resolve(userWorkDir);
63676
+ const usep = u.endsWith(path76.sep) ? "" : path76.sep;
63212
63677
  if (target === u || target.startsWith(u + usep)) return true;
63213
63678
  }
63214
- const root = path75.resolve(personaRoot);
63215
- const sep4 = root.endsWith(path75.sep) ? "" : path75.sep;
63679
+ const root = path76.resolve(personaRoot);
63680
+ const sep4 = root.endsWith(path76.sep) ? "" : path76.sep;
63216
63681
  if (!target.startsWith(root + sep4)) return false;
63217
- const rel = path75.relative(root, target);
63682
+ const rel = path76.relative(root, target);
63218
63683
  if (!rel || rel.startsWith("..")) return false;
63219
- const personaId2 = rel.split(path75.sep)[0];
63684
+ const personaId2 = rel.split(path76.sep)[0];
63220
63685
  if (!personaId2) return false;
63221
63686
  const allowed = getAllowedPersonaIds(grants, action);
63222
63687
  if (allowed === "*") return true;
63223
63688
  return allowed.has(personaId2);
63224
63689
  }
63225
63690
  function personaIdFromPath(absPath, personaRoot) {
63226
- const root = path75.resolve(personaRoot);
63227
- const target = path75.resolve(absPath);
63228
- const sep4 = root.endsWith(path75.sep) ? "" : path75.sep;
63691
+ const root = path76.resolve(personaRoot);
63692
+ const target = path76.resolve(absPath);
63693
+ const sep4 = root.endsWith(path76.sep) ? "" : path76.sep;
63229
63694
  if (!target.startsWith(root + sep4)) return null;
63230
- const rel = path75.relative(root, target);
63695
+ const rel = path76.relative(root, target);
63231
63696
  if (!rel || rel.startsWith("..")) return null;
63232
- const id = rel.split(path75.sep)[0];
63697
+ const id = rel.split(path76.sep)[0];
63233
63698
  return id || null;
63234
63699
  }
63235
63700
  function isPathWithin(dir, absPath) {
63236
- const d = path75.resolve(dir);
63237
- const t = path75.resolve(absPath);
63238
- const sep4 = d.endsWith(path75.sep) ? "" : path75.sep;
63701
+ const d = path76.resolve(dir);
63702
+ const t = path76.resolve(absPath);
63703
+ const sep4 = d.endsWith(path76.sep) ? "" : path76.sep;
63239
63704
  return t === d || t.startsWith(d + sep4);
63240
63705
  }
63241
63706
  function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
63242
63707
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
63243
- return personaIdFromPath(path75.resolve(absPath), personaRoot) === personaId2;
63708
+ return personaIdFromPath(path76.resolve(absPath), personaRoot) === personaId2;
63244
63709
  }
63245
63710
 
63246
63711
  // src/handlers/history.ts
@@ -63293,7 +63758,7 @@ function buildHistoryHandlers(deps) {
63293
63758
  if (!pid) return false;
63294
63759
  return isGuestPathAllowed(
63295
63760
  ctx.grants,
63296
- path76.join(personaRoot, pid),
63761
+ path77.join(personaRoot, pid),
63297
63762
  personaRoot,
63298
63763
  "read",
63299
63764
  userWorkDir
@@ -63305,7 +63770,7 @@ function buildHistoryHandlers(deps) {
63305
63770
  };
63306
63771
  const list = async (frame, _client, ctx) => {
63307
63772
  const args = HistoryListArgs.parse(frame);
63308
- assertGuestPath(ctx, path76.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
63773
+ assertGuestPath(ctx, path77.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
63309
63774
  const sessions = await history.listSessions(args);
63310
63775
  return { response: { type: "history:list", sessions } };
63311
63776
  };
@@ -63353,14 +63818,14 @@ function buildHistoryHandlers(deps) {
63353
63818
  };
63354
63819
  const subagents = async (frame, _client, ctx) => {
63355
63820
  const args = HistorySubagentsArgs.parse(frame);
63356
- assertGuestPath(ctx, path76.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
63821
+ assertGuestPath(ctx, path77.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
63357
63822
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
63358
63823
  const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
63359
63824
  return { response: { type: "history:subagents", subagents: subs } };
63360
63825
  };
63361
63826
  const subagentRead = async (frame, _client, ctx) => {
63362
63827
  const args = HistorySubagentReadArgs.parse(frame);
63363
- assertGuestPath(ctx, path76.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
63828
+ assertGuestPath(ctx, path77.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
63364
63829
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
63365
63830
  const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
63366
63831
  return { response: { type: "history:subagent-read", ...res } };
@@ -63370,7 +63835,7 @@ function buildHistoryHandlers(deps) {
63370
63835
  if (ctx?.principal.kind === "guest" && personaRoot) {
63371
63836
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
63372
63837
  const filtered = dirs.filter(
63373
- (d) => isGuestPathAllowed(ctx.grants, path76.resolve(d.cwd), personaRoot, "read", userWorkDir)
63838
+ (d) => isGuestPathAllowed(ctx.grants, path77.resolve(d.cwd), personaRoot, "read", userWorkDir)
63374
63839
  );
63375
63840
  return { response: { type: "history:recentDirs", dirs: filtered } };
63376
63841
  }
@@ -63387,17 +63852,17 @@ function buildHistoryHandlers(deps) {
63387
63852
  }
63388
63853
 
63389
63854
  // src/handlers/projects.ts
63390
- var fs70 = __toESM(require("fs"), 1);
63391
- var os22 = __toESM(require("os"), 1);
63392
- var path77 = __toESM(require("path"), 1);
63393
- var import_node_child_process14 = require("child_process");
63855
+ var fs71 = __toESM(require("fs"), 1);
63856
+ var os23 = __toESM(require("os"), 1);
63857
+ var path78 = __toESM(require("path"), 1);
63858
+ var import_node_child_process15 = require("child_process");
63394
63859
  init_protocol();
63395
- var DEFAULT_PROJECTS_ROOT = path77.join(os22.homedir(), "Documents", "ChatGPT");
63860
+ var DEFAULT_PROJECTS_ROOT = path78.join(os23.homedir(), "Documents", "ChatGPT");
63396
63861
  function allocateDir(root, name) {
63397
- let candidate = path77.join(root, name);
63862
+ let candidate = path78.join(root, name);
63398
63863
  let n = 2;
63399
- while (fs70.existsSync(candidate)) {
63400
- candidate = path77.join(root, `${name} ${n}`);
63864
+ while (fs71.existsSync(candidate)) {
63865
+ candidate = path78.join(root, `${name} ${n}`);
63401
63866
  n += 1;
63402
63867
  }
63403
63868
  return candidate;
@@ -63425,11 +63890,11 @@ function buildProjectHandlers(deps) {
63425
63890
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
63426
63891
  }
63427
63892
  try {
63428
- if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
63893
+ if (!fs71.statSync(args.path).isDirectory()) throw new Error("not dir");
63429
63894
  } catch {
63430
63895
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
63431
63896
  }
63432
- const r = (0, import_node_child_process14.spawnSync)("open", ["-R", args.path], { stdio: "ignore" });
63897
+ const r = (0, import_node_child_process15.spawnSync)("open", ["-R", args.path], { stdio: "ignore" });
63433
63898
  if (r.status !== 0) {
63434
63899
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `open -R \u5931\u8D25: exit ${r.status}`);
63435
63900
  }
@@ -63441,7 +63906,7 @@ function buildProjectHandlers(deps) {
63441
63906
  let target;
63442
63907
  if (args.path) {
63443
63908
  try {
63444
- if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
63909
+ if (!fs71.statSync(args.path).isDirectory()) throw new Error("not dir");
63445
63910
  } catch {
63446
63911
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
63447
63912
  }
@@ -63449,15 +63914,15 @@ function buildProjectHandlers(deps) {
63449
63914
  } else {
63450
63915
  const name = args.name;
63451
63916
  try {
63452
- fs70.mkdirSync(root, { recursive: true });
63917
+ fs71.mkdirSync(root, { recursive: true });
63453
63918
  target = allocateDir(root, name);
63454
- fs70.mkdirSync(target);
63919
+ fs71.mkdirSync(target);
63455
63920
  } catch (err) {
63456
63921
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
63457
63922
  }
63458
- const git = (0, import_node_child_process14.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
63923
+ const git = (0, import_node_child_process15.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
63459
63924
  if (git.status !== 0) {
63460
- fs70.rmSync(target, { recursive: true, force: true });
63925
+ fs71.rmSync(target, { recursive: true, force: true });
63461
63926
  throw new ClawdError(
63462
63927
  ERROR_CODES.INVALID_CWD,
63463
63928
  `git init \u5931\u8D25\uFF08${git.error ? String(git.error) : `exit ${git.status}`}\uFF09: ${target}`
@@ -63482,8 +63947,8 @@ function buildProjectHandlers(deps) {
63482
63947
  }
63483
63948
 
63484
63949
  // src/handlers/workspace.ts
63485
- var path78 = __toESM(require("path"), 1);
63486
- var os23 = __toESM(require("os"), 1);
63950
+ var path79 = __toESM(require("path"), 1);
63951
+ var os24 = __toESM(require("os"), 1);
63487
63952
  init_protocol();
63488
63953
  init_protocol();
63489
63954
  function buildEnabledPluginNames(personaManager, personaId2) {
@@ -63523,23 +63988,23 @@ function buildWorkspaceHandlers(deps) {
63523
63988
  const list = async (frame, _client, ctx) => {
63524
63989
  const args = WorkspaceListArgs.parse(frame);
63525
63990
  const isGuest = ctx?.principal.kind === "guest";
63526
- const fallbackCwd = isGuest && personaRoot ? personaRoot : os23.homedir();
63527
- const resolvedCwd = path78.resolve(args.cwd ?? fallbackCwd);
63528
- const target = args.path ? path78.resolve(resolvedCwd, args.path) : resolvedCwd;
63991
+ const fallbackCwd = isGuest && personaRoot ? personaRoot : os24.homedir();
63992
+ const resolvedCwd = path79.resolve(args.cwd ?? fallbackCwd);
63993
+ const target = args.path ? path79.resolve(resolvedCwd, args.path) : resolvedCwd;
63529
63994
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
63530
63995
  const res = workspace.list({ ...args, cwd: resolvedCwd });
63531
63996
  return { response: { type: "workspace:list", ...res } };
63532
63997
  };
63533
63998
  const read = async (frame, _client, ctx) => {
63534
63999
  const args = WorkspaceReadArgs.parse(frame);
63535
- const target = path78.isAbsolute(args.path) ? path78.resolve(args.path) : path78.resolve(args.cwd, args.path);
64000
+ const target = path79.isAbsolute(args.path) ? path79.resolve(args.path) : path79.resolve(args.cwd, args.path);
63536
64001
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
63537
64002
  const res = workspace.read(args);
63538
64003
  return { response: { type: "workspace:read", ...res } };
63539
64004
  };
63540
64005
  const skillsList = async (frame, _client, ctx) => {
63541
64006
  const args = SkillsListArgs.parse(frame);
63542
- const cwdAbs = path78.resolve(args.cwd);
64007
+ const cwdAbs = path79.resolve(args.cwd);
63543
64008
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
63544
64009
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
63545
64010
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -63551,7 +64016,7 @@ function buildWorkspaceHandlers(deps) {
63551
64016
  };
63552
64017
  const agentsList = async (frame, _client, ctx) => {
63553
64018
  const args = AgentsListArgs.parse(frame);
63554
- const cwdAbs = path78.resolve(args.cwd);
64019
+ const cwdAbs = path79.resolve(args.cwd);
63555
64020
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
63556
64021
  if (args.tool === "codex") {
63557
64022
  return { response: { type: "agents:list", agents: [] } };
@@ -63573,18 +64038,18 @@ function buildWorkspaceHandlers(deps) {
63573
64038
  }
63574
64039
 
63575
64040
  // src/handlers/git.ts
63576
- var path80 = __toESM(require("path"), 1);
64041
+ var path81 = __toESM(require("path"), 1);
63577
64042
  init_protocol();
63578
64043
  init_protocol();
63579
64044
 
63580
64045
  // src/workspace/git.ts
63581
- var import_node_child_process15 = require("child_process");
64046
+ var import_node_child_process16 = require("child_process");
63582
64047
  var import_node_fs51 = __toESM(require("fs"), 1);
63583
- var import_node_path62 = __toESM(require("path"), 1);
64048
+ var import_node_path63 = __toESM(require("path"), 1);
63584
64049
  var import_node_util = require("util");
63585
- var pexec = (0, import_node_util.promisify)(import_node_child_process15.execFile);
64050
+ var pexec = (0, import_node_util.promisify)(import_node_child_process16.execFile);
63586
64051
  function normalizePath(p2) {
63587
- const resolved = import_node_path62.default.resolve(p2);
64052
+ const resolved = import_node_path63.default.resolve(p2);
63588
64053
  try {
63589
64054
  return import_node_fs51.default.realpathSync(resolved);
63590
64055
  } catch {
@@ -63660,7 +64125,7 @@ async function listGitBranches(cwd) {
63660
64125
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
63661
64126
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
63662
64127
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
63663
- if (!isGuestPathAllowed(ctx.grants, path80.resolve(cwd), personaRoot, "read", userWorkDir)) {
64128
+ if (!isGuestPathAllowed(ctx.grants, path81.resolve(cwd), personaRoot, "read", userWorkDir)) {
63664
64129
  throw new ClawdError(
63665
64130
  ERROR_CODES.UNAUTHORIZED,
63666
64131
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -64205,7 +64670,7 @@ function buildFeishuAuthHandlers(deps) {
64205
64670
  }
64206
64671
 
64207
64672
  // src/handlers/meta.ts
64208
- var import_node_os21 = __toESM(require("os"), 1);
64673
+ var import_node_os22 = __toESM(require("os"), 1);
64209
64674
  init_protocol();
64210
64675
 
64211
64676
  // src/handlers/method-grants.ts
@@ -64508,21 +64973,21 @@ function computeMethodAccess(args) {
64508
64973
  }
64509
64974
 
64510
64975
  // src/version.ts
64511
- var version = "0.2.463".length > 0 ? "0.2.463" : "dev";
64976
+ var version = "0.2.465".length > 0 ? "0.2.465" : "dev";
64512
64977
 
64513
64978
  // src/cli-probe/probe.ts
64514
- var fs72 = __toESM(require("fs"), 1);
64515
- var path81 = __toESM(require("path"), 1);
64979
+ var fs73 = __toESM(require("fs"), 1);
64980
+ var path82 = __toESM(require("path"), 1);
64516
64981
  var PKG_NAME = "@clawos-dev/clawd";
64517
64982
  var BIN_NAME = "clawd";
64518
64983
  var MAX_PARENT_HOPS = 5;
64519
64984
  function probeGlobalCli(pathEnv) {
64520
64985
  if (!pathEnv) return null;
64521
- for (const dir of pathEnv.split(path81.delimiter)) {
64986
+ for (const dir of pathEnv.split(path82.delimiter)) {
64522
64987
  if (!dir) continue;
64523
64988
  let real;
64524
64989
  try {
64525
- real = fs72.realpathSync(path81.join(dir, BIN_NAME));
64990
+ real = fs73.realpathSync(path82.join(dir, BIN_NAME));
64526
64991
  } catch {
64527
64992
  continue;
64528
64993
  }
@@ -64532,15 +64997,15 @@ function probeGlobalCli(pathEnv) {
64532
64997
  return null;
64533
64998
  }
64534
64999
  function readOwnPackageVersion(entryPath) {
64535
- let dir = path81.dirname(entryPath);
65000
+ let dir = path82.dirname(entryPath);
64536
65001
  for (let i = 0; i < MAX_PARENT_HOPS; i++) {
64537
65002
  try {
64538
- const raw = fs72.readFileSync(path81.join(dir, "package.json"), "utf8");
65003
+ const raw = fs73.readFileSync(path82.join(dir, "package.json"), "utf8");
64539
65004
  const pkg = JSON.parse(raw);
64540
65005
  if (pkg.name !== PKG_NAME) return null;
64541
65006
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
64542
65007
  } catch {
64543
- const parent = path81.dirname(dir);
65008
+ const parent = path82.dirname(dir);
64544
65009
  if (parent === dir) return null;
64545
65010
  dir = parent;
64546
65011
  }
@@ -64576,7 +65041,7 @@ function buildReadyFrame(deps, client) {
64576
65041
  return {
64577
65042
  version,
64578
65043
  protocolVersion: PROTOCOL_VERSION,
64579
- hostname: import_node_os21.default.hostname(),
65044
+ hostname: import_node_os22.default.hostname(),
64580
65045
  os: process.platform,
64581
65046
  tools,
64582
65047
  runningSessions: info.runningSessions,
@@ -64712,7 +65177,7 @@ function buildPersonaHandlers(deps) {
64712
65177
  }
64713
65178
 
64714
65179
  // src/handlers/attachment.ts
64715
- var import_node_path63 = __toESM(require("path"), 1);
65180
+ var import_node_path64 = __toESM(require("path"), 1);
64716
65181
  init_protocol();
64717
65182
  init_protocol();
64718
65183
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -64792,12 +65257,12 @@ function buildAttachmentHandlers(deps) {
64792
65257
  `session ${args.sessionId} scope unresolved`
64793
65258
  );
64794
65259
  }
64795
- const cwdAbs = import_node_path63.default.resolve(sessionFile.cwd);
64796
- const candidateAbs = import_node_path63.default.isAbsolute(args.relPath) ? import_node_path63.default.resolve(args.relPath) : import_node_path63.default.resolve(cwdAbs, args.relPath);
65260
+ const cwdAbs = import_node_path64.default.resolve(sessionFile.cwd);
65261
+ const candidateAbs = import_node_path64.default.isAbsolute(args.relPath) ? import_node_path64.default.resolve(args.relPath) : import_node_path64.default.resolve(cwdAbs, args.relPath);
64797
65262
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
64798
65263
  const entries = deps.groupFileStore.list(scope, args.sessionId);
64799
65264
  const entry = entries.find((e) => {
64800
- const storedAbs = import_node_path63.default.isAbsolute(e.relPath) ? import_node_path63.default.resolve(e.relPath) : import_node_path63.default.resolve(cwdAbs, e.relPath);
65265
+ const storedAbs = import_node_path64.default.isAbsolute(e.relPath) ? import_node_path64.default.resolve(e.relPath) : import_node_path64.default.resolve(cwdAbs, e.relPath);
64801
65266
  return storedAbs === candidateAbs && !e.stale;
64802
65267
  });
64803
65268
  if (!entry) {
@@ -64822,7 +65287,7 @@ function buildAttachmentHandlers(deps) {
64822
65287
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
64823
65288
  const f = deps.sessionStore.read(sessionId);
64824
65289
  if (!f) return;
64825
- assertGuestAttachmentPath(ctx, import_node_path63.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
65290
+ assertGuestAttachmentPath(ctx, import_node_path64.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
64826
65291
  }
64827
65292
  const groupAdd = async (frame, _client, ctx) => {
64828
65293
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -64837,8 +65302,8 @@ function buildAttachmentHandlers(deps) {
64837
65302
  if (!scope) {
64838
65303
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
64839
65304
  }
64840
- const cwdAbs = import_node_path63.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
64841
- const candidateAbs = import_node_path63.default.isAbsolute(args.relPath) ? import_node_path63.default.resolve(args.relPath) : import_node_path63.default.resolve(cwdAbs, args.relPath);
65305
+ const cwdAbs = import_node_path64.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
65306
+ const candidateAbs = import_node_path64.default.isAbsolute(args.relPath) ? import_node_path64.default.resolve(args.relPath) : import_node_path64.default.resolve(cwdAbs, args.relPath);
64842
65307
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
64843
65308
  const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
64844
65309
  const size = 0;
@@ -64896,21 +65361,21 @@ function buildAttachmentHandlers(deps) {
64896
65361
  }
64897
65362
 
64898
65363
  // src/handlers/extension.ts
64899
- var import_promises16 = __toESM(require("fs/promises"), 1);
64900
- var import_node_path68 = __toESM(require("path"), 1);
65364
+ var import_promises17 = __toESM(require("fs/promises"), 1);
65365
+ var import_node_path69 = __toESM(require("path"), 1);
64901
65366
  init_protocol();
64902
65367
 
64903
65368
  // src/extension/bundle-zip.ts
64904
- var import_promises13 = __toESM(require("fs/promises"), 1);
64905
- var import_node_path64 = __toESM(require("path"), 1);
64906
- var import_node_crypto17 = __toESM(require("crypto"), 1);
65369
+ var import_promises14 = __toESM(require("fs/promises"), 1);
65370
+ var import_node_path65 = __toESM(require("path"), 1);
65371
+ var import_node_crypto18 = __toESM(require("crypto"), 1);
64907
65372
  var import_jszip2 = __toESM(require_lib3(), 1);
64908
65373
  async function bundleExtensionDir(dir) {
64909
65374
  const entries = await listFilesSorted(dir);
64910
65375
  const zip = new import_jszip2.default();
64911
65376
  for (const rel of entries) {
64912
- const abs = import_node_path64.default.join(dir, rel);
64913
- const content = await import_promises13.default.readFile(abs);
65377
+ const abs = import_node_path65.default.join(dir, rel);
65378
+ const content = await import_promises14.default.readFile(abs);
64914
65379
  zip.file(rel, content, { date: FIXED_DATE });
64915
65380
  }
64916
65381
  const buffer = await zip.generateAsync({
@@ -64918,7 +65383,7 @@ async function bundleExtensionDir(dir) {
64918
65383
  compression: "DEFLATE",
64919
65384
  compressionOptions: { level: 6 }
64920
65385
  });
64921
- const sha256 = import_node_crypto17.default.createHash("sha256").update(buffer).digest("hex");
65386
+ const sha256 = import_node_crypto18.default.createHash("sha256").update(buffer).digest("hex");
64922
65387
  return { buffer, sha256 };
64923
65388
  }
64924
65389
  var FIXED_DATE = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
@@ -64930,8 +65395,8 @@ async function listFilesSorted(rootDir) {
64930
65395
  return out;
64931
65396
  }
64932
65397
  async function walk(absRoot, relPrefix, out) {
64933
- const dirAbs = import_node_path64.default.join(absRoot, relPrefix);
64934
- const entries = await import_promises13.default.readdir(dirAbs, { withFileTypes: true });
65398
+ const dirAbs = import_node_path65.default.join(absRoot, relPrefix);
65399
+ const entries = await import_promises14.default.readdir(dirAbs, { withFileTypes: true });
64935
65400
  for (const e of entries) {
64936
65401
  if (IGNORE_BASENAMES.has(e.name)) continue;
64937
65402
  const rel = relPrefix ? `${relPrefix}/${e.name}` : e.name;
@@ -64983,26 +65448,26 @@ function computePublishCheck(args) {
64983
65448
  }
64984
65449
 
64985
65450
  // src/extension/install-flow.ts
64986
- var import_promises14 = __toESM(require("fs/promises"), 1);
64987
- var import_node_path66 = __toESM(require("path"), 1);
64988
- var import_node_os23 = __toESM(require("os"), 1);
64989
- var import_node_crypto18 = __toESM(require("crypto"), 1);
65451
+ var import_promises15 = __toESM(require("fs/promises"), 1);
65452
+ var import_node_path67 = __toESM(require("path"), 1);
65453
+ var import_node_os24 = __toESM(require("os"), 1);
65454
+ var import_node_crypto19 = __toESM(require("crypto"), 1);
64990
65455
  var import_jszip3 = __toESM(require_lib3(), 1);
64991
65456
 
64992
65457
  // src/extension/paths.ts
64993
- var import_node_os22 = __toESM(require("os"), 1);
64994
- var import_node_path65 = __toESM(require("path"), 1);
65458
+ var import_node_os23 = __toESM(require("os"), 1);
65459
+ var import_node_path66 = __toESM(require("path"), 1);
64995
65460
  function clawdHomeRoot(override) {
64996
- return override ?? process.env.CLAWD_HOME ?? import_node_path65.default.join(import_node_os22.default.homedir(), ".clawd");
65461
+ return override ?? process.env.CLAWD_HOME ?? import_node_path66.default.join(import_node_os23.default.homedir(), ".clawd");
64997
65462
  }
64998
65463
  function extensionsRoot(override) {
64999
- return import_node_path65.default.join(clawdHomeRoot(override), "extensions");
65464
+ return import_node_path66.default.join(clawdHomeRoot(override), "extensions");
65000
65465
  }
65001
65466
  function publishedChannelsFile(override) {
65002
- return import_node_path65.default.join(clawdHomeRoot(override), "extensions-published.json");
65467
+ return import_node_path66.default.join(clawdHomeRoot(override), "extensions-published.json");
65003
65468
  }
65004
65469
  function bundleCacheRoot(override) {
65005
- return import_node_path65.default.join(clawdHomeRoot(override), "extension-bundles");
65470
+ return import_node_path66.default.join(clawdHomeRoot(override), "extension-bundles");
65006
65471
  }
65007
65472
 
65008
65473
  // src/extension/install-flow.ts
@@ -65015,7 +65480,7 @@ var InstallError = class extends Error {
65015
65480
  };
65016
65481
  async function installFromChannel(args, deps) {
65017
65482
  const { channelRef, snapshotHash, bundleZip } = args;
65018
- const computed = import_node_crypto18.default.createHash("sha256").update(bundleZip).digest("hex");
65483
+ const computed = import_node_crypto19.default.createHash("sha256").update(bundleZip).digest("hex");
65019
65484
  if (computed !== snapshotHash) {
65020
65485
  throw new InstallError(
65021
65486
  "HASH_MISMATCH",
@@ -65029,7 +65494,7 @@ async function installFromChannel(args, deps) {
65029
65494
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
65030
65495
  }
65031
65496
  for (const name of Object.keys(zip.files)) {
65032
- if (name.includes("..") || name.startsWith("/") || import_node_path66.default.isAbsolute(name)) {
65497
+ if (name.includes("..") || name.startsWith("/") || import_node_path67.default.isAbsolute(name)) {
65033
65498
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
65034
65499
  }
65035
65500
  }
@@ -65061,10 +65526,10 @@ async function installFromChannel(args, deps) {
65061
65526
  );
65062
65527
  }
65063
65528
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
65064
- const destDir = import_node_path66.default.join(deps.extensionsRoot, localExtId);
65529
+ const destDir = import_node_path67.default.join(deps.extensionsRoot, localExtId);
65065
65530
  let destExists = false;
65066
65531
  try {
65067
- await import_promises14.default.access(destDir);
65532
+ await import_promises15.default.access(destDir);
65068
65533
  destExists = true;
65069
65534
  } catch {
65070
65535
  }
@@ -65074,28 +65539,28 @@ async function installFromChannel(args, deps) {
65074
65539
  `extension ${localExtId} already installed locally (from owner ${channelRef.ownerPrincipalId})`
65075
65540
  );
65076
65541
  }
65077
- const stage = await import_promises14.default.mkdtemp(
65078
- import_node_path66.default.join(import_node_os23.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
65542
+ const stage = await import_promises15.default.mkdtemp(
65543
+ import_node_path67.default.join(import_node_os24.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
65079
65544
  );
65080
65545
  try {
65081
65546
  for (const [name, entry] of Object.entries(zip.files)) {
65082
- const dest = import_node_path66.default.join(stage, name);
65547
+ const dest = import_node_path67.default.join(stage, name);
65083
65548
  if (entry.dir) {
65084
- await import_promises14.default.mkdir(dest, { recursive: true });
65549
+ await import_promises15.default.mkdir(dest, { recursive: true });
65085
65550
  continue;
65086
65551
  }
65087
- await import_promises14.default.mkdir(import_node_path66.default.dirname(dest), { recursive: true });
65552
+ await import_promises15.default.mkdir(import_node_path67.default.dirname(dest), { recursive: true });
65088
65553
  if (name === "manifest.json") {
65089
65554
  const rewritten = { ...parsed.data, id: localExtId };
65090
- await import_promises14.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
65555
+ await import_promises15.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
65091
65556
  } else {
65092
- await import_promises14.default.writeFile(dest, await entry.async("nodebuffer"));
65557
+ await import_promises15.default.writeFile(dest, await entry.async("nodebuffer"));
65093
65558
  }
65094
65559
  }
65095
- await import_promises14.default.mkdir(deps.extensionsRoot, { recursive: true });
65096
- await import_promises14.default.rename(stage, destDir);
65560
+ await import_promises15.default.mkdir(deps.extensionsRoot, { recursive: true });
65561
+ await import_promises15.default.rename(stage, destDir);
65097
65562
  } catch (e) {
65098
- await import_promises14.default.rm(stage, { recursive: true, force: true }).catch(() => {
65563
+ await import_promises15.default.rm(stage, { recursive: true, force: true }).catch(() => {
65099
65564
  });
65100
65565
  throw e;
65101
65566
  }
@@ -65104,10 +65569,10 @@ async function installFromChannel(args, deps) {
65104
65569
  }
65105
65570
 
65106
65571
  // src/extension/update-flow.ts
65107
- var import_promises15 = __toESM(require("fs/promises"), 1);
65108
- var import_node_path67 = __toESM(require("path"), 1);
65109
- var import_node_os24 = __toESM(require("os"), 1);
65110
- var import_node_crypto19 = __toESM(require("crypto"), 1);
65572
+ var import_promises16 = __toESM(require("fs/promises"), 1);
65573
+ var import_node_path68 = __toESM(require("path"), 1);
65574
+ var import_node_os25 = __toESM(require("os"), 1);
65575
+ var import_node_crypto20 = __toESM(require("crypto"), 1);
65111
65576
  var import_jszip4 = __toESM(require_lib3(), 1);
65112
65577
  var UpdateError = class extends Error {
65113
65578
  constructor(code, message) {
@@ -65122,11 +65587,11 @@ async function updateFromChannel(args, deps) {
65122
65587
  channelRef.extId,
65123
65588
  channelRef.ownerPrincipalId
65124
65589
  );
65125
- const liveDir = import_node_path67.default.join(deps.extensionsRoot, localExtId);
65590
+ const liveDir = import_node_path68.default.join(deps.extensionsRoot, localExtId);
65126
65591
  const prevDir = `${liveDir}.prev`;
65127
65592
  let existingVersion;
65128
65593
  try {
65129
- const raw = await import_promises15.default.readFile(import_node_path67.default.join(liveDir, "manifest.json"), "utf8");
65594
+ const raw = await import_promises16.default.readFile(import_node_path68.default.join(liveDir, "manifest.json"), "utf8");
65130
65595
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
65131
65596
  if (!parsed2.success) {
65132
65597
  throw new UpdateError(
@@ -65145,7 +65610,7 @@ async function updateFromChannel(args, deps) {
65145
65610
  if (e instanceof UpdateError) throw e;
65146
65611
  throw e;
65147
65612
  }
65148
- const computed = import_node_crypto19.default.createHash("sha256").update(bundleZip).digest("hex");
65613
+ const computed = import_node_crypto20.default.createHash("sha256").update(bundleZip).digest("hex");
65149
65614
  if (computed !== snapshotHash) {
65150
65615
  throw new UpdateError(
65151
65616
  "HASH_MISMATCH",
@@ -65159,7 +65624,7 @@ async function updateFromChannel(args, deps) {
65159
65624
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
65160
65625
  }
65161
65626
  for (const name of Object.keys(zip.files)) {
65162
- if (name.includes("..") || name.startsWith("/") || import_node_path67.default.isAbsolute(name)) {
65627
+ if (name.includes("..") || name.startsWith("/") || import_node_path68.default.isAbsolute(name)) {
65163
65628
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
65164
65629
  }
65165
65630
  }
@@ -65191,31 +65656,31 @@ async function updateFromChannel(args, deps) {
65191
65656
  );
65192
65657
  }
65193
65658
  await deps.runtime.close(localExtId);
65194
- await import_promises15.default.rm(prevDir, { recursive: true, force: true });
65195
- await import_promises15.default.rename(liveDir, prevDir);
65196
- const stage = await import_promises15.default.mkdtemp(
65197
- import_node_path67.default.join(import_node_os24.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
65659
+ await import_promises16.default.rm(prevDir, { recursive: true, force: true });
65660
+ await import_promises16.default.rename(liveDir, prevDir);
65661
+ const stage = await import_promises16.default.mkdtemp(
65662
+ import_node_path68.default.join(import_node_os25.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
65198
65663
  );
65199
65664
  try {
65200
65665
  for (const [name, entry] of Object.entries(zip.files)) {
65201
- const dest = import_node_path67.default.join(stage, name);
65666
+ const dest = import_node_path68.default.join(stage, name);
65202
65667
  if (entry.dir) {
65203
- await import_promises15.default.mkdir(dest, { recursive: true });
65668
+ await import_promises16.default.mkdir(dest, { recursive: true });
65204
65669
  continue;
65205
65670
  }
65206
- await import_promises15.default.mkdir(import_node_path67.default.dirname(dest), { recursive: true });
65671
+ await import_promises16.default.mkdir(import_node_path68.default.dirname(dest), { recursive: true });
65207
65672
  if (name === "manifest.json") {
65208
65673
  const rewritten = { ...parsed.data, id: localExtId };
65209
- await import_promises15.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
65674
+ await import_promises16.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
65210
65675
  } else {
65211
- await import_promises15.default.writeFile(dest, await entry.async("nodebuffer"));
65676
+ await import_promises16.default.writeFile(dest, await entry.async("nodebuffer"));
65212
65677
  }
65213
65678
  }
65214
- await import_promises15.default.rename(stage, liveDir);
65679
+ await import_promises16.default.rename(stage, liveDir);
65215
65680
  } catch (e) {
65216
- await import_promises15.default.rm(stage, { recursive: true, force: true }).catch(() => {
65681
+ await import_promises16.default.rm(stage, { recursive: true, force: true }).catch(() => {
65217
65682
  });
65218
- await import_promises15.default.rename(prevDir, liveDir).catch(() => {
65683
+ await import_promises16.default.rename(prevDir, liveDir).catch(() => {
65219
65684
  });
65220
65685
  await deps.runtime.open(localExtId).catch(() => {
65221
65686
  });
@@ -65237,7 +65702,7 @@ async function updateFromChannel(args, deps) {
65237
65702
  reason: e.message
65238
65703
  };
65239
65704
  }
65240
- await import_promises15.default.rm(prevDir, { recursive: true, force: true });
65705
+ await import_promises16.default.rm(prevDir, { recursive: true, force: true });
65241
65706
  return {
65242
65707
  kind: "updated",
65243
65708
  extId: localExtId,
@@ -65245,9 +65710,9 @@ async function updateFromChannel(args, deps) {
65245
65710
  };
65246
65711
  }
65247
65712
  async function rollback(deps, localExtId, liveDir, prevDir) {
65248
- await import_promises15.default.rm(liveDir, { recursive: true, force: true }).catch(() => {
65713
+ await import_promises16.default.rm(liveDir, { recursive: true, force: true }).catch(() => {
65249
65714
  });
65250
- await import_promises15.default.rename(prevDir, liveDir).catch(() => {
65715
+ await import_promises16.default.rename(prevDir, liveDir).catch(() => {
65251
65716
  });
65252
65717
  await deps.runtime.open(localExtId).catch(() => {
65253
65718
  });
@@ -65270,18 +65735,18 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
65270
65735
  );
65271
65736
  }
65272
65737
  }
65273
- const manifestPath = import_node_path68.default.join(root, extId, "manifest.json");
65738
+ const manifestPath = import_node_path69.default.join(root, extId, "manifest.json");
65274
65739
  const manifest = await readManifest(root, extId);
65275
65740
  const next = { ...manifest, version: newVersion };
65276
65741
  const tmp = `${manifestPath}.tmp`;
65277
- await import_promises16.default.writeFile(tmp, JSON.stringify(next, null, 2));
65278
- await import_promises16.default.rename(tmp, manifestPath);
65742
+ await import_promises17.default.writeFile(tmp, JSON.stringify(next, null, 2));
65743
+ await import_promises17.default.rename(tmp, manifestPath);
65279
65744
  }
65280
65745
  async function readManifest(root, extId) {
65281
- const file = import_node_path68.default.join(root, extId, "manifest.json");
65746
+ const file = import_node_path69.default.join(root, extId, "manifest.json");
65282
65747
  let raw;
65283
65748
  try {
65284
- raw = await import_promises16.default.readFile(file, "utf8");
65749
+ raw = await import_promises17.default.readFile(file, "utf8");
65285
65750
  } catch (e) {
65286
65751
  if (e.code === "ENOENT") {
65287
65752
  throw new ClawdError(ERROR_CODES.INVALID_PARAM, `extension ${extId} not installed`);
@@ -65362,7 +65827,7 @@ function buildExtensionHandlers(deps) {
65362
65827
  };
65363
65828
  async function buildSnapshotMeta(extId) {
65364
65829
  const manifest = await readManifest(deps.root, extId);
65365
- const { sha256, buffer } = await bundleExtensionDir(import_node_path68.default.join(deps.root, extId));
65830
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path69.default.join(deps.root, extId));
65366
65831
  return { manifest, contentHash: sha256, buffer };
65367
65832
  }
65368
65833
  const publish = async (frame, _client, ctx) => {
@@ -65537,7 +66002,7 @@ function buildExtensionHandlers(deps) {
65537
66002
  }
65538
66003
 
65539
66004
  // src/app-builder/kill-port.ts
65540
- var import_node_child_process16 = require("child_process");
66005
+ var import_node_child_process17 = require("child_process");
65541
66006
  async function killPortOccupants(port, ownedPids, logger) {
65542
66007
  let pids;
65543
66008
  try {
@@ -65579,7 +66044,7 @@ async function killPortOccupants(port, ownedPids, logger) {
65579
66044
  }
65580
66045
  function listPidsOnPort(port) {
65581
66046
  return new Promise((resolve9, reject) => {
65582
- (0, import_node_child_process16.execFile)(
66047
+ (0, import_node_child_process17.execFile)(
65583
66048
  "lsof",
65584
66049
  ["-ti", `:${port}`],
65585
66050
  { timeout: 3e3 },
@@ -65605,7 +66070,7 @@ var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
65605
66070
 
65606
66071
  // src/handlers/app-builder.ts
65607
66072
  init_protocol();
65608
- var import_node_path69 = require("path");
66073
+ var import_node_path70 = require("path");
65609
66074
  var import_node_fs52 = require("fs");
65610
66075
  var DEFAULT_TEMPLATE = "nestjs-react";
65611
66076
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
@@ -65752,13 +66217,13 @@ function buildAppBuilderHandlers(deps) {
65752
66217
  const created = await deps.createProjectOnDisk({
65753
66218
  store: userStore,
65754
66219
  name: f.name,
65755
- templateSrcDir: (0, import_node_path69.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE),
65756
- scaffoldScript: (0, import_node_path69.join)(deps.deployKitRoot, "scripts", "new-extension.sh"),
66220
+ templateSrcDir: (0, import_node_path70.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE),
66221
+ scaffoldScript: (0, import_node_path70.join)(deps.deployKitRoot, "scripts", "new-extension.sh"),
65757
66222
  reservedPorts,
65758
66223
  // 凭据只进 scaffold 子进程的 env,且**只给这个 persona 的 kit 模板声明要的那几个变量**
65759
66224
  // (M1b Step 5)。整表塞进去粒度只到「进程」——那会把 service-role key 交给一个用不到
65760
66225
  // 它的脚本。new-extension.sh 用它把模板的 `${VAR}` 渲成项目可跑的 server/.env。
65761
- extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path69.join)(personaRoot, "extension-kit")),
66226
+ extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path70.join)(personaRoot, "extension-kit")),
65762
66227
  ...deps.logger ? { logger: deps.logger } : {}
65763
66228
  });
65764
66229
  project = created.project;
@@ -65957,7 +66422,7 @@ function buildAppBuilderHandlers(deps) {
65957
66422
  await userStore.clearPublishJob(args.name);
65958
66423
  }
65959
66424
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
65960
- const scriptPath = (0, import_node_path69.join)(deps.deployKitRoot, "scripts", "publish.sh");
66425
+ const scriptPath = (0, import_node_path70.join)(deps.deployKitRoot, "scripts", "publish.sh");
65961
66426
  deps.logger?.info("app-builder.publish.start", {
65962
66427
  name: args.name,
65963
66428
  sessionId: boundSession.sessionId,
@@ -65973,7 +66438,7 @@ function buildAppBuilderHandlers(deps) {
65973
66438
  // 凭据只进 publish.sh 这个子进程的 env,且只给它的 kit 模板声明要的那几个变量
65974
66439
  // (M1b Step 5)。那个进程里跑着 `eval "$BUILD_CMD"`——项目自带的构建命令会继承这份
65975
66440
  // env,多给一个变量就是多交一个凭据给它。personaRoot 上面已按绑定 session 的 persona 解析。
65976
- extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path69.join)(personaRoot, "extension-kit")),
66441
+ extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path70.join)(personaRoot, "extension-kit")),
65977
66442
  hooks: {
65978
66443
  // 元数据每次写盘(publishJob 起落 / prodUrl 回填)后重推一帧:UI 渲染 PublishProgress
65979
66444
  // 三段 checklist 依赖 project.publishJob.status==='in-flight',而 publishJob 字段只有
@@ -66381,7 +66846,7 @@ function buildTopicHandlers(deps) {
66381
66846
  init_protocol();
66382
66847
 
66383
66848
  // src/channel/authority.ts
66384
- var import_promises17 = __toESM(require("fs/promises"), 1);
66849
+ var import_promises18 = __toESM(require("fs/promises"), 1);
66385
66850
  init_protocol();
66386
66851
  var DEFAULT_AUTHORITY_RULES = [
66387
66852
  { id: "outbound-message", desc: "\u4EE5\u8001\u677F\u540D\u4E49\u7ED9\u5176\u4ED6\u4EBA\u53D1\u6D88\u606F\uFF08IM/\u90AE\u4EF6\uFF09", action: "ask" },
@@ -66399,7 +66864,7 @@ async function resolveAuthority(args) {
66399
66864
  let source;
66400
66865
  let raw = null;
66401
66866
  try {
66402
- raw = await import_promises17.default.readFile(args.tablePath, "utf8");
66867
+ raw = await import_promises18.default.readFile(args.tablePath, "utf8");
66403
66868
  } catch (e) {
66404
66869
  if (e.code !== "ENOENT") {
66405
66870
  return askBecause(`\u6388\u6743\u8BBE\u5B9A\u8BFB\u4E0D\u51FA\u6765\uFF08${args.tablePath}\uFF09\uFF1A${e.message}`);
@@ -66579,11 +67044,11 @@ function parsePrDetailResponse(json, repoRef) {
66579
67044
  // src/handlers/github.ts
66580
67045
  var HOSTNAME = "github.com";
66581
67046
  function buildGithubHandlers(deps) {
66582
- const { gh } = deps;
67047
+ const { gh: gh2 } = deps;
66583
67048
  return {
66584
67049
  "github:status": async () => {
66585
67050
  try {
66586
- await gh.run(["--version"]);
67051
+ await gh2.run(["--version"]);
66587
67052
  } catch (err) {
66588
67053
  if (err instanceof GhError && err.kind === "gh-missing") {
66589
67054
  return { response: { installed: false, authenticated: false } };
@@ -66591,17 +67056,17 @@ function buildGithubHandlers(deps) {
66591
67056
  throw err;
66592
67057
  }
66593
67058
  try {
66594
- await gh.run(["auth", "status", "--active", "--hostname", HOSTNAME]);
67059
+ await gh2.run(["auth", "status", "--active", "--hostname", HOSTNAME]);
66595
67060
  } catch {
66596
67061
  return { response: { installed: true, authenticated: false } };
66597
67062
  }
66598
- const login = (await gh.run(["api", "user", "--jq", ".login"])).trim();
67063
+ const login = (await gh2.run(["api", "user", "--jq", ".login"])).trim();
66599
67064
  const response = { installed: true, authenticated: true, login };
66600
67065
  return { response };
66601
67066
  },
66602
67067
  "github:prList": async (frame) => {
66603
67068
  const { role } = GithubPrListArgs.parse(frame);
66604
- const stdout = await gh.run([
67069
+ const stdout = await gh2.run([
66605
67070
  "api",
66606
67071
  "graphql",
66607
67072
  "-f",
@@ -66617,7 +67082,7 @@ function buildGithubHandlers(deps) {
66617
67082
  },
66618
67083
  "github:prDetail": async (frame) => {
66619
67084
  const { owner: owner2, repo: repo2, number: number2 } = GithubPrDetailArgs.parse(frame);
66620
- const stdout = await gh.run([
67085
+ const stdout = await gh2.run([
66621
67086
  "api",
66622
67087
  "graphql",
66623
67088
  "-f",
@@ -66635,7 +67100,7 @@ function buildGithubHandlers(deps) {
66635
67100
  "github:prMerge": async (frame) => {
66636
67101
  const { owner: owner2, repo: repo2, number: number2, expectedHeadSha } = GithubPrMergeArgs.parse(frame);
66637
67102
  try {
66638
- await gh.run([
67103
+ await gh2.run([
66639
67104
  "pr",
66640
67105
  "merge",
66641
67106
  String(number2),
@@ -66655,19 +67120,19 @@ function buildGithubHandlers(deps) {
66655
67120
  },
66656
67121
  "github:prComment": async (frame) => {
66657
67122
  const { owner: owner2, repo: repo2, number: number2, body } = GithubPrCommentArgs.parse(frame);
66658
- await gh.run(["api", `repos/${owner2}/${repo2}/issues/${number2}/comments`, "-f", `body=${body}`]);
67123
+ await gh2.run(["api", `repos/${owner2}/${repo2}/issues/${number2}/comments`, "-f", `body=${body}`]);
66659
67124
  return { response: { posted: true } };
66660
67125
  },
66661
67126
  "github:prSetReady": async (frame) => {
66662
67127
  const { owner: owner2, repo: repo2, number: number2, ready } = GithubPrSetReadyArgs.parse(frame);
66663
67128
  const args = ["pr", "ready", String(number2), "--repo", `${owner2}/${repo2}`];
66664
67129
  if (!ready) args.push("--undo");
66665
- await gh.run(args);
67130
+ await gh2.run(args);
66666
67131
  return { response: { updated: true } };
66667
67132
  },
66668
67133
  "github:collaborators": async (frame) => {
66669
67134
  const { owner: owner2, repo: repo2 } = GithubCollaboratorsArgs.parse(frame);
66670
- const stdout = await gh.run(["api", `repos/${owner2}/${repo2}/collaborators?per_page=100`]);
67135
+ const stdout = await gh2.run(["api", `repos/${owner2}/${repo2}/collaborators?per_page=100`]);
66671
67136
  const arr = JSON.parse(stdout);
66672
67137
  const logins = arr.map((c) => String(c.login ?? "")).filter((s) => s !== "");
66673
67138
  return { response: { logins } };
@@ -66676,7 +67141,7 @@ function buildGithubHandlers(deps) {
66676
67141
  const { owner: owner2, repo: repo2, number: number2, reviewers } = GithubPrRequestReviewersArgs.parse(frame);
66677
67142
  const args = ["api", "-X", "POST", `repos/${owner2}/${repo2}/pulls/${number2}/requested_reviewers`];
66678
67143
  for (const r of reviewers) args.push("-f", `reviewers[]=${r}`);
66679
- await gh.run(args);
67144
+ await gh2.run(args);
66680
67145
  return { response: { requested: true } };
66681
67146
  }
66682
67147
  };
@@ -66708,12 +67173,12 @@ function buildVisitorHandlers(deps) {
66708
67173
  }
66709
67174
 
66710
67175
  // src/extension/registry.ts
66711
- var import_promises18 = __toESM(require("fs/promises"), 1);
66712
- var import_node_path70 = __toESM(require("path"), 1);
67176
+ var import_promises19 = __toESM(require("fs/promises"), 1);
67177
+ var import_node_path71 = __toESM(require("path"), 1);
66713
67178
  async function loadAll(root) {
66714
67179
  let entries;
66715
67180
  try {
66716
- entries = await import_promises18.default.readdir(root, { withFileTypes: true });
67181
+ entries = await import_promises19.default.readdir(root, { withFileTypes: true });
66717
67182
  } catch (e) {
66718
67183
  if (e.code === "ENOENT") return [];
66719
67184
  throw e;
@@ -66722,16 +67187,16 @@ async function loadAll(root) {
66722
67187
  for (const ent of entries) {
66723
67188
  if (!ent.isDirectory()) continue;
66724
67189
  if (ent.name.startsWith(".")) continue;
66725
- records.push(await loadOne(import_node_path70.default.join(root, ent.name), ent.name));
67190
+ records.push(await loadOne(import_node_path71.default.join(root, ent.name), ent.name));
66726
67191
  }
66727
67192
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
66728
67193
  return records;
66729
67194
  }
66730
67195
  async function loadOne(dir, dirName) {
66731
- const manifestPath = import_node_path70.default.join(dir, "manifest.json");
67196
+ const manifestPath = import_node_path71.default.join(dir, "manifest.json");
66732
67197
  let raw;
66733
67198
  try {
66734
- raw = await import_promises18.default.readFile(manifestPath, "utf8");
67199
+ raw = await import_promises19.default.readFile(manifestPath, "utf8");
66735
67200
  } catch {
66736
67201
  return {
66737
67202
  extId: dirName,
@@ -66772,8 +67237,8 @@ async function loadOne(dir, dirName) {
66772
67237
  }
66773
67238
 
66774
67239
  // src/extension/uninstall.ts
66775
- var import_promises19 = __toESM(require("fs/promises"), 1);
66776
- var import_node_path71 = __toESM(require("path"), 1);
67240
+ var import_promises20 = __toESM(require("fs/promises"), 1);
67241
+ var import_node_path72 = __toESM(require("path"), 1);
66777
67242
  var UninstallError = class extends Error {
66778
67243
  constructor(code, message) {
66779
67244
  super(message);
@@ -66782,32 +67247,32 @@ var UninstallError = class extends Error {
66782
67247
  code;
66783
67248
  };
66784
67249
  async function uninstall(deps) {
66785
- const dir = import_node_path71.default.join(deps.root, deps.extId);
67250
+ const dir = import_node_path72.default.join(deps.root, deps.extId);
66786
67251
  try {
66787
- await import_promises19.default.access(dir);
67252
+ await import_promises20.default.access(dir);
66788
67253
  } catch {
66789
67254
  throw new UninstallError("NOT_FOUND", `extension ${deps.extId} not installed`);
66790
67255
  }
66791
67256
  await deps.runtime.close(deps.extId);
66792
- await import_promises19.default.rm(dir, { recursive: true, force: true });
67257
+ await import_promises20.default.rm(dir, { recursive: true, force: true });
66793
67258
  }
66794
67259
 
66795
67260
  // src/handlers/index.ts
66796
- var import_node_crypto20 = require("crypto");
67261
+ var import_node_crypto21 = require("crypto");
66797
67262
 
66798
67263
  // src/handlers/peer-exec.ts
66799
67264
  init_protocol();
66800
67265
 
66801
67266
  // src/peer-ops/run-command.ts
66802
- var import_node_child_process17 = require("child_process");
66803
- var import_node_os25 = __toESM(require("os"), 1);
67267
+ var import_node_child_process18 = require("child_process");
67268
+ var import_node_os26 = __toESM(require("os"), 1);
66804
67269
  var DEFAULT_TIMEOUT_MS5 = 3e4;
66805
67270
  var MAX_TIMEOUT_MS = 3e5;
66806
67271
  var MAX_OUTPUT_BYTES = 1048576;
66807
67272
  function runCommand(command, opts = {}) {
66808
67273
  const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5, MAX_TIMEOUT_MS);
66809
67274
  return new Promise((resolve9) => {
66810
- const child = (0, import_node_child_process17.spawn)("bash", ["-c", command], { cwd: import_node_os25.default.homedir() });
67275
+ const child = (0, import_node_child_process18.spawn)("bash", ["-c", command], { cwd: import_node_os26.default.homedir() });
66811
67276
  const out = [];
66812
67277
  const err = [];
66813
67278
  let outBytes = 0;
@@ -66949,7 +67414,7 @@ function buildMethodHandlers(deps) {
66949
67414
  const c = deps.contactStore.get(deviceId);
66950
67415
  return c ? { deviceId: c.deviceId, remoteUrl: c.remoteUrl, connectToken: c.connectToken } : null;
66951
67416
  },
66952
- genId: () => (0, import_node_crypto20.randomUUID)(),
67417
+ genId: () => (0, import_node_crypto21.randomUUID)(),
66953
67418
  now: () => Date.now(),
66954
67419
  forwardInboxPostToPeer,
66955
67420
  logger: deps.logger
@@ -67018,7 +67483,7 @@ function buildMethodHandlers(deps) {
67018
67483
  broadcast: deps.broadcastToOwners
67019
67484
  }),
67020
67485
  ...buildMasterHandlers({
67021
- authorityTablePath: import_node_path72.default.join(deps.masterDataDir, "master-authority.json")
67486
+ authorityTablePath: import_node_path73.default.join(deps.masterDataDir, "master-authority.json")
67022
67487
  }),
67023
67488
  ...buildTopicHandlers({
67024
67489
  topicStore: deps.topicStore,
@@ -67049,23 +67514,23 @@ function buildMethodHandlers(deps) {
67049
67514
  init_protocol();
67050
67515
 
67051
67516
  // src/tools/version-probe.ts
67052
- var import_node_child_process19 = require("child_process");
67517
+ var import_node_child_process20 = require("child_process");
67053
67518
  init_claude();
67054
67519
 
67055
67520
  // src/tools/shell-path.ts
67056
- var import_node_child_process18 = require("child_process");
67057
- var import_node_os26 = __toESM(require("os"), 1);
67521
+ var import_node_child_process19 = require("child_process");
67522
+ var import_node_os27 = __toESM(require("os"), 1);
67058
67523
  function refreshPathFromLoginShell() {
67059
67524
  if (process.platform === "win32") return;
67060
- const shell = process.env.SHELL ?? import_node_os26.default.userInfo().shell ?? "/bin/zsh";
67525
+ const shell = process.env.SHELL ?? import_node_os27.default.userInfo().shell ?? "/bin/zsh";
67061
67526
  try {
67062
- const out = (0, import_node_child_process18.execFileSync)(shell, ["-ilc", 'command echo -n "$PATH"'], {
67527
+ const out = (0, import_node_child_process19.execFileSync)(shell, ["-ilc", 'command echo -n "$PATH"'], {
67063
67528
  encoding: "utf8",
67064
67529
  timeout: 3e3,
67065
67530
  stdio: ["ignore", "pipe", "ignore"]
67066
67531
  });
67067
- const path98 = out.trim();
67068
- if (path98) process.env.PATH = path98;
67532
+ const path99 = out.trim();
67533
+ if (path99) process.env.PATH = path99;
67069
67534
  } catch {
67070
67535
  }
67071
67536
  }
@@ -67076,7 +67541,7 @@ function parseVersionOutput(out) {
67076
67541
  }
67077
67542
  function execVersion(bin) {
67078
67543
  return new Promise((resolve9, reject) => {
67079
- (0, import_node_child_process19.execFile)(bin, ["--version"], { timeout: 5e3 }, (err, stdout) => {
67544
+ (0, import_node_child_process20.execFile)(bin, ["--version"], { timeout: 5e3 }, (err, stdout) => {
67080
67545
  if (err) reject(err);
67081
67546
  else resolve9(String(stdout));
67082
67547
  });
@@ -67190,8 +67655,8 @@ function buildOnboardingHandlers(deps) {
67190
67655
 
67191
67656
  // src/app-builder-plugin/project-store.ts
67192
67657
  var import_node_fs53 = require("fs");
67193
- var import_node_child_process20 = require("child_process");
67194
- var import_node_path73 = require("path");
67658
+ var import_node_child_process21 = require("child_process");
67659
+ var import_node_path74 = require("path");
67195
67660
  init_protocol();
67196
67661
  var PROJECTS_DIR = "projects";
67197
67662
  var META_FILE = ".clawd-project.json";
@@ -67221,14 +67686,14 @@ var ProjectStore = class {
67221
67686
  }
67222
67687
  /** projects/<name>/.clawd-project.json 路径 */
67223
67688
  metaPath(name) {
67224
- return (0, import_node_path73.join)(this.projectsRoot(), name, META_FILE);
67689
+ return (0, import_node_path74.join)(this.projectsRoot(), name, META_FILE);
67225
67690
  }
67226
67691
  /** projects/<name>/ 目录路径(cwd 用) */
67227
67692
  projectDir(name) {
67228
- return (0, import_node_path73.join)(this.projectsRoot(), name);
67693
+ return (0, import_node_path74.join)(this.projectsRoot(), name);
67229
67694
  }
67230
67695
  projectsRoot() {
67231
- return (0, import_node_path73.join)(this.root, PROJECTS_DIR);
67696
+ return (0, import_node_path74.join)(this.root, PROJECTS_DIR);
67232
67697
  }
67233
67698
  async list() {
67234
67699
  let entries;
@@ -67311,7 +67776,7 @@ var ProjectStore = class {
67311
67776
  async scaffold(name, templateSrcDir, scaffoldScriptPath, extraEnv) {
67312
67777
  const destDir = this.projectDir(name);
67313
67778
  return await new Promise((resolve9, reject) => {
67314
- const child = (0, import_node_child_process20.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
67779
+ const child = (0, import_node_child_process21.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
67315
67780
  // extraEnv 排在 PATH **之前**:凭据表里若混进一条名叫 PATH 的条目,顶掉 PATH 会让
67316
67781
  // 脚本以「命令找不到」的形态崩在离现场很远的地方。
67317
67782
  env: { ...process.env, ...extraEnv ?? {}, PATH: process.env.PATH ?? "" },
@@ -67425,7 +67890,7 @@ var ProjectStore = class {
67425
67890
  };
67426
67891
 
67427
67892
  // src/app-builder/dev-server-supervisor.ts
67428
- var import_node_child_process21 = require("child_process");
67893
+ var import_node_child_process22 = require("child_process");
67429
67894
  var import_node_events2 = require("events");
67430
67895
  var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
67431
67896
  var DevServerSupervisor = class extends import_node_events2.EventEmitter {
@@ -67462,7 +67927,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
67462
67927
  tunnelHost: args.tunnelHost,
67463
67928
  devCommand: cmd
67464
67929
  });
67465
- const child = (0, import_node_child_process21.spawn)("sh", ["-c", cmd], {
67930
+ const child = (0, import_node_child_process22.spawn)("sh", ["-c", cmd], {
67466
67931
  cwd: args.cwd,
67467
67932
  env,
67468
67933
  stdio: "pipe",
@@ -67679,10 +68144,10 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
67679
68144
  };
67680
68145
 
67681
68146
  // src/app-builder-plugin/core.ts
67682
- var import_node_child_process23 = require("child_process");
68147
+ var import_node_child_process24 = require("child_process");
67683
68148
 
67684
68149
  // src/app-builder-plugin/publish-registry.ts
67685
- var import_node_crypto21 = require("crypto");
68150
+ var import_node_crypto22 = require("crypto");
67686
68151
  var PublishJobRegistry = class {
67687
68152
  jobs = /* @__PURE__ */ new Map();
67688
68153
  has(name) {
@@ -67699,7 +68164,7 @@ var PublishJobRegistry = class {
67699
68164
  if (this.jobs.has(args.name)) {
67700
68165
  throw new Error(`already publishing: ${args.name}`);
67701
68166
  }
67702
- const jobId = args.jobId ?? `job-${(0, import_node_crypto21.randomUUID)()}`;
68167
+ const jobId = args.jobId ?? `job-${(0, import_node_crypto22.randomUUID)()}`;
67703
68168
  this.jobs.set(args.name, {
67704
68169
  jobId,
67705
68170
  name: args.name,
@@ -67732,9 +68197,9 @@ var PublishJobRegistry = class {
67732
68197
  };
67733
68198
 
67734
68199
  // src/app-builder-plugin/publish-job-runner.ts
67735
- var import_node_child_process22 = require("child_process");
68200
+ var import_node_child_process23 = require("child_process");
67736
68201
  var import_node_fs54 = require("fs");
67737
- var import_node_path74 = require("path");
68202
+ var import_node_path75 = require("path");
67738
68203
 
67739
68204
  // src/app-builder-plugin/publish-stage-parser.ts
67740
68205
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -67761,19 +68226,19 @@ function tailStderrLines(buf, n) {
67761
68226
  // src/app-builder-plugin/publish-job-runner.ts
67762
68227
  async function startPublishJob(deps, args) {
67763
68228
  const { registry: registry2, projectDir } = deps;
67764
- const spawn14 = deps.spawnImpl ?? import_node_child_process22.spawn;
68229
+ const spawn15 = deps.spawnImpl ?? import_node_child_process23.spawn;
67765
68230
  if (registry2.has(args.name)) {
67766
68231
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
67767
68232
  }
67768
68233
  const projDir = projectDir(args.name);
67769
- const logPath = (0, import_node_path74.join)(projDir, ".publish.log");
68234
+ const logPath = (0, import_node_path75.join)(projDir, ".publish.log");
67770
68235
  let logStream = null;
67771
68236
  try {
67772
68237
  logStream = (0, import_node_fs54.createWriteStream)(logPath, { flags: "w" });
67773
68238
  } catch {
67774
68239
  logStream = null;
67775
68240
  }
67776
- const child = spawn14("bash", [args.scriptPath, projDir, args.personaRoot ?? ""], {
68241
+ const child = spawn15("bash", [args.scriptPath, projDir, args.personaRoot ?? ""], {
67777
68242
  cwd: projDir,
67778
68243
  // 宿主给的 env 覆盖在 process.env 之上:daemon 进程本身没有这些变量(它们只在这一个
67779
68244
  // 子进程里活着)。云上宿主不传 extraEnv,凭据本来就在容器 env 里。
@@ -68113,9 +68578,9 @@ async function recoverInterruptedPublishJobs(store, logger) {
68113
68578
 
68114
68579
  // src/app-builder-plugin/mcp-config.ts
68115
68580
  var import_node_fs55 = __toESM(require("fs"), 1);
68116
- var import_node_path75 = __toESM(require("path"), 1);
68581
+ var import_node_path76 = __toESM(require("path"), 1);
68117
68582
  function appBuilderMcpConfigPath(dataDir) {
68118
- return import_node_path75.default.join(dataDir, "app-builder.mcp.json");
68583
+ return import_node_path76.default.join(dataDir, "app-builder.mcp.json");
68119
68584
  }
68120
68585
  function writeAppBuilderMcpConfig(args) {
68121
68586
  const cfgPath = appBuilderMcpConfigPath(args.dataDir);
@@ -68129,8 +68594,8 @@ function writeAppBuilderMcpConfig(args) {
68129
68594
  env: {
68130
68595
  CLAWD_DAEMON_TOKEN: args.daemonToken,
68131
68596
  CLAWD_DAEMON_URL: args.daemonUrl,
68132
- CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT: import_node_path75.default.join(args.deployKitScriptsDir, "new-extension.sh"),
68133
- CLAWD_APP_BUILDER_PUBLISH_SCRIPT: import_node_path75.default.join(args.deployKitScriptsDir, "publish.sh"),
68597
+ CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT: import_node_path76.default.join(args.deployKitScriptsDir, "new-extension.sh"),
68598
+ CLAWD_APP_BUILDER_PUBLISH_SCRIPT: import_node_path76.default.join(args.deployKitScriptsDir, "publish.sh"),
68134
68599
  ...args.logPath ? { CLAWD_APP_BUILDER_LOG: args.logPath } : {}
68135
68600
  }
68136
68601
  }
@@ -68177,9 +68642,9 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
68177
68642
  }
68178
68643
 
68179
68644
  // src/extension/runtime.ts
68180
- var import_node_child_process24 = require("child_process");
68181
- var import_node_path76 = __toESM(require("path"), 1);
68182
- var import_promises20 = require("timers/promises");
68645
+ var import_node_child_process25 = require("child_process");
68646
+ var import_node_path77 = __toESM(require("path"), 1);
68647
+ var import_promises21 = require("timers/promises");
68183
68648
 
68184
68649
  // src/extension/port-allocator.ts
68185
68650
  var import_node_net2 = __toESM(require("net"), 1);
@@ -68279,13 +68744,13 @@ var Runtime = class {
68279
68744
  /\$CLAWOS_EXT_PORT/g,
68280
68745
  String(port)
68281
68746
  );
68282
- const dir = import_node_path76.default.join(this.root, extId);
68747
+ const dir = import_node_path77.default.join(this.root, extId);
68283
68748
  const env = {
68284
68749
  ...process.env,
68285
68750
  CLAWOS_EXT_PORT: String(port),
68286
68751
  CLAWOS_EXT_ID: extId
68287
68752
  };
68288
- const child = (0, import_node_child_process24.spawn)("sh", ["-c", cmd], {
68753
+ const child = (0, import_node_child_process25.spawn)("sh", ["-c", cmd], {
68289
68754
  cwd: dir,
68290
68755
  env,
68291
68756
  stdio: ["ignore", "pipe", "pipe"],
@@ -68355,7 +68820,7 @@ ${handle.stderrTail}`
68355
68820
  if (res.ok) return;
68356
68821
  } catch {
68357
68822
  }
68358
- await (0, import_promises20.setTimeout)(this.healthzIntervalMs);
68823
+ await (0, import_promises21.setTimeout)(this.healthzIntervalMs);
68359
68824
  }
68360
68825
  throw new RuntimeError(
68361
68826
  "HEALTHZ_FAILED",
@@ -68380,7 +68845,7 @@ ${handle.stderrTail}`
68380
68845
  };
68381
68846
  killGroup("SIGTERM");
68382
68847
  const exited = new Promise((resolve9) => child.once("exit", () => resolve9()));
68383
- const timed = (0, import_promises20.setTimeout)(5e3).then(() => "timeout");
68848
+ const timed = (0, import_promises21.setTimeout)(5e3).then(() => "timeout");
68384
68849
  const winner = await Promise.race([exited.then(() => "exited"), timed]);
68385
68850
  if (winner === "timeout" && child.exitCode === null) {
68386
68851
  killGroup("SIGKILL");
@@ -68390,8 +68855,8 @@ ${handle.stderrTail}`
68390
68855
  };
68391
68856
 
68392
68857
  // src/extension/published-channels.ts
68393
- var import_promises21 = __toESM(require("fs/promises"), 1);
68394
- var import_node_path77 = __toESM(require("path"), 1);
68858
+ var import_promises22 = __toESM(require("fs/promises"), 1);
68859
+ var import_node_path78 = __toESM(require("path"), 1);
68395
68860
  init_zod();
68396
68861
  var PublishedChannelsError = class extends Error {
68397
68862
  constructor(code, message) {
@@ -68421,7 +68886,7 @@ var PublishedChannelStore = class {
68421
68886
  this.channels.clear();
68422
68887
  let raw;
68423
68888
  try {
68424
- raw = await import_promises21.default.readFile(this.filePath, "utf8");
68889
+ raw = await import_promises22.default.readFile(this.filePath, "utf8");
68425
68890
  } catch (e) {
68426
68891
  if (e.code === "ENOENT") {
68427
68892
  this.loaded = true;
@@ -68490,15 +68955,15 @@ var PublishedChannelStore = class {
68490
68955
  )
68491
68956
  };
68492
68957
  const tmp = `${this.filePath}.tmp`;
68493
- await import_promises21.default.mkdir(import_node_path77.default.dirname(this.filePath), { recursive: true });
68494
- await import_promises21.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
68495
- await import_promises21.default.rename(tmp, this.filePath);
68958
+ await import_promises22.default.mkdir(import_node_path78.default.dirname(this.filePath), { recursive: true });
68959
+ await import_promises22.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
68960
+ await import_promises22.default.rename(tmp, this.filePath);
68496
68961
  }
68497
68962
  };
68498
68963
 
68499
68964
  // src/extension/bundle-cache.ts
68500
- var import_promises22 = __toESM(require("fs/promises"), 1);
68501
- var import_node_path78 = __toESM(require("path"), 1);
68965
+ var import_promises23 = __toESM(require("fs/promises"), 1);
68966
+ var import_node_path79 = __toESM(require("path"), 1);
68502
68967
  var BundleCache = class {
68503
68968
  constructor(rootDir) {
68504
68969
  this.rootDir = rootDir;
@@ -68506,17 +68971,17 @@ var BundleCache = class {
68506
68971
  rootDir;
68507
68972
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
68508
68973
  async write(snapshotHash, buffer) {
68509
- await import_promises22.default.mkdir(this.rootDir, { recursive: true });
68510
- const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
68974
+ await import_promises23.default.mkdir(this.rootDir, { recursive: true });
68975
+ const file = import_node_path79.default.join(this.rootDir, `${snapshotHash}.zip`);
68511
68976
  const tmp = `${file}.tmp`;
68512
- await import_promises22.default.writeFile(tmp, buffer, { mode: 384 });
68513
- await import_promises22.default.rename(tmp, file);
68977
+ await import_promises23.default.writeFile(tmp, buffer, { mode: 384 });
68978
+ await import_promises23.default.rename(tmp, file);
68514
68979
  }
68515
68980
  /** Returns the bundle bytes, or null when the file doesn't exist. */
68516
68981
  async read(snapshotHash) {
68517
- const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
68982
+ const file = import_node_path79.default.join(this.rootDir, `${snapshotHash}.zip`);
68518
68983
  try {
68519
- return await import_promises22.default.readFile(file);
68984
+ return await import_promises23.default.readFile(file);
68520
68985
  } catch (e) {
68521
68986
  if (e.code === "ENOENT") return null;
68522
68987
  throw e;
@@ -68524,8 +68989,8 @@ var BundleCache = class {
68524
68989
  }
68525
68990
  /** Idempotent — missing file is not an error. */
68526
68991
  async delete(snapshotHash) {
68527
- const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
68528
- await import_promises22.default.rm(file, { force: true });
68992
+ const file = import_node_path79.default.join(this.rootDir, `${snapshotHash}.zip`);
68993
+ await import_promises23.default.rm(file, { force: true });
68529
68994
  }
68530
68995
  };
68531
68996
 
@@ -68545,26 +69010,26 @@ async function startDaemon(config) {
68545
69010
  },
68546
69011
  source: "daemon",
68547
69012
  sampling: logShippingCfg.sampling,
68548
- homeDir: import_node_os27.default.homedir()
69013
+ homeDir: import_node_os28.default.homedir()
68549
69014
  });
68550
- const logDir = import_node_path79.default.join(config.dataDir, "log");
69015
+ const logDir = import_node_path80.default.join(config.dataDir, "log");
68551
69016
  import_node_fs56.default.mkdirSync(logDir, { recursive: true });
68552
69017
  const logger = createLogger({
68553
69018
  level: config.logLevel,
68554
- file: import_node_path79.default.join(logDir, "clawd.log"),
69019
+ file: import_node_path80.default.join(logDir, "clawd.log"),
68555
69020
  logClient
68556
69021
  });
68557
69022
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
68558
69023
  const screenIdleProbeLogger = createFileOnlyLogger({
68559
- file: import_node_path79.default.join(logDir, "screen-idle-probe.log"),
69024
+ file: import_node_path80.default.join(logDir, "screen-idle-probe.log"),
68560
69025
  level: "debug"
68561
69026
  });
68562
69027
  logger.info("screen-idle probe logger enabled", {
68563
- file: import_node_path79.default.join(logDir, "screen-idle-probe.log")
69028
+ file: import_node_path80.default.join(logDir, "screen-idle-probe.log")
68564
69029
  });
68565
69030
  const CAP_TARGETS = [
68566
- import_node_path79.default.join(logDir, "clawd.log"),
68567
- import_node_path79.default.join(logDir, "screen-idle-probe.log")
69031
+ import_node_path80.default.join(logDir, "clawd.log"),
69032
+ import_node_path80.default.join(logDir, "screen-idle-probe.log")
68568
69033
  ];
68569
69034
  const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
68570
69035
  const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
@@ -68686,8 +69151,8 @@ async function startDaemon(config) {
68686
69151
  const agents = new AgentsScanner();
68687
69152
  const history = new ClaudeHistoryReader();
68688
69153
  let transport = null;
68689
- const personaStore = new PersonaStore(import_node_path79.default.join(config.dataDir, "personas"));
68690
- const usersRoot = import_node_path79.default.join(config.dataDir, "users");
69154
+ const personaStore = new PersonaStore(import_node_path80.default.join(config.dataDir, "personas"));
69155
+ const usersRoot = import_node_path80.default.join(config.dataDir, "users");
68691
69156
  const defaultsRoot = findDefaultsRoot(logger);
68692
69157
  if (defaultsRoot) {
68693
69158
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -68711,7 +69176,7 @@ async function startDaemon(config) {
68711
69176
  retirePersonaBuilder({ store: personaStore, logger });
68712
69177
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
68713
69178
  const dispatchStore = createDispatchStore({
68714
- filePath: import_node_path79.default.join(config.dataDir, "dispatch.json"),
69179
+ filePath: import_node_path80.default.join(config.dataDir, "dispatch.json"),
68715
69180
  now: () => Date.now(),
68716
69181
  onFlushError: (err) => logger.error("dispatch store flush failed", {
68717
69182
  reason: err instanceof Error ? err.message : String(err)
@@ -68720,18 +69185,18 @@ async function startDaemon(config) {
68720
69185
  await dispatchStore.load();
68721
69186
  dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
68722
69187
  const channelStore = createChannelStore({
68723
- filePath: import_node_path79.default.join(config.dataDir, "channels.json"),
69188
+ filePath: import_node_path80.default.join(config.dataDir, "channels.json"),
68724
69189
  now: () => Date.now(),
68725
- genId: () => `ch-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
69190
+ genId: () => `ch-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
68726
69191
  onFlushError: (err) => logger.error("channel store flush failed", {
68727
69192
  reason: err instanceof Error ? err.message : String(err)
68728
69193
  })
68729
69194
  });
68730
69195
  await channelStore.load();
68731
69196
  const topicStore = createTopicStore({
68732
- filePath: import_node_path79.default.join(config.dataDir, "topics.json"),
69197
+ filePath: import_node_path80.default.join(config.dataDir, "topics.json"),
68733
69198
  now: () => Date.now(),
68734
- genId: () => `tp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
69199
+ genId: () => `tp-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
68735
69200
  onFlushError: (err) => logger.error("topic store flush failed", {
68736
69201
  reason: err instanceof Error ? err.message : String(err)
68737
69202
  })
@@ -68739,7 +69204,7 @@ async function startDaemon(config) {
68739
69204
  await topicStore.load();
68740
69205
  let deliverPendingRef;
68741
69206
  const personaDispatchManager = new PersonaDispatchManager({
68742
- genId: () => (0, import_node_crypto22.randomUUID)(),
69207
+ genId: () => (0, import_node_crypto23.randomUUID)(),
68743
69208
  store: dispatchStore,
68744
69209
  now: () => Date.now(),
68745
69210
  onCompleted: (sid) => deliverPendingRef?.(sid),
@@ -68756,28 +69221,28 @@ async function startDaemon(config) {
68756
69221
  });
68757
69222
  }
68758
69223
  });
68759
- const here = typeof __dirname === "string" ? __dirname : import_node_path79.default.dirname((0, import_node_url5.fileURLToPath)(import_meta8.url));
69224
+ const here = typeof __dirname === "string" ? __dirname : import_node_path80.default.dirname((0, import_node_url5.fileURLToPath)(import_meta8.url));
68760
69225
  const mcpConfigs = [];
68761
69226
  const secretsBundleRoot = findSecretsBundleRoot(logger);
68762
- const localSecretsDir = import_node_path79.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
69227
+ const localSecretsDir = import_node_path80.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
68763
69228
  const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
68764
69229
  const resolvePersonaMcpConfig = (personaId2) => renderPersonaMcpSecrets({
68765
69230
  personaId: personaId2,
68766
- personaDir: import_node_path79.default.join(config.dataDir, "personas", personaId2),
69231
+ personaDir: import_node_path80.default.join(config.dataDir, "personas", personaId2),
68767
69232
  secrets: readSecrets(),
68768
- outDir: import_node_path79.default.join(config.dataDir, "persona-mcp"),
69233
+ outDir: import_node_path80.default.join(config.dataDir, "persona-mcp"),
68769
69234
  logger
68770
69235
  });
68771
69236
  const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
68772
69237
  const dispatchServerCandidates = [
68773
- import_node_path79.default.join(here, "dispatch", "mcp-server.cjs"),
69238
+ import_node_path80.default.join(here, "dispatch", "mcp-server.cjs"),
68774
69239
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
68775
- import_node_path79.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
69240
+ import_node_path80.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
68776
69241
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
68777
69242
  ];
68778
69243
  const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
68779
69244
  if (dispatchServerScriptPath) {
68780
- const dispatchLogPath = import_node_path79.default.join(logDir, "dispatch-mcp-server.log");
69245
+ const dispatchLogPath = import_node_path80.default.join(logDir, "dispatch-mcp-server.log");
68781
69246
  const dispatchCfgPath = writeDispatchMcpConfig({
68782
69247
  dataDir: config.dataDir,
68783
69248
  serverScriptPath: dispatchServerScriptPath,
@@ -68797,12 +69262,12 @@ async function startDaemon(config) {
68797
69262
  });
68798
69263
  }
68799
69264
  const ticketServerCandidates = [
68800
- import_node_path79.default.join(here, "ticket", "mcp-server.cjs"),
68801
- import_node_path79.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
69265
+ import_node_path80.default.join(here, "ticket", "mcp-server.cjs"),
69266
+ import_node_path80.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
68802
69267
  ];
68803
69268
  const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
68804
69269
  if (ticketServerScriptPath) {
68805
- const ticketLogPath = import_node_path79.default.join(logDir, "ticket-mcp-server.log");
69270
+ const ticketLogPath = import_node_path80.default.join(logDir, "ticket-mcp-server.log");
68806
69271
  const ticketCfgPath = writeTicketMcpConfig({
68807
69272
  dataDir: config.dataDir,
68808
69273
  serverScriptPath: ticketServerScriptPath,
@@ -68824,12 +69289,12 @@ async function startDaemon(config) {
68824
69289
  });
68825
69290
  }
68826
69291
  const shiftServerCandidates = [
68827
- import_node_path79.default.join(here, "shift", "mcp-server.cjs"),
68828
- import_node_path79.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
69292
+ import_node_path80.default.join(here, "shift", "mcp-server.cjs"),
69293
+ import_node_path80.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
68829
69294
  ];
68830
69295
  const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
68831
69296
  if (shiftServerScriptPath) {
68832
- const shiftLogPath = import_node_path79.default.join(logDir, "shift-mcp-server.log");
69297
+ const shiftLogPath = import_node_path80.default.join(logDir, "shift-mcp-server.log");
68833
69298
  const shiftCfgPath = await writeShiftMcpConfig({
68834
69299
  dataDir: config.dataDir,
68835
69300
  serverScriptPath: shiftServerScriptPath,
@@ -68850,12 +69315,12 @@ async function startDaemon(config) {
68850
69315
  );
68851
69316
  }
68852
69317
  const inboxServerCandidates = [
68853
- import_node_path79.default.join(here, "inbox", "mcp-server.cjs"),
68854
- import_node_path79.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
69318
+ import_node_path80.default.join(here, "inbox", "mcp-server.cjs"),
69319
+ import_node_path80.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
68855
69320
  ];
68856
69321
  const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
68857
69322
  if (inboxServerScriptPath) {
68858
- const inboxLogPath = import_node_path79.default.join(logDir, "inbox-mcp-server.log");
69323
+ const inboxLogPath = import_node_path80.default.join(logDir, "inbox-mcp-server.log");
68859
69324
  const inboxCfgPath = await writeInboxMcpConfig({
68860
69325
  dataDir: config.dataDir,
68861
69326
  serverScriptPath: inboxServerScriptPath,
@@ -68876,8 +69341,8 @@ async function startDaemon(config) {
68876
69341
  );
68877
69342
  }
68878
69343
  const peerOpsServerCandidates = [
68879
- import_node_path79.default.join(here, "peer-ops", "mcp-server.cjs"),
68880
- import_node_path79.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
69344
+ import_node_path80.default.join(here, "peer-ops", "mcp-server.cjs"),
69345
+ import_node_path80.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
68881
69346
  ];
68882
69347
  const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
68883
69348
  if (peerOpsServerScriptPath) {
@@ -68899,12 +69364,12 @@ async function startDaemon(config) {
68899
69364
  );
68900
69365
  }
68901
69366
  const rpcToolServerCandidates = [
68902
- import_node_path79.default.join(here, "rpc-tool", "mcp-server.cjs"),
68903
- import_node_path79.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
69367
+ import_node_path80.default.join(here, "rpc-tool", "mcp-server.cjs"),
69368
+ import_node_path80.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
68904
69369
  ];
68905
69370
  const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
68906
69371
  if (rpcToolServerScriptPath) {
68907
- const rpcToolLogPath = import_node_path79.default.join(logDir, "rpc-tool-mcp-server.log");
69372
+ const rpcToolLogPath = import_node_path80.default.join(logDir, "rpc-tool-mcp-server.log");
68908
69373
  const rpcToolCfgPath = writeRpcToolMcpConfig({
68909
69374
  dataDir: config.dataDir,
68910
69375
  serverScriptPath: rpcToolServerScriptPath,
@@ -68925,18 +69390,18 @@ async function startDaemon(config) {
68925
69390
  );
68926
69391
  }
68927
69392
  const appBuilderServerCandidates = [
68928
- import_node_path79.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
68929
- import_node_path79.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
69393
+ import_node_path80.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
69394
+ import_node_path80.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
68930
69395
  ];
68931
69396
  const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
68932
69397
  if (appBuilderServerScriptPath) {
68933
- const appBuilderLogPath = import_node_path79.default.join(logDir, "app-builder-mcp-server.log");
69398
+ const appBuilderLogPath = import_node_path80.default.join(logDir, "app-builder-mcp-server.log");
68934
69399
  const appBuilderCfgPath = writeAppBuilderMcpConfig({
68935
69400
  dataDir: config.dataDir,
68936
69401
  serverScriptPath: appBuilderServerScriptPath,
68937
69402
  daemonToken: resolvedAuthToken,
68938
69403
  daemonUrl: mcpDaemonUrl,
68939
- deployKitScriptsDir: import_node_path79.default.join(config.dataDir, "deploy-kit", "scripts"),
69404
+ deployKitScriptsDir: import_node_path80.default.join(config.dataDir, "deploy-kit", "scripts"),
68940
69405
  logPath: appBuilderLogPath
68941
69406
  });
68942
69407
  mcpConfigs.push({ id: "app-builder", path: appBuilderCfgPath, personas: APP_BUILDER_PERSONAS });
@@ -68952,7 +69417,7 @@ async function startDaemon(config) {
68952
69417
  );
68953
69418
  }
68954
69419
  const shiftStore = createShiftStore({
68955
- filePath: import_node_path79.default.join(config.dataDir, "shift.json"),
69420
+ filePath: import_node_path80.default.join(config.dataDir, "shift.json"),
68956
69421
  ownerIdProvider: () => ownerPrincipalId,
68957
69422
  now: () => Date.now()
68958
69423
  });
@@ -68974,7 +69439,7 @@ async function startDaemon(config) {
68974
69439
  getAdapter,
68975
69440
  historyReader: history,
68976
69441
  dataDir: config.dataDir,
68977
- personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
69442
+ personaRoot: import_node_path80.default.join(config.dataDir, "personas"),
68978
69443
  // dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
68979
69444
  // personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
68980
69445
  getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
@@ -69031,7 +69496,7 @@ async function startDaemon(config) {
69031
69496
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
69032
69497
  attachmentGroup: {
69033
69498
  onFileEdit: (input) => {
69034
- const absPath = import_node_path79.default.isAbsolute(input.relPath) ? input.relPath : import_node_path79.default.join(input.cwd, input.relPath);
69499
+ const absPath = import_node_path80.default.isAbsolute(input.relPath) ? input.relPath : import_node_path80.default.join(input.cwd, input.relPath);
69035
69500
  let size = 0;
69036
69501
  try {
69037
69502
  size = import_node_fs56.default.statSync(absPath).size;
@@ -69064,9 +69529,9 @@ async function startDaemon(config) {
69064
69529
  logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
69065
69530
  }
69066
69531
  const projectsStore = new ProjectsStore({
69067
- file: import_node_path79.default.join(config.dataDir, "projects.json"),
69532
+ file: import_node_path80.default.join(config.dataDir, "projects.json"),
69068
69533
  clawdDir: config.dataDir,
69069
- codexStateFile: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex", ".codex-global-state.json"),
69534
+ codexStateFile: import_node_path80.default.join(import_node_os28.default.homedir(), ".codex", ".codex-global-state.json"),
69070
69535
  logger
69071
69536
  });
69072
69537
  const observer = new SessionObserver({
@@ -69126,12 +69591,12 @@ async function startDaemon(config) {
69126
69591
  screenIdleProbeLogger
69127
69592
  }) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
69128
69593
  registerAdapter("claude", claudeAdapter);
69129
- const codexIsolatedHome = import_node_path79.default.join(config.dataDir, "codex-home");
69594
+ const codexIsolatedHome = import_node_path80.default.join(config.dataDir, "codex-home");
69130
69595
  try {
69131
69596
  import_node_fs56.default.mkdirSync(codexIsolatedHome, { recursive: true });
69132
69597
  for (const f of ["auth.json", "config.toml"]) {
69133
- const link = import_node_path79.default.join(codexIsolatedHome, f);
69134
- const target = import_node_path79.default.join(import_node_os27.default.homedir(), ".codex", f);
69598
+ const link = import_node_path80.default.join(codexIsolatedHome, f);
69599
+ const target = import_node_path80.default.join(import_node_os28.default.homedir(), ".codex", f);
69135
69600
  if (!import_node_fs56.default.existsSync(link) && import_node_fs56.default.existsSync(target)) import_node_fs56.default.symlinkSync(target, link);
69136
69601
  }
69137
69602
  } catch (err) {
@@ -69145,11 +69610,11 @@ async function startDaemon(config) {
69145
69610
  // projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
69146
69611
  codexHomeFor: (cwd) => resolveCodexHome({
69147
69612
  cwd,
69148
- personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
69613
+ personaRoot: import_node_path80.default.join(config.dataDir, "personas"),
69149
69614
  // 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
69150
69615
  // Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
69151
69616
  projectPaths: projectsStore.listMerged().map((x) => x.path),
69152
- sharedHome: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex"),
69617
+ sharedHome: import_node_path80.default.join(import_node_os28.default.homedir(), ".codex"),
69153
69618
  isolatedHome: codexIsolatedHome
69154
69619
  })
69155
69620
  })
@@ -69434,11 +69899,11 @@ async function startDaemon(config) {
69434
69899
  // 'persona/<pid>/owner',default 走 'default'。
69435
69900
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
69436
69901
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
69437
- personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
69902
+ personaRoot: import_node_path80.default.join(config.dataDir, "personas"),
69438
69903
  usersRoot
69439
69904
  },
69440
69905
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
69441
- personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
69906
+ personaRoot: import_node_path80.default.join(config.dataDir, "personas"),
69442
69907
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
69443
69908
  usersRoot,
69444
69909
  // v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
@@ -69539,11 +70004,11 @@ async function startDaemon(config) {
69539
70004
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
69540
70005
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
69541
70006
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
69542
- appBuilderPersonaRoot: import_node_path79.default.join(config.dataDir, "personas", "persona-app-builder"),
70007
+ appBuilderPersonaRoot: import_node_path80.default.join(config.dataDir, "personas", "persona-app-builder"),
69543
70008
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
69544
- deployKitRoot: import_node_path79.default.join(config.dataDir, "deploy-kit"),
70009
+ deployKitRoot: import_node_path80.default.join(config.dataDir, "deploy-kit"),
69545
70010
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
69546
- resolvePersonaRoot: (personaId2) => import_node_path79.default.join(config.dataDir, "personas", personaId2),
70011
+ resolvePersonaRoot: (personaId2) => import_node_path80.default.join(config.dataDir, "personas", personaId2),
69547
70012
  // 凭据表(M1b Step 5):与 MCP 那条同一张表、同一个来源,只是交付给另一个子进程。
69548
70013
  readSecrets,
69549
70014
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
@@ -69600,7 +70065,7 @@ async function startDaemon(config) {
69600
70065
  sourceSessionId: args.sourceSessionId
69601
70066
  });
69602
70067
  const sourceFile = manager.findOwnedSession(args.sourceSessionId);
69603
- const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os27.default.homedir());
70068
+ const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os28.default.homedir());
69604
70069
  logger.info("dispatch.spawnB.source-resolved", {
69605
70070
  dispatchId: args.dispatchId,
69606
70071
  sourceJsonlPath,
@@ -69658,12 +70123,12 @@ async function startDaemon(config) {
69658
70123
  });
69659
70124
  Object.assign(handlers, shiftHandlers);
69660
70125
  const deployReceipts = createReceiptStore({
69661
- filePath: import_node_path79.default.join(config.dataDir, "deploy.json"),
70126
+ filePath: import_node_path80.default.join(config.dataDir, "deploy.json"),
69662
70127
  now: () => Date.now(),
69663
70128
  onFlushError: (err) => logger.error("deploy receipts flush failed", { error: String(err) })
69664
70129
  });
69665
70130
  const deploySecrets = createSecretStore({
69666
- filePath: import_node_path79.default.join(config.dataDir, "deploy-secrets.json"),
70131
+ filePath: import_node_path80.default.join(config.dataDir, "deploy-secrets.json"),
69667
70132
  now: () => Date.now(),
69668
70133
  onFlushError: (err) => logger.error("deploy secrets flush failed", { error: String(err) })
69669
70134
  });
@@ -69694,6 +70159,7 @@ async function startDaemon(config) {
69694
70159
  runNode: (script, args, opts) => runNodeScript(script, args, opts.timeoutMs),
69695
70160
  fetchImpl: fetch,
69696
70161
  now: () => Date.now(),
70162
+ sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
69697
70163
  onStage: (stage) => {
69698
70164
  deployReceipts.update(deployId, { trialStage: stage });
69699
70165
  },
@@ -69706,6 +70172,8 @@ async function startDaemon(config) {
69706
70172
  receipt,
69707
70173
  // 试装带全量(含使用者自带那几条的临时垫付值)——它要真跑一次发布
69708
70174
  secretTable: secretTableFor(receipt, deploySecrets.resolve(deployId), "all"),
70175
+ // persona 目录由 daemon 给:构建器不认识任何 persona 的名字(见 RunTrialArgs.personaDir)
70176
+ personaDir: personaStore.personaDirPath(receipt.personaId),
69709
70177
  round: receipt.trialRound
69710
70178
  }
69711
70179
  );
@@ -69736,7 +70204,7 @@ async function startDaemon(config) {
69736
70204
  hasPersona: (personaId2) => personaStore.has(personaId2),
69737
70205
  startScan: (deployId, personaId2) => {
69738
70206
  const assetLines = SCANNABLE_ASSETS.map(
69739
- (name) => ` - ${name}\uFF1A${import_node_path79.default.join(config.dataDir, name)}`
70207
+ (name) => ` - ${name}\uFF1A${import_node_path80.default.join(config.dataDir, name)}`
69740
70208
  ).join("\n");
69741
70209
  const prompt = [
69742
70210
  `\u626B\u63CF persona\u300C${personaId2}\u300D\u7684\u90E8\u7F72\u73AF\u5883\uFF0CdeployId=${deployId}\u3002`,
@@ -69788,7 +70256,7 @@ async function startDaemon(config) {
69788
70256
  const cloudHost = await loadCloudHostConfig(config.dataDir);
69789
70257
  await gatewayAdmin({ cloudHost, fetchImpl: fetch }, "/admin/deployments:remove", { deployId });
69790
70258
  },
69791
- genId: () => `dp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
70259
+ genId: () => `dp-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
69792
70260
  now: () => Date.now()
69793
70261
  });
69794
70262
  Object.assign(handlers, deployHandlers);
@@ -69801,7 +70269,7 @@ async function startDaemon(config) {
69801
70269
  });
69802
70270
  shiftScheduler.start();
69803
70271
  logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
69804
- const larkBotStore = createLarkBotBindingStore(import_node_path79.default.join(config.dataDir, "personas"));
70272
+ const larkBotStore = createLarkBotBindingStore(import_node_path80.default.join(config.dataDir, "personas"));
69805
70273
  const larkBotCloud = createLarkBotCloudClient({
69806
70274
  api: config.clawosApi ?? DEFAULT_CLAWOS_API,
69807
70275
  apiKey: resolveClawdTicketsApiKey(),
@@ -69815,7 +70283,7 @@ async function startDaemon(config) {
69815
70283
  store: larkBotStore,
69816
70284
  fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
69817
70285
  // 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
69818
- mediaRootFor: (chatId) => import_node_path79.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
70286
+ mediaRootFor: (chatId) => import_node_path80.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
69819
70287
  isShuttingDown: () => larkDraining,
69820
70288
  logger: {
69821
70289
  warn: (msg) => logger.warn(msg),
@@ -70120,8 +70588,8 @@ async function startDaemon(config) {
70120
70588
  const lines = [
70121
70589
  `Tunnel: ${r.url}`,
70122
70590
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
70123
- `Frpc config: ${import_node_path79.default.join(config.dataDir, "frpc.toml")}`,
70124
- `Frpc log: ${import_node_path79.default.join(logDir, "frpc.log")}`
70591
+ `Frpc config: ${import_node_path80.default.join(config.dataDir, "frpc.toml")}`,
70592
+ `Frpc log: ${import_node_path80.default.join(logDir, "frpc.log")}`
70125
70593
  ];
70126
70594
  const width2 = Math.max(...lines.map((l) => l.length));
70127
70595
  const bar = "\u2550".repeat(width2 + 4);
@@ -70134,7 +70602,7 @@ ${bar}
70134
70602
 
70135
70603
  `);
70136
70604
  try {
70137
- const connectPath = import_node_path79.default.join(config.dataDir, "connect.txt");
70605
+ const connectPath = import_node_path80.default.join(config.dataDir, "connect.txt");
70138
70606
  import_node_fs56.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
70139
70607
  } catch {
70140
70608
  }
@@ -70224,7 +70692,7 @@ ${bar}
70224
70692
  };
70225
70693
  }
70226
70694
  function migrateDropPersonsDir(dataDir) {
70227
- const dir = import_node_path79.default.join(dataDir, "persons");
70695
+ const dir = import_node_path80.default.join(dataDir, "persons");
70228
70696
  try {
70229
70697
  import_node_fs56.default.rmSync(dir, { recursive: true, force: true });
70230
70698
  } catch {