@clawos-dev/clawd 0.2.468 → 0.2.469

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: path99, errorMaps, issueData } = params;
454
- const fullPath = [...path99, ...issueData.path || []];
453
+ const { data, path: path100, errorMaps, issueData } = params;
454
+ const fullPath = [...path100, ...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, path99, key) {
765
+ constructor(parent, value, path100, key) {
766
766
  this._cachedPath = [];
767
767
  this.parent = parent;
768
768
  this.data = value;
769
- this._path = path99;
769
+ this._path = path100;
770
770
  this._key = key;
771
771
  }
772
772
  get path() {
@@ -6077,6 +6077,16 @@ var init_deploy_schemas = __esm({
6077
6077
  evidence: external_exports.array(EnvEvidenceSchema).optional(),
6078
6078
  smokeTask: external_exports.string().optional(),
6079
6079
  notes: external_exports.array(external_exports.string()).default([]),
6080
+ /**
6081
+ * 这次扫描**被告知有哪些共享资产**(daemon 的 `SCANNABLE_ASSETS` 在 finishScan 那一刻的名单)。
6082
+ *
6083
+ * 记它是为了回答一个只有它答得了的问题:「这张单据是不是用还不知道某个资产的扫描器扫的」。
6084
+ * 没有它就只能拿「当前资产表 ⊄ 单据的 assets」当判据——而一个 persona 本来就可能真的用不到
6085
+ * 某个资产,那会变成对每张单据的常态唠叨。
6086
+ *
6087
+ * 缺席 = M1b 及以前扫的老单据(那时候扫描器只被告知了 deploy-kit 一条)。
6088
+ */
6089
+ scannedAssets: external_exports.array(external_exports.string()).optional(),
6080
6090
  /**
6081
6091
  * 每条凭据的履约选择:secret name → 'deployer' | 'user'。
6082
6092
  * **只记「谁出」,不记值。** 没做选择的凭据不在这个 map 里(缺席即未定),
@@ -9905,8 +9915,8 @@ var require_req = __commonJS({
9905
9915
  if (req.originalUrl) {
9906
9916
  _req.url = req.originalUrl;
9907
9917
  } else {
9908
- const path99 = req.path;
9909
- _req.url = typeof path99 === "string" ? path99 : req.url ? req.url.path || req.url : void 0;
9918
+ const path100 = req.path;
9919
+ _req.url = typeof path100 === "string" ? path100 : req.url ? req.url.path || req.url : void 0;
9910
9920
  }
9911
9921
  if (req.query) {
9912
9922
  _req.query = req.query;
@@ -10071,14 +10081,14 @@ var require_redact = __commonJS({
10071
10081
  }
10072
10082
  return obj;
10073
10083
  }
10074
- function parsePath(path99) {
10084
+ function parsePath(path100) {
10075
10085
  const parts = [];
10076
10086
  let current = "";
10077
10087
  let inBrackets = false;
10078
10088
  let inQuotes = false;
10079
10089
  let quoteChar = "";
10080
- for (let i = 0; i < path99.length; i++) {
10081
- const char = path99[i];
10090
+ for (let i = 0; i < path100.length; i++) {
10091
+ const char = path100[i];
10082
10092
  if (!inBrackets && char === ".") {
10083
10093
  if (current) {
10084
10094
  parts.push(current);
@@ -10209,10 +10219,10 @@ var require_redact = __commonJS({
10209
10219
  return current;
10210
10220
  }
10211
10221
  function redactPaths(obj, paths, censor, remove = false) {
10212
- for (const path99 of paths) {
10213
- const parts = parsePath(path99);
10222
+ for (const path100 of paths) {
10223
+ const parts = parsePath(path100);
10214
10224
  if (parts.includes("*")) {
10215
- redactWildcardPath(obj, parts, censor, path99, remove);
10225
+ redactWildcardPath(obj, parts, censor, path100, remove);
10216
10226
  } else {
10217
10227
  if (remove) {
10218
10228
  removeKey(obj, parts);
@@ -10297,8 +10307,8 @@ var require_redact = __commonJS({
10297
10307
  }
10298
10308
  } else {
10299
10309
  if (afterWildcard.includes("*")) {
10300
- const wrappedCensor = typeof censor === "function" ? (value, path99) => {
10301
- const fullPath = [...pathArray.slice(0, pathLength), ...path99];
10310
+ const wrappedCensor = typeof censor === "function" ? (value, path100) => {
10311
+ const fullPath = [...pathArray.slice(0, pathLength), ...path100];
10302
10312
  return censor(value, fullPath);
10303
10313
  } : censor;
10304
10314
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -10333,8 +10343,8 @@ var require_redact = __commonJS({
10333
10343
  return null;
10334
10344
  }
10335
10345
  const pathStructure = /* @__PURE__ */ new Map();
10336
- for (const path99 of pathsToClone) {
10337
- const parts = parsePath(path99);
10346
+ for (const path100 of pathsToClone) {
10347
+ const parts = parsePath(path100);
10338
10348
  let current = pathStructure;
10339
10349
  for (let i = 0; i < parts.length; i++) {
10340
10350
  const part = parts[i];
@@ -10386,24 +10396,24 @@ var require_redact = __commonJS({
10386
10396
  }
10387
10397
  return cloneSelectively(obj, pathStructure);
10388
10398
  }
10389
- function validatePath(path99) {
10390
- if (typeof path99 !== "string") {
10399
+ function validatePath(path100) {
10400
+ if (typeof path100 !== "string") {
10391
10401
  throw new Error("Paths must be (non-empty) strings");
10392
10402
  }
10393
- if (path99 === "") {
10403
+ if (path100 === "") {
10394
10404
  throw new Error("Invalid redaction path ()");
10395
10405
  }
10396
- if (path99.includes("..")) {
10397
- throw new Error(`Invalid redaction path (${path99})`);
10406
+ if (path100.includes("..")) {
10407
+ throw new Error(`Invalid redaction path (${path100})`);
10398
10408
  }
10399
- if (path99.includes(",")) {
10400
- throw new Error(`Invalid redaction path (${path99})`);
10409
+ if (path100.includes(",")) {
10410
+ throw new Error(`Invalid redaction path (${path100})`);
10401
10411
  }
10402
10412
  let bracketCount = 0;
10403
10413
  let inQuotes = false;
10404
10414
  let quoteChar = "";
10405
- for (let i = 0; i < path99.length; i++) {
10406
- const char = path99[i];
10415
+ for (let i = 0; i < path100.length; i++) {
10416
+ const char = path100[i];
10407
10417
  if ((char === '"' || char === "'") && bracketCount > 0) {
10408
10418
  if (!inQuotes) {
10409
10419
  inQuotes = true;
@@ -10417,20 +10427,20 @@ var require_redact = __commonJS({
10417
10427
  } else if (char === "]" && !inQuotes) {
10418
10428
  bracketCount--;
10419
10429
  if (bracketCount < 0) {
10420
- throw new Error(`Invalid redaction path (${path99})`);
10430
+ throw new Error(`Invalid redaction path (${path100})`);
10421
10431
  }
10422
10432
  }
10423
10433
  }
10424
10434
  if (bracketCount !== 0) {
10425
- throw new Error(`Invalid redaction path (${path99})`);
10435
+ throw new Error(`Invalid redaction path (${path100})`);
10426
10436
  }
10427
10437
  }
10428
10438
  function validatePaths(paths) {
10429
10439
  if (!Array.isArray(paths)) {
10430
10440
  throw new TypeError("paths must be an array");
10431
10441
  }
10432
- for (const path99 of paths) {
10433
- validatePath(path99);
10442
+ for (const path100 of paths) {
10443
+ validatePath(path100);
10434
10444
  }
10435
10445
  }
10436
10446
  function slowRedact(options = {}) {
@@ -10598,8 +10608,8 @@ var require_redaction = __commonJS({
10598
10608
  if (shape[k2] === null) {
10599
10609
  o[k2] = (value) => topCensor(value, [k2]);
10600
10610
  } else {
10601
- const wrappedCensor = typeof censor === "function" ? (value, path99) => {
10602
- return censor(value, [k2, ...path99]);
10611
+ const wrappedCensor = typeof censor === "function" ? (value, path100) => {
10612
+ return censor(value, [k2, ...path100]);
10603
10613
  } : censor;
10604
10614
  o[k2] = Redact({
10605
10615
  paths: shape[k2],
@@ -10820,7 +10830,7 @@ var require_sonic_boom = __commonJS({
10820
10830
  var fs88 = require("fs");
10821
10831
  var EventEmitter3 = require("events");
10822
10832
  var inherits = require("util").inherits;
10823
- var path99 = require("path");
10833
+ var path100 = require("path");
10824
10834
  var sleep2 = require_atomic_sleep();
10825
10835
  var assert = require("assert");
10826
10836
  var BUSY_WRITE_TIMEOUT = 100;
@@ -10874,7 +10884,7 @@ var require_sonic_boom = __commonJS({
10874
10884
  const mode = sonic.mode;
10875
10885
  if (sonic.sync) {
10876
10886
  try {
10877
- if (sonic.mkdir) fs88.mkdirSync(path99.dirname(file), { recursive: true });
10887
+ if (sonic.mkdir) fs88.mkdirSync(path100.dirname(file), { recursive: true });
10878
10888
  const fd = fs88.openSync(file, flags, mode);
10879
10889
  fileOpened(null, fd);
10880
10890
  } catch (err) {
@@ -10882,7 +10892,7 @@ var require_sonic_boom = __commonJS({
10882
10892
  throw err;
10883
10893
  }
10884
10894
  } else if (sonic.mkdir) {
10885
- fs88.mkdir(path99.dirname(file), { recursive: true }, (err) => {
10895
+ fs88.mkdir(path100.dirname(file), { recursive: true }, (err) => {
10886
10896
  if (err) return fileOpened(err);
10887
10897
  fs88.open(file, flags, mode, fileOpened);
10888
10898
  });
@@ -14513,11 +14523,11 @@ var init_lib = __esm({
14513
14523
  }
14514
14524
  }
14515
14525
  },
14516
- addToPath: function addToPath(path99, added, removed, oldPosInc, options) {
14517
- var last = path99.lastComponent;
14526
+ addToPath: function addToPath(path100, added, removed, oldPosInc, options) {
14527
+ var last = path100.lastComponent;
14518
14528
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
14519
14529
  return {
14520
- oldPos: path99.oldPos + oldPosInc,
14530
+ oldPos: path100.oldPos + oldPosInc,
14521
14531
  lastComponent: {
14522
14532
  count: last.count + 1,
14523
14533
  added,
@@ -14527,7 +14537,7 @@ var init_lib = __esm({
14527
14537
  };
14528
14538
  } else {
14529
14539
  return {
14530
- oldPos: path99.oldPos + oldPosInc,
14540
+ oldPos: path100.oldPos + oldPosInc,
14531
14541
  lastComponent: {
14532
14542
  count: 1,
14533
14543
  added,
@@ -15109,10 +15119,10 @@ function attachmentToHistoryMessage(o, ts) {
15109
15119
  const memories = raw.map((m2) => {
15110
15120
  if (!m2 || typeof m2 !== "object") return null;
15111
15121
  const rec4 = m2;
15112
- const path99 = typeof rec4.path === "string" ? rec4.path : null;
15122
+ const path100 = typeof rec4.path === "string" ? rec4.path : null;
15113
15123
  const content = typeof rec4.content === "string" ? rec4.content : null;
15114
- if (!path99 || content == null) return null;
15115
- const entry = { path: path99, content };
15124
+ if (!path100 || content == null) return null;
15125
+ const entry = { path: path100, content };
15116
15126
  if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
15117
15127
  return entry;
15118
15128
  }).filter((m2) => m2 !== null);
@@ -15978,10 +15988,10 @@ function parseAttachment(obj) {
15978
15988
  const memories = raw.map((m2) => {
15979
15989
  if (!m2 || typeof m2 !== "object") return null;
15980
15990
  const rec4 = m2;
15981
- const path99 = typeof rec4.path === "string" ? rec4.path : null;
15991
+ const path100 = typeof rec4.path === "string" ? rec4.path : null;
15982
15992
  const content = typeof rec4.content === "string" ? rec4.content : null;
15983
- if (!path99 || content == null) return null;
15984
- const out = { path: path99, content };
15993
+ if (!path100 || content == null) return null;
15994
+ const out = { path: path100, content };
15985
15995
  if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
15986
15996
  return out;
15987
15997
  }).filter((m2) => m2 !== null);
@@ -36955,8 +36965,8 @@ var require_utils = __commonJS({
36955
36965
  var result = transform[inputType][outputType](input);
36956
36966
  return result;
36957
36967
  };
36958
- exports2.resolve = function(path99) {
36959
- var parts = path99.split("/");
36968
+ exports2.resolve = function(path100) {
36969
+ var parts = path100.split("/");
36960
36970
  var result = [];
36961
36971
  for (var index = 0; index < parts.length; index++) {
36962
36972
  var part = parts[index];
@@ -42809,18 +42819,18 @@ var require_object = __commonJS({
42809
42819
  var object = new ZipObject(name, zipObjectContent, o);
42810
42820
  this.files[name] = object;
42811
42821
  };
42812
- var parentFolder = function(path99) {
42813
- if (path99.slice(-1) === "/") {
42814
- path99 = path99.substring(0, path99.length - 1);
42822
+ var parentFolder = function(path100) {
42823
+ if (path100.slice(-1) === "/") {
42824
+ path100 = path100.substring(0, path100.length - 1);
42815
42825
  }
42816
- var lastSlash = path99.lastIndexOf("/");
42817
- return lastSlash > 0 ? path99.substring(0, lastSlash) : "";
42826
+ var lastSlash = path100.lastIndexOf("/");
42827
+ return lastSlash > 0 ? path100.substring(0, lastSlash) : "";
42818
42828
  };
42819
- var forceTrailingSlash = function(path99) {
42820
- if (path99.slice(-1) !== "/") {
42821
- path99 += "/";
42829
+ var forceTrailingSlash = function(path100) {
42830
+ if (path100.slice(-1) !== "/") {
42831
+ path100 += "/";
42822
42832
  }
42823
- return path99;
42833
+ return path100;
42824
42834
  };
42825
42835
  var folderAdd = function(name, createFolders) {
42826
42836
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -43822,7 +43832,7 @@ var require_lib3 = __commonJS({
43822
43832
  // src/run-case/recorder.ts
43823
43833
  function startRunCaseRecorder(opts) {
43824
43834
  const now = opts.now ?? Date.now;
43825
- const dir = import_node_path81.default.dirname(opts.recordPath);
43835
+ const dir = import_node_path82.default.dirname(opts.recordPath);
43826
43836
  let stream = null;
43827
43837
  let closing = false;
43828
43838
  let closedSettled = false;
@@ -43862,12 +43872,12 @@ function startRunCaseRecorder(opts) {
43862
43872
  };
43863
43873
  return { tap, close, closed };
43864
43874
  }
43865
- var import_node_fs57, import_node_path81;
43875
+ var import_node_fs57, import_node_path82;
43866
43876
  var init_recorder = __esm({
43867
43877
  "src/run-case/recorder.ts"() {
43868
43878
  "use strict";
43869
43879
  import_node_fs57 = __toESM(require("fs"), 1);
43870
- import_node_path81 = __toESM(require("path"), 1);
43880
+ import_node_path82 = __toESM(require("path"), 1);
43871
43881
  }
43872
43882
  });
43873
43883
 
@@ -43910,7 +43920,7 @@ var init_wire = __esm({
43910
43920
  // src/run-case/controller.ts
43911
43921
  async function runController(opts) {
43912
43922
  const now = opts.now ?? Date.now;
43913
- const cwd = opts.cwd ?? (0, import_node_fs58.mkdtempSync)(import_node_path82.default.join(import_node_os29.default.tmpdir(), "clawd-runcase-"));
43923
+ const cwd = opts.cwd ?? (0, import_node_fs58.mkdtempSync)(import_node_path83.default.join(import_node_os29.default.tmpdir(), "clawd-runcase-"));
43914
43924
  const ownsCwd = opts.cwd === void 0;
43915
43925
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
43916
43926
  const spawnCtx = { cwd };
@@ -44077,13 +44087,13 @@ async function runController(opts) {
44077
44087
  }
44078
44088
  return exitCode ?? 0;
44079
44089
  }
44080
- var import_node_fs58, import_node_os29, import_node_path82;
44090
+ var import_node_fs58, import_node_os29, import_node_path83;
44081
44091
  var init_controller = __esm({
44082
44092
  "src/run-case/controller.ts"() {
44083
44093
  "use strict";
44084
44094
  import_node_fs58 = require("fs");
44085
44095
  import_node_os29 = __toESM(require("os"), 1);
44086
- import_node_path82 = __toESM(require("path"), 1);
44096
+ import_node_path83 = __toESM(require("path"), 1);
44087
44097
  init_claude();
44088
44098
  init_stdout_splitter();
44089
44099
  init_permission_stdio();
@@ -44358,7 +44368,7 @@ Env (advanced):
44358
44368
  `;
44359
44369
 
44360
44370
  // src/index.ts
44361
- var import_node_path80 = __toESM(require("path"), 1);
44371
+ var import_node_path81 = __toESM(require("path"), 1);
44362
44372
  var import_node_fs56 = __toESM(require("fs"), 1);
44363
44373
  var import_node_os28 = __toESM(require("os"), 1);
44364
44374
  var import_node_crypto23 = require("crypto");
@@ -51616,8 +51626,8 @@ function turnStartInput(text) {
51616
51626
  const items = [];
51617
51627
  let leftover = text;
51618
51628
  for (const m2 of text.matchAll(SKILL_RE)) {
51619
- const [marker, name, path99] = m2;
51620
- items.push({ type: "skill", name, path: path99 });
51629
+ const [marker, name, path100] = m2;
51630
+ items.push({ type: "skill", name, path: path100 });
51621
51631
  leftover = leftover.replace(marker, "");
51622
51632
  }
51623
51633
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -54712,6 +54722,56 @@ function nextReadiness(receipt, filledEnv) {
54712
54722
  return next === receipt.status ? void 0 : next;
54713
54723
  }
54714
54724
 
54725
+ // src/deploy/scan-task.ts
54726
+ var import_node_path30 = __toESM(require("path"), 1);
54727
+ var BUTLER_PERSONA_ID = "persona-clawd-butler";
54728
+ var SCANNABLE_ASSETS = [
54729
+ {
54730
+ name: "deploy-kit",
54731
+ path: (dataDir) => import_node_path30.default.join(dataDir, "deploy-kit"),
54732
+ what: "FC \u90E8\u7F72\u80FD\u529B\uFF08publish.sh / new-extension.sh / \u5DE5\u5177\u94FE / \u51ED\u8BC1\u76EE\u5F55\uFF09\u3002persona \u7528\u7EDD\u5BF9\u8DEF\u5F84\u53BB\u8C03\u8FD9\u91CC\u7684\u811A\u672C\u65F6\uFF0C\u5C31\u8BE5\u62A5\u4E00\u6761 asset\u3002"
54733
+ },
54734
+ {
54735
+ name: "app-builder-plugin",
54736
+ what: "clawd-app-builder MCP server \u7684\u6784\u5EFA\u4EA7\u7269\uFF08daemon \u7684 tsup \u4EA7\u7269\uFF0C\u672C\u673A\u4E0D\u5728\u76D8\u4E0A\u5355\u72EC\u5B58\u4E00\u4EFD\uFF09\u3002**\u5224\u636E**\uFF1Apersona \u7684\u4E3B\u5E72\u52A8\u4F5C\u8D70\u7684\u662F daemon \u63D0\u4F9B\u7684 MCP\uFF08clawd-rpc / app-builder \u90A3\u7C7B\uFF09\u65F6\uFF0C\u4E91\u4E0A\u5BB9\u5668\u91CC\u6CA1\u6709 daemon\uFF0C\u8DD1\u7684\u5C31\u662F\u8FD9\u4EFD\u4EA7\u7269\u2014\u2014\u7528\u5230\u5B83\u5C31\u62A5\u4E00\u6761 asset\uFF0C\u5426\u5219\u5B83\u8FDB\u4E0D\u4E86\u955C\u50CF\u3002"
54737
+ }
54738
+ ];
54739
+ function staleScannerAssets(receipt, known = SCANNABLE_ASSETS) {
54740
+ const knew = new Set(receipt.scannedAssets ?? []);
54741
+ return known.filter((a) => !knew.has(a.name));
54742
+ }
54743
+ var STALE_ASSETS_NOTE_PREFIX = "\u3010\u4E0A\u4E91\u626B\u63CF\u3011";
54744
+ function describeStaleAssets(stale) {
54745
+ if (stale.length === 0) return void 0;
54746
+ const plain = (s) => s.replace(/\*\*/g, "").replace(/\s+/g, " ").trim();
54747
+ return `${STALE_ASSETS_NOTE_PREFIX}\u8FD9\u5F20\u5355\u636E\u626B\u7684\u65F6\u5019\uFF0C\u626B\u63CF\u5668\u8FD8\u4E0D\u77E5\u9053\u6709${stale.map((a) => `\u300C${a.name}\u300D`).join("\u3001")}\u8FD9${stale.length > 1 ? "\u51E0" : ""}\u9879\u5171\u4EAB\u8D44\u4EA7\uFF0C\u6240\u4EE5\u6E05\u5355\u91CC\u53EF\u80FD\u6F0F\u4E86\u58F0\u660E\u3002${stale.map((a) => ` ${a.name} \u662F\uFF1A${plain(a.what)}`).join("")} \u7528\u5F97\u4E0A\u7684\u8BDD\uFF0C\u5728\u6E05\u5355\u91CC\u8865\u4E00\u6761 asset\uFF0C\u6216\u8005\u91CD\u626B\uFF08deploy:rescan\uFF09\u4E00\u904D\u3002`;
54748
+ }
54749
+ function settleEndedScan(outcome, current) {
54750
+ if (current?.status !== "scanning") return void 0;
54751
+ return {
54752
+ status: "scanFailed",
54753
+ error: "error" in outcome ? outcome.error : "butler \u4F1A\u8BDD\u7ED3\u675F\u4E86\u4F46\u6CA1\u6709\u8C03 finishScan"
54754
+ };
54755
+ }
54756
+ function reconcileInterruptedScans(deps) {
54757
+ const stale = deps.list().filter((r) => r.status === "scanning");
54758
+ for (const r of stale) {
54759
+ deps.update(r.deployId, { status: "scanFailed", error: "daemon \u91CD\u542F\uFF0C\u626B\u63CF\u4F1A\u8BDD\u5DF2\u4E2D\u65AD\u2014\u2014\u8BF7\u91CD\u65B0\u626B\u63CF" });
54760
+ }
54761
+ return stale.map((r) => r.deployId);
54762
+ }
54763
+ function reconcileInterruptedTrials(deps) {
54764
+ const stale = deps.list().filter((r) => r.status === "trialing");
54765
+ for (const r of stale) {
54766
+ deps.update(r.deployId, {
54767
+ status: "failed",
54768
+ trialStage: void 0,
54769
+ gaps: [{ errorText: "daemon \u91CD\u542F\uFF0C\u8FD9\u4E00\u8F6E\u8BD5\u88C5\u88AB\u6253\u65AD\u4E86\u2014\u2014\u6CA1\u7ED3\u8BBA\uFF0C\u91CD\u8DD1\u4E00\u6B21\u5373\u53EF\u3002" }]
54770
+ });
54771
+ }
54772
+ return stale.map((r) => r.deployId);
54773
+ }
54774
+
54715
54775
  // src/handlers/deploy.ts
54716
54776
  function ensureOwner(ctx) {
54717
54777
  if (!ctx || ctx.principal.kind !== "owner") {
@@ -54892,6 +54952,9 @@ function buildDeployHandlers(deps) {
54892
54952
  status: "draft",
54893
54953
  smokeTask: args.smokeTask ? redactSecretValues(args.smokeTask) : args.smokeTask,
54894
54954
  notes: args.notes?.map(redactSecretValues),
54955
+ // 记下这次扫描**被告知有哪些共享资产**。以后资产表长出新条目时,只有扫的时候还不知道
54956
+ // 它的那些单据会被提示一次(见 staleScannerAssets)——不记的话就只能对每张单据都唠叨。
54957
+ scannedAssets: SCANNABLE_ASSETS.map((a) => a.name),
54895
54958
  error: void 0
54896
54959
  });
54897
54960
  return view(applyReadiness(deps, next));
@@ -54928,12 +54991,16 @@ function buildDeployHandlers(deps) {
54928
54991
  `VALIDATION_ERROR: \u5DF2\u7ECF\u8BD5\u88C5 ${receipt.trialRound} \u8F6E\u4E86\uFF08\u4E0A\u9650 ${TRIAL_ROUND_MAX}\uFF09\u3002\u4E00\u8F6E\u662F\u4E00\u6B21\u771F\u7684\u955C\u50CF\u6784\u5EFA\u52A0\u4E00\u6B21\u771F\u7684\u53D1\u5E03\uFF0C\u5230\u8FD9\u4E2A\u6570\u8BF4\u660E\u7F3A\u7684\u591A\u534A\u4E0D\u662F\u4E00\u6761\u4F9D\u8D56\u2014\u2014\u56DE\u53BB\u91CD\u626B\u4E00\u904D\uFF0C\u6216\u8005\u627E\u4EBA\u770B\u770B\u8FD9\u6761\u8DEF\u662F\u4E0D\u662F\u8D70\u4E0D\u901A`
54929
54992
  );
54930
54993
  }
54994
+ const stale = describeStaleAssets(staleScannerAssets(receipt));
54995
+ const kept = receipt.notes.filter((n) => !n.startsWith(STALE_ASSETS_NOTE_PREFIX));
54996
+ const notes = stale ? [...kept, stale] : kept.length === receipt.notes.length ? void 0 : kept;
54931
54997
  const next = deps.receipts.update(args.deployId, {
54932
54998
  status: "trialing",
54933
54999
  trialRound: receipt.trialRound + 1,
54934
55000
  trialStage: "\u6392\u961F\u51C6\u5907\u4E2D",
54935
55001
  // 上一轮的缺口不留到这一轮:人已经照着补过了,留着会让人以为没改动
54936
55002
  gaps: [],
55003
+ ...notes ? { notes } : {},
54937
55004
  error: void 0
54938
55005
  });
54939
55006
  deps.startTrial(args.deployId);
@@ -54986,7 +55053,7 @@ function buildDeployHandlers(deps) {
54986
55053
 
54987
55054
  // src/deploy/receipt-store.ts
54988
55055
  var import_promises4 = __toESM(require("fs/promises"), 1);
54989
- var import_node_path30 = __toESM(require("path"), 1);
55056
+ var import_node_path31 = __toESM(require("path"), 1);
54990
55057
  init_protocol();
54991
55058
  function createReceiptStore(deps) {
54992
55059
  let receipts = [];
@@ -55012,7 +55079,7 @@ function createReceiptStore(deps) {
55012
55079
  flushTimer = null;
55013
55080
  }
55014
55081
  const content = { version: 1, receipts };
55015
- await import_promises4.default.mkdir(import_node_path30.default.dirname(deps.filePath), { recursive: true });
55082
+ await import_promises4.default.mkdir(import_node_path31.default.dirname(deps.filePath), { recursive: true });
55016
55083
  const tmp = `${deps.filePath}.tmp-${process.pid}-${deps.now()}`;
55017
55084
  await import_promises4.default.writeFile(tmp, JSON.stringify(content, null, 2), { encoding: "utf8", mode: 384 });
55018
55085
  await import_promises4.default.rename(tmp, deps.filePath);
@@ -55070,7 +55137,7 @@ function createReceiptStore(deps) {
55070
55137
 
55071
55138
  // src/deploy/secret-store.ts
55072
55139
  var import_promises5 = __toESM(require("fs/promises"), 1);
55073
- var import_node_path31 = __toESM(require("path"), 1);
55140
+ var import_node_path32 = __toESM(require("path"), 1);
55074
55141
  function createSecretStore(deps) {
55075
55142
  let entries = [];
55076
55143
  let flushTimer = null;
@@ -55096,7 +55163,7 @@ function createSecretStore(deps) {
55096
55163
  flushTimer = null;
55097
55164
  }
55098
55165
  const content = { version: 1, entries };
55099
- await import_promises5.default.mkdir(import_node_path31.default.dirname(deps.filePath), { recursive: true });
55166
+ await import_promises5.default.mkdir(import_node_path32.default.dirname(deps.filePath), { recursive: true });
55100
55167
  const tmp = `${deps.filePath}.tmp-${process.pid}-${deps.now()}`;
55101
55168
  await import_promises5.default.writeFile(tmp, JSON.stringify(content, null, 2), { encoding: "utf8", mode: 384 });
55102
55169
  await import_promises5.default.rename(tmp, deps.filePath);
@@ -55167,9 +55234,10 @@ function createSecretStore(deps) {
55167
55234
 
55168
55235
  // src/deploy/cloud-host-config.ts
55169
55236
  var import_promises6 = __toESM(require("fs/promises"), 1);
55170
- var import_node_path32 = __toESM(require("path"), 1);
55237
+ var import_node_path33 = __toESM(require("path"), 1);
55171
55238
  var CLOUD_HOST_CONFIG_FILE = "cloud-host.json";
55172
- var REQUIRED = ["provisionDir", "gatewayUrl", "gatewayAdminKey", "gatewayApiKey"];
55239
+ var REQUIRED = ["gatewayUrl", "gatewayAdminKey", "gatewayApiKey"];
55240
+ var LOCAL_REQUIRED = ["provisionDir", "k3sHost", "k3sKeyPath"];
55173
55241
  var CloudHostConfigError = class extends Error {
55174
55242
  };
55175
55243
  var looksLikeRegistryRef = (s) => {
@@ -55251,7 +55319,7 @@ function formatGaps(file, gaps, hasLocalCoords) {
55251
55319
  return lines.join("\n");
55252
55320
  }
55253
55321
  async function loadCloudHostConfig(dataDir) {
55254
- const file = import_node_path32.default.join(dataDir, CLOUD_HOST_CONFIG_FILE);
55322
+ const file = import_node_path33.default.join(dataDir, CLOUD_HOST_CONFIG_FILE);
55255
55323
  let raw;
55256
55324
  try {
55257
55325
  raw = await import_promises6.default.readFile(file, "utf8");
@@ -55276,9 +55344,11 @@ async function loadCloudHostConfig(dataDir) {
55276
55344
  const buildHost = parsed.buildHost === "local" ? "local" : "gha";
55277
55345
  const imageRepo = parsed.imageRepo ?? "clawd-persona-cloud";
55278
55346
  if (buildHost === "local") {
55279
- const need = ["k3sHost", "k3sKeyPath"].filter((k2) => !parsed[k2]);
55347
+ const need = LOCAL_REQUIRED.filter((k2) => !parsed[k2]);
55280
55348
  if (need.length > 0) {
55281
- throw new CloudHostConfigError(`${file} \u7684 buildHost \u662F local\uFF0C\u8FD8\u7F3A\uFF1A${need.join(" / ")}`);
55349
+ throw new CloudHostConfigError(
55350
+ `${file} \u7684 buildHost \u662F local\uFF0C\u8FD8\u7F3A\uFF1A${need.join(" / ")}\u3002` + (need.includes("provisionDir") ? '\uFF08provisionDir \u662F clawos checkout \u91CC\u7684 cloud-host/provision \u7EDD\u5BF9\u8DEF\u5F84\u2014\u2014local \u8FD9\u6761\u8DEF\u8981\u5728\u672C\u673A\u8DD1\u6784\u5EFA\u5668\u3001\u8FD8\u8981\u4ECE\u4ED3\u5E93\u53D6\u968F\u884C\u8D44\u4EA7\uFF0C\u6240\u4EE5\u5B83\u5FC5\u987B\u6307\u5411\u4E00\u4EFD checkout\u3002\u4E0D\u60F3\u8981\u8FD9\u4E2A\u524D\u63D0\u7684\u8BDD\uFF0C\u6539\u6210\u9ED8\u8BA4\u7684 "buildHost": "gha"\uFF0C\u90A3\u6761\u8DEF\u4E0D\u78B0\u4ED3\u5E93\u3002\uFF09' : "")
55351
+ );
55282
55352
  }
55283
55353
  } else {
55284
55354
  const gaps = ghaGaps(parsed, imageRepo);
@@ -55289,7 +55359,7 @@ async function loadCloudHostConfig(dataDir) {
55289
55359
  }
55290
55360
  }
55291
55361
  return {
55292
- provisionDir: parsed.provisionDir,
55362
+ ...parsed.provisionDir ? { provisionDir: parsed.provisionDir } : {},
55293
55363
  gatewayUrl: parsed.gatewayUrl.replace(/\/+$/, ""),
55294
55364
  gatewayAdminKey: parsed.gatewayAdminKey,
55295
55365
  gatewayApiKey: parsed.gatewayApiKey,
@@ -55322,34 +55392,34 @@ async function loadCloudHostConfig(dataDir) {
55322
55392
  // src/deploy/trial-runner.ts
55323
55393
  var import_promises8 = __toESM(require("fs/promises"), 1);
55324
55394
  var import_node_os9 = __toESM(require("os"), 1);
55325
- var import_node_path34 = __toESM(require("path"), 1);
55395
+ var import_node_path35 = __toESM(require("path"), 1);
55326
55396
 
55327
55397
  // src/deploy/bundle-store.ts
55328
55398
  var import_node_crypto7 = __toESM(require("crypto"), 1);
55329
55399
  var import_promises7 = __toESM(require("fs/promises"), 1);
55330
55400
  var import_node_os8 = __toESM(require("os"), 1);
55331
- var import_node_path33 = __toESM(require("path"), 1);
55401
+ var import_node_path34 = __toESM(require("path"), 1);
55332
55402
  var import_node_child_process8 = require("child_process");
55333
55403
  var BUNDLE_URL_TTL_SEC = 30 * 60;
55334
55404
  var RUNTIME_STATE = /* @__PURE__ */ new Set(["projects", ".attachments", ".clawd/sessions"]);
55335
55405
  var NEVER_PERSONA = /* @__PURE__ */ new Set(["node_modules", ".git"]);
55336
55406
  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"), {
55407
+ const stage = await import_promises7.default.mkdtemp(import_node_path34.default.join(import_node_os8.default.tmpdir(), "clawd-bundle-"));
55408
+ const root = import_node_path34.default.resolve(personaDir);
55409
+ await import_promises7.default.cp(root, import_node_path34.default.join(stage, "persona"), {
55340
55410
  recursive: true,
55341
55411
  dereference: true,
55342
55412
  filter: (src) => {
55343
- const rel = import_node_path33.default.relative(root, import_node_path33.default.resolve(src));
55413
+ const rel = import_node_path34.default.relative(root, import_node_path34.default.resolve(src));
55344
55414
  if (!rel) return true;
55345
- return !RUNTIME_STATE.has(rel) && !NEVER_PERSONA.has(import_node_path33.default.basename(rel));
55415
+ return !RUNTIME_STATE.has(rel) && !NEVER_PERSONA.has(import_node_path34.default.basename(rel));
55346
55416
  }
55347
55417
  });
55348
55418
  return { dir: stage, cleanup: () => import_promises7.default.rm(stage, { recursive: true, force: true }) };
55349
55419
  }
55350
55420
  async function packPersonaBundle(personaDir) {
55351
55421
  const { dir: stage, cleanup } = await stagePersonaDir(personaDir);
55352
- const file = import_node_path33.default.join(stage, "bundle.tgz");
55422
+ const file = import_node_path34.default.join(stage, "bundle.tgz");
55353
55423
  await new Promise((resolve9, reject) => {
55354
55424
  const child = (0, import_node_child_process8.spawn)("tar", ["-czf", file, "-C", stage, "persona"], { stdio: ["ignore", "ignore", "pipe"] });
55355
55425
  let err = "";
@@ -55614,12 +55684,24 @@ var gap = (errorText, raw, suggest) => ({
55614
55684
  ...raw ? { raw: redactSecretValues(raw.slice(-RAW_TAIL_CHARS)) } : {},
55615
55685
  ...suggest ? { suggest } : {}
55616
55686
  });
55687
+ var CLI_NAME = /^(@[a-z0-9][a-z0-9._+-]*\/)?[a-z0-9][a-z0-9._+-]*$/i;
55688
+ var CLI_NAME_MAX = 40;
55689
+ var stripCliPrefix = (s) => s.replace(/^cli:/i, "");
55617
55690
  function missingFromAgentText(text) {
55691
+ const empty = { clis: [], notes: [] };
55618
55692
  const idx = text.lastIndexOf(MISSING_MARKER);
55619
- if (idx === -1) return [];
55693
+ if (idx === -1) return empty;
55620
55694
  const line = text.slice(idx + MISSING_MARKER.length).split("\n")[0].trim();
55621
- if (!line || /^(none|无|没有)[.。]?$/i.test(line)) return [];
55622
- return line.replace(/[`*]/g, "").split(/[,,、]/).map((s) => s.trim()).filter((s) => s.length > 0 && s.length <= 40 && !/[\s((]/.test(s));
55695
+ if (!line || /^(none|无|没有)[.。]?$/i.test(line)) return empty;
55696
+ const out = { clis: [], notes: [] };
55697
+ for (const raw of line.replace(/[`*]/g, "").split(/[,,、]/)) {
55698
+ const item = raw.trim();
55699
+ if (!item) continue;
55700
+ const name = stripCliPrefix(item);
55701
+ if (name.length <= CLI_NAME_MAX && CLI_NAME.test(name)) out.clis.push(name);
55702
+ else out.notes.push(item);
55703
+ }
55704
+ return out;
55623
55705
  }
55624
55706
  function gapsFromBuildOutput(r) {
55625
55707
  try {
@@ -55641,6 +55723,8 @@ async function chat(deps, args) {
55641
55723
  const timer = setTimeout(() => ctl.abort(), args.timeoutMs);
55642
55724
  const notes = [];
55643
55725
  let text = "";
55726
+ let meta;
55727
+ let delivered = false;
55644
55728
  try {
55645
55729
  const res = await deps.fetchImpl(`${cloudHost.gatewayUrl}/v1/chat/completions`, {
55646
55730
  method: "POST",
@@ -55658,8 +55742,14 @@ async function chat(deps, args) {
55658
55742
  });
55659
55743
  if (!res.ok) {
55660
55744
  const body = await res.text().catch(() => "");
55661
- return { ok: false, text: `gateway \u62D2\u4E86\u8FD9\u6B21\u6295\u5582\uFF08HTTP ${res.status}\uFF09\uFF1A${body.slice(0, 500)}`, notes };
55745
+ return {
55746
+ ok: false,
55747
+ notes,
55748
+ text: `gateway \u62D2\u4E86\u8FD9\u6B21\u6295\u5582\uFF08HTTP ${res.status}\uFF09\uFF1A${body.slice(0, 500)}`,
55749
+ infra: { stage: "schedule", reason: `HTTP ${res.status}` }
55750
+ };
55662
55751
  }
55752
+ delivered = true;
55663
55753
  for await (const line of sseLines(res)) {
55664
55754
  if (line.startsWith(":")) {
55665
55755
  const note = line.slice(1).trim();
@@ -55675,6 +55765,7 @@ async function chat(deps, args) {
55675
55765
  try {
55676
55766
  const frame = JSON.parse(payload);
55677
55767
  text += frame.choices?.[0]?.delta?.content ?? "";
55768
+ if (frame.clawd) meta = frame.clawd;
55678
55769
  } catch {
55679
55770
  }
55680
55771
  }
@@ -55683,13 +55774,22 @@ async function chat(deps, args) {
55683
55774
  return {
55684
55775
  ok: false,
55685
55776
  notes,
55686
- text: aborted ? `\u7B49\u4E86 ${Math.round(args.timeoutMs / 6e4)} \u5206\u949F\uFF0C\u5BB9\u5668\u90A3\u8FB9\u8FD8\u6CA1\u8DD1\u5B8C` : `\u8DDF gateway \u8BF4\u4E0D\u4E0A\u8BDD\uFF1A${String(err)}`
55777
+ text: aborted ? `\u7B49\u4E86 ${Math.round(args.timeoutMs / 6e4)} \u5206\u949F\uFF0C\u5BB9\u5668\u90A3\u8FB9\u8FD8\u6CA1\u8DD1\u5B8C` : `\u8DDF gateway \u8BF4\u4E0D\u4E0A\u8BDD\uFF1A${String(err)}`,
55778
+ // 连响应都没拿到 = 这次投喂没落地;**流中途才断**的另说:任务还在云上跑,
55779
+ // 判不出是清单的错还是网络的错,从严算数
55780
+ ...delivered ? {} : { infra: { stage: "schedule", reason: String(err) } }
55687
55781
  };
55688
55782
  } finally {
55689
55783
  clearTimeout(timer);
55690
55784
  }
55691
- const failed = /\[gateway\]/.test(text);
55692
- return { ok: !failed, text, notes };
55785
+ if (!meta?.outcome) {
55786
+ deps.logger?.warn("deploy.trial.no-final-frame", {
55787
+ note: "gateway \u6CA1\u7ED9\u672B\u5E27\u7684 clawd.outcome\uFF0C\u56DE\u843D\u5230\u6B63\u6587\u5224\u5B9A\uFF08\u8001 gateway\uFF0C\u6216\u8005\u8FD9\u6761\u6D41\u88AB\u622A\u65AD\u4E86\uFF09"
55788
+ });
55789
+ }
55790
+ const failed = meta?.outcome ? meta.outcome.kind !== "success" : /\[gateway\]/.test(text);
55791
+ const infra = meta?.outcome?.infra;
55792
+ return { ok: !failed, text, notes, ...failed && infra ? { infra } : {} };
55693
55793
  }
55694
55794
  async function* sseLines(res) {
55695
55795
  const reader = res.body?.getReader();
@@ -55709,8 +55809,8 @@ async function* sseLines(res) {
55709
55809
  }
55710
55810
  if (buf.trim()) yield buf.trim();
55711
55811
  }
55712
- async function gatewayAdmin(deps, path99, body) {
55713
- const res = await deps.fetchImpl(`${deps.cloudHost.gatewayUrl}${path99}`, {
55812
+ async function gatewayAdmin(deps, path100, body) {
55813
+ const res = await deps.fetchImpl(`${deps.cloudHost.gatewayUrl}${path100}`, {
55714
55814
  method: "POST",
55715
55815
  headers: {
55716
55816
  "content-type": "application/json",
@@ -55723,11 +55823,11 @@ async function gatewayAdmin(deps, path99, body) {
55723
55823
  signal: AbortSignal.timeout(GATEWAY_ADMIN_TIMEOUT_MS)
55724
55824
  });
55725
55825
  const text = await res.text();
55726
- if (!res.ok) throw new Error(`gateway ${path99} \u56DE\u4E86 HTTP ${res.status}\uFF1A${text.slice(0, 300)}`);
55826
+ if (!res.ok) throw new Error(`gateway ${path100} \u56DE\u4E86 HTTP ${res.status}\uFF1A${text.slice(0, 300)}`);
55727
55827
  try {
55728
55828
  return JSON.parse(text);
55729
55829
  } catch {
55730
- throw new Error(`gateway ${path99} \u56DE\u7684\u4E0D\u662F JSON\uFF1A${text.slice(0, 300)}`);
55830
+ throw new Error(`gateway ${path100} \u56DE\u7684\u4E0D\u662F JSON\uFF1A${text.slice(0, 300)}`);
55731
55831
  }
55732
55832
  }
55733
55833
  async function registerOfficialDeployment(deps, receipt, deployerSecrets) {
@@ -55826,28 +55926,37 @@ async function buildViaGha(deps, args) {
55826
55926
  }
55827
55927
  async function buildLocally(deps, args) {
55828
55928
  const { cloudHost } = deps;
55929
+ const needed = [
55930
+ ["provisionDir", cloudHost.provisionDir],
55931
+ ["k3sHost", cloudHost.k3sHost],
55932
+ ["k3sKeyPath", cloudHost.k3sKeyPath]
55933
+ ].filter(([, v2]) => !v2).map(([k2]) => k2);
55934
+ if (needed.length > 0) {
55935
+ return { ok: false, gaps: [gap(`cloud-host.json \u7684 buildHost \u662F local\uFF0C\u4F46\u7F3A ${needed.join(" / ")}\u3002`)] };
55936
+ }
55937
+ const provisionDir = cloudHost.provisionDir;
55829
55938
  const baseTag = `${cloudHost.imageRepo}:base-local`;
55830
55939
  const deadline = deps.now() + args.timeoutMs;
55831
55940
  const left = () => Math.max(3e4, deadline - deps.now());
55832
55941
  deps.onStage("\u5728\u672C\u673A\u6784\u5E95\u5EA7");
55833
55942
  const base = await deps.runNode(
55834
- `${cloudHost.provisionDir}/build-image.mjs`,
55943
+ `${provisionDir}/build-image.mjs`,
55835
55944
  [
55836
55945
  "--base",
55837
55946
  "--manifest",
55838
- `${cloudHost.provisionDir}/manifests/base.json`,
55947
+ `${provisionDir}/manifests/base.json`,
55839
55948
  "--tag",
55840
55949
  baseTag,
55841
55950
  "--platform",
55842
55951
  "linux/amd64",
55843
55952
  "--context",
55844
- `${cloudHost.provisionDir}/build-context-base`
55953
+ `${provisionDir}/build-context-base`
55845
55954
  ],
55846
55955
  { timeoutMs: left() }
55847
55956
  );
55848
55957
  if (base.code !== 0) return { ok: false, gaps: gapsFromBuildOutput(base) };
55849
55958
  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`);
55959
+ const manifestFile = import_node_path35.default.join(import_node_os9.default.tmpdir(), `clawd-trial-${args.tmpKey}.json`);
55851
55960
  let built;
55852
55961
  let staged;
55853
55962
  try {
@@ -55858,14 +55967,14 @@ async function buildLocally(deps, args) {
55858
55967
  try {
55859
55968
  await import_promises8.default.writeFile(manifestFile, JSON.stringify({ manifest: args.manifest }, null, 2), { mode: 384 });
55860
55969
  built = await deps.runNode(
55861
- `${cloudHost.provisionDir}/build-image.mjs`,
55970
+ `${provisionDir}/build-image.mjs`,
55862
55971
  [
55863
55972
  "--manifest",
55864
55973
  manifestFile,
55865
55974
  "--from",
55866
55975
  baseTag,
55867
55976
  "--persona-dir",
55868
- import_node_path34.default.join(staged.dir, "persona"),
55977
+ import_node_path35.default.join(staged.dir, "persona"),
55869
55978
  "--tag",
55870
55979
  args.image,
55871
55980
  "--platform",
@@ -55882,11 +55991,8 @@ async function buildLocally(deps, args) {
55882
55991
  }
55883
55992
  if (built.code !== 0) return { ok: false, gaps: gapsFromBuildOutput(built) };
55884
55993
  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
- }
55888
55994
  const pushed = await deps.runNode(
55889
- `${cloudHost.provisionDir}/push-to-k3s.mjs`,
55995
+ `${provisionDir}/push-to-k3s.mjs`,
55890
55996
  ["--host", cloudHost.k3sHost, "--key", cloudHost.k3sKeyPath, "--image", args.image],
55891
55997
  { timeoutMs: left() }
55892
55998
  );
@@ -55906,6 +56012,12 @@ async function runTrial(deps, args) {
55906
56012
  const appName = trialAppName(receipt.deployId);
55907
56013
  const deadline = deps.now() + cloudHost.trialTimeoutMs;
55908
56014
  const left = () => Math.max(3e4, deadline - deps.now());
56015
+ if (cloudHost.buildHost !== "local" && cloudHost.provisionDir) {
56016
+ deps.logger?.info("deploy.trial.provision-dir-unused", {
56017
+ provisionDir: cloudHost.provisionDir,
56018
+ note: "buildHost=gha \u4E0D\u8BFB provisionDir\uFF08\u6784\u5EFA\u6574\u4E2A\u53D1\u751F\u5728 GitHub runner \u4E0A\uFF09\uFF0C\u8FD9\u4E00\u884C\u53EF\u4EE5\u4ECE cloud-host.json \u5220\u6389"
56019
+ });
56020
+ }
55909
56021
  const buildOutcome = cloudHost.buildHost === "local" ? await buildLocally(deps, {
55910
56022
  manifest,
55911
56023
  personaDir: args.personaDir,
@@ -55942,10 +56054,15 @@ async function runTrial(deps, args) {
55942
56054
  prompt: buildTeardownPrompt(appName),
55943
56055
  timeoutMs: Math.min(left(), 15 * 6e4)
55944
56056
  });
56057
+ const infra = smoke.infra ?? (smoke.ok ? teardown.infra : void 0);
56058
+ if (infra) {
56059
+ deps.logger?.warn("deploy.trial.infra-failure", { deployId: receipt.deployId, round, stage: infra.stage });
56060
+ }
56061
+ const spent = !infra;
55945
56062
  if (!smoke.ok) {
55946
56063
  return {
55947
56064
  ok: false,
55948
- spent: true,
56065
+ spent,
55949
56066
  gaps: [
55950
56067
  gap(smoke.text.trim() || "\u5BB9\u5668\u91CC\u90A3\u4E2A persona \u6CA1\u8BF4\u6E05\u695A\u4E3A\u4EC0\u4E48\u6CA1\u8DD1\u5B8C", smoke.notes.slice(-20).join("\n")),
55951
56068
  ...teardown.ok ? [] : [gap(`\u987A\u5E26\uFF1A\u8BD5\u88C5\u4EA7\u7269\u6CA1\u62C6\u5E72\u51C0\u2014\u2014${teardown.text.trim()}`)]
@@ -55953,14 +56070,21 @@ async function runTrial(deps, args) {
55953
56070
  };
55954
56071
  }
55955
56072
  if (!teardown.ok) {
55956
- return { ok: false, spent: true, gaps: [gap(`\u5E94\u7528\u5EFA\u51FA\u6765\u5E76\u53D1\u5E03\u6210\u529F\u4E86\uFF0C\u4F46\u62C6\u4E0D\u5E72\u51C0\uFF1A${teardown.text.trim()}`, teardown.notes.slice(-20).join("\n"))] };
56073
+ return { ok: false, spent, gaps: [gap(`\u5E94\u7528\u5EFA\u51FA\u6765\u5E76\u53D1\u5E03\u6210\u529F\u4E86\uFF0C\u4F46\u62C6\u4E0D\u5E72\u51C0\uFF1A${teardown.text.trim()}`, teardown.notes.slice(-20).join("\n"))] };
55957
56074
  }
55958
56075
  const missing = missingFromAgentText(smoke.text);
55959
- if (missing.length > 0) {
56076
+ if (missing.notes.length > 0) {
56077
+ deps.logger?.warn("deploy.trial.missing-not-a-dependency", {
56078
+ deployId: receipt.deployId,
56079
+ round,
56080
+ items: missing.notes
56081
+ });
56082
+ }
56083
+ if (missing.clis.length > 0) {
55960
56084
  return {
55961
56085
  ok: false,
55962
56086
  spent: true,
55963
- gaps: missing.map((name) => gap(
56087
+ gaps: missing.clis.map((name) => gap(
55964
56088
  `\u5BB9\u5668\u91CC\u6CA1\u6709 \`${name}\`\uFF0C\u662F\u5B83\u81EA\u5DF1\u52A8\u624B\u8865\u4E0A\u624D\u8DD1\u4E0B\u53BB\u7684\u2014\u2014\u6E05\u5355\u91CC\u6F0F\u4E86\u8FD9\u6761\uFF0C\u4E0B\u4E00\u4E2A\u5BB9\u5668\u7167\u6837\u7F3A\u3002`,
55965
56089
  smoke.text.slice(-RAW_TAIL_CHARS),
55966
56090
  `cli:${name}`
@@ -56008,35 +56132,6 @@ async function runNodeScript(script, args, timeoutMs) {
56008
56132
  });
56009
56133
  }
56010
56134
 
56011
- // src/deploy/scan-task.ts
56012
- var BUTLER_PERSONA_ID = "persona-clawd-butler";
56013
- var SCANNABLE_ASSETS = ["deploy-kit"];
56014
- function settleEndedScan(outcome, current) {
56015
- if (current?.status !== "scanning") return void 0;
56016
- return {
56017
- status: "scanFailed",
56018
- error: "error" in outcome ? outcome.error : "butler \u4F1A\u8BDD\u7ED3\u675F\u4E86\u4F46\u6CA1\u6709\u8C03 finishScan"
56019
- };
56020
- }
56021
- function reconcileInterruptedScans(deps) {
56022
- const stale = deps.list().filter((r) => r.status === "scanning");
56023
- for (const r of stale) {
56024
- deps.update(r.deployId, { status: "scanFailed", error: "daemon \u91CD\u542F\uFF0C\u626B\u63CF\u4F1A\u8BDD\u5DF2\u4E2D\u65AD\u2014\u2014\u8BF7\u91CD\u65B0\u626B\u63CF" });
56025
- }
56026
- return stale.map((r) => r.deployId);
56027
- }
56028
- function reconcileInterruptedTrials(deps) {
56029
- const stale = deps.list().filter((r) => r.status === "trialing");
56030
- for (const r of stale) {
56031
- deps.update(r.deployId, {
56032
- status: "failed",
56033
- trialStage: void 0,
56034
- gaps: [{ errorText: "daemon \u91CD\u542F\uFF0C\u8FD9\u4E00\u8F6E\u8BD5\u88C5\u88AB\u6253\u65AD\u4E86\u2014\u2014\u6CA1\u7ED3\u8BBA\uFF0C\u91CD\u8DD1\u4E00\u6B21\u5373\u53EF\u3002" }]
56035
- });
56036
- }
56037
- return stale.map((r) => r.deployId);
56038
- }
56039
-
56040
56135
  // src/handlers/lark-bot.ts
56041
56136
  init_protocol();
56042
56137
  var PROVISION_ERROR_SET = new Set(LARK_BOT_PROVISION_ERROR_REASONS);
@@ -56425,9 +56520,9 @@ async function refreshTunnelUrlOnStartup(deps) {
56425
56520
 
56426
56521
  // src/lark-bot-connector/binding-store.ts
56427
56522
  var import_node_fs28 = __toESM(require("fs"), 1);
56428
- var import_node_path35 = __toESM(require("path"), 1);
56523
+ var import_node_path36 = __toESM(require("path"), 1);
56429
56524
  function createLarkBotBindingStore(personaRoot) {
56430
- const filePath = (personaId2) => import_node_path35.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
56525
+ const filePath = (personaId2) => import_node_path36.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
56431
56526
  const read = (personaId2) => {
56432
56527
  const file = filePath(personaId2);
56433
56528
  if (!import_node_fs28.default.existsSync(file)) return null;
@@ -56441,7 +56536,7 @@ function createLarkBotBindingStore(personaRoot) {
56441
56536
  };
56442
56537
  const write = (personaId2, meta) => {
56443
56538
  const file = filePath(personaId2);
56444
- import_node_fs28.default.mkdirSync(import_node_path35.default.dirname(file), { recursive: true });
56539
+ import_node_fs28.default.mkdirSync(import_node_path36.default.dirname(file), { recursive: true });
56445
56540
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
56446
56541
  import_node_fs28.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
56447
56542
  import_node_fs28.default.renameSync(tmp, file);
@@ -56609,7 +56704,7 @@ function createLarkBotCloudClient(opts) {
56609
56704
 
56610
56705
  // src/lark-bot-connector/chat-router.ts
56611
56706
  var import_node_fs29 = __toESM(require("fs"), 1);
56612
- var import_node_path36 = __toESM(require("path"), 1);
56707
+ var import_node_path37 = __toESM(require("path"), 1);
56613
56708
  init_protocol();
56614
56709
  var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
56615
56710
  var LOCAL_TURN_RETRIES = 2;
@@ -56676,7 +56771,7 @@ function createLarkChatRouter(deps) {
56676
56771
  }
56677
56772
  const dir = deps.mediaRootFor(env.chatId);
56678
56773
  import_node_fs29.default.mkdirSync(dir, { recursive: true });
56679
- const p2 = import_node_path36.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
56774
+ const p2 = import_node_path37.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
56680
56775
  import_node_fs29.default.writeFileSync(p2, r.data);
56681
56776
  lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56682
56777
  } catch (err) {
@@ -56699,7 +56794,7 @@ function createLarkChatRouter(deps) {
56699
56794
  }
56700
56795
  const dir = deps.mediaRootFor(env.chatId);
56701
56796
  import_node_fs29.default.mkdirSync(dir, { recursive: true });
56702
- const p2 = import_node_path36.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
56797
+ const p2 = import_node_path37.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
56703
56798
  import_node_fs29.default.writeFileSync(p2, r.data);
56704
56799
  lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56705
56800
  } catch (err) {
@@ -57789,7 +57884,7 @@ var CodexHistoryReader = class {
57789
57884
  };
57790
57885
 
57791
57886
  // src/tools/codex-skills.ts
57792
- var import_node_path37 = __toESM(require("path"), 1);
57887
+ var import_node_path38 = __toESM(require("path"), 1);
57793
57888
  function str3(v2) {
57794
57889
  return typeof v2 === "string" ? v2 : void 0;
57795
57890
  }
@@ -57804,13 +57899,13 @@ function mapSkillsListResponse(res) {
57804
57899
  const r = s ?? {};
57805
57900
  const name = str3(r.name);
57806
57901
  if (!name) continue;
57807
- const path99 = str3(r.path);
57902
+ const path100 = str3(r.path);
57808
57903
  const description = str3(r.description);
57809
57904
  const isPlugin = name.includes(":");
57810
57905
  out.push({
57811
57906
  name,
57812
57907
  source: isPlugin ? "plugin" : "project",
57813
- ...path99 ? { path: path99 } : {},
57908
+ ...path100 ? { path: path100 } : {},
57814
57909
  ...description ? { description } : {},
57815
57910
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
57816
57911
  });
@@ -57826,7 +57921,7 @@ async function listCodexSkills(cwd, deps = {}) {
57826
57921
  // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
57827
57922
  // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
57828
57923
  beforeRequest: (client) => {
57829
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path37.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
57924
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path38.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
57830
57925
  }
57831
57926
  });
57832
57927
  return mapSkillsListResponse(res);
@@ -57913,14 +58008,14 @@ function str4(v2) {
57913
58008
  // src/workspace/browser.ts
57914
58009
  var import_node_fs30 = __toESM(require("fs"), 1);
57915
58010
  var import_node_os10 = __toESM(require("os"), 1);
57916
- var import_node_path38 = __toESM(require("path"), 1);
58011
+ var import_node_path39 = __toESM(require("path"), 1);
57917
58012
  init_protocol();
57918
58013
  var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
57919
58014
  function resolveInsideCwd(cwd, subpath) {
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)) {
58015
+ const absCwd = import_node_path39.default.resolve(cwd);
58016
+ const joined = import_node_path39.default.resolve(absCwd, subpath ?? ".");
58017
+ const rel = import_node_path39.default.relative(absCwd, joined);
58018
+ if (rel.startsWith("..") || import_node_path39.default.isAbsolute(rel)) {
57924
58019
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
57925
58020
  }
57926
58021
  return joined;
@@ -57951,7 +58046,7 @@ var WorkspaceBrowser = class {
57951
58046
  mtime: ""
57952
58047
  };
57953
58048
  try {
57954
- const st = import_node_fs30.default.statSync(import_node_path38.default.join(full, d.name));
58049
+ const st = import_node_fs30.default.statSync(import_node_path39.default.join(full, d.name));
57955
58050
  entry.mtime = new Date(st.mtimeMs).toISOString();
57956
58051
  if (d.isFile()) entry.size = st.size;
57957
58052
  } catch {
@@ -57998,7 +58093,7 @@ var WorkspaceBrowser = class {
57998
58093
  // src/skills/agents-scanner.ts
57999
58094
  var import_node_fs31 = __toESM(require("fs"), 1);
58000
58095
  var import_node_os11 = __toESM(require("os"), 1);
58001
- var import_node_path39 = __toESM(require("path"), 1);
58096
+ var import_node_path40 = __toESM(require("path"), 1);
58002
58097
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
58003
58098
  function isDirLikeSync2(p2) {
58004
58099
  try {
@@ -58036,10 +58131,10 @@ function scanAgentsDir(dir, source, seen, out) {
58036
58131
  }
58037
58132
  for (const ent of entries) {
58038
58133
  if (!ent.name.endsWith(".md")) continue;
58039
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path39.default.join(dir, ent.name)))) {
58134
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path40.default.join(dir, ent.name)))) {
58040
58135
  continue;
58041
58136
  }
58042
- const filePath = import_node_path39.default.join(dir, ent.name);
58137
+ const filePath = import_node_path40.default.join(dir, ent.name);
58043
58138
  const baseName = ent.name.replace(/\.md$/, "");
58044
58139
  if (seen.has(baseName)) continue;
58045
58140
  seen.add(baseName);
@@ -58062,7 +58157,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
58062
58157
  return;
58063
58158
  }
58064
58159
  for (const ent of entries) {
58065
- const childPath = import_node_path39.default.join(dir, ent.name);
58160
+ const childPath = import_node_path40.default.join(dir, ent.name);
58066
58161
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
58067
58162
  walk2(childPath, [...namespaces, ent.name]);
58068
58163
  continue;
@@ -58087,9 +58182,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
58087
58182
  walk2(root, []);
58088
58183
  }
58089
58184
  function readInstalledPlugins2(home) {
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");
58185
+ const pluginsDir = import_node_path40.default.join(home, ".claude", "plugins");
58186
+ const v2 = import_node_path40.default.join(pluginsDir, "installed_plugins_v2.json");
58187
+ const v1 = import_node_path40.default.join(pluginsDir, "installed_plugins.json");
58093
58188
  let raw = null;
58094
58189
  for (const candidate of [v2, v1]) {
58095
58190
  try {
@@ -58118,19 +58213,19 @@ function readInstalledPlugins2(home) {
58118
58213
  return out;
58119
58214
  }
58120
58215
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
58121
- let cur = import_node_path39.default.resolve(startCwd);
58122
- const fsRoot = import_node_path39.default.parse(cur).root;
58216
+ let cur = import_node_path40.default.resolve(startCwd);
58217
+ const fsRoot = import_node_path40.default.parse(cur).root;
58123
58218
  while (true) {
58124
- scanAgentsDir(import_node_path39.default.join(cur, ".claude", "agents"), "project", seen, out);
58219
+ scanAgentsDir(import_node_path40.default.join(cur, ".claude", "agents"), "project", seen, out);
58125
58220
  let hasGit = false;
58126
58221
  try {
58127
- hasGit = import_node_fs31.default.existsSync(import_node_path39.default.join(cur, ".git"));
58222
+ hasGit = import_node_fs31.default.existsSync(import_node_path40.default.join(cur, ".git"));
58128
58223
  } catch {
58129
58224
  }
58130
58225
  if (hasGit) return;
58131
58226
  if (cur === home) return;
58132
58227
  if (cur === fsRoot) return;
58133
- const parent = import_node_path39.default.dirname(cur);
58228
+ const parent = import_node_path40.default.dirname(cur);
58134
58229
  if (parent === cur) return;
58135
58230
  cur = parent;
58136
58231
  }
@@ -58165,7 +58260,7 @@ var AgentsScanner = class {
58165
58260
  }
58166
58261
  const fsBlock = [];
58167
58262
  scanAgentsDir(
58168
- import_node_path39.default.join(this.home, ".claude", "agents"),
58263
+ import_node_path40.default.join(this.home, ".claude", "agents"),
58169
58264
  "global",
58170
58265
  seen,
58171
58266
  fsBlock
@@ -58179,7 +58274,7 @@ var AgentsScanner = class {
58179
58274
  ...this.extraPluginRoots
58180
58275
  ];
58181
58276
  for (const { name, root } of plugins) {
58182
- const agentsRoot = import_node_path39.default.join(root, "agents");
58277
+ const agentsRoot = import_node_path40.default.join(root, "agents");
58183
58278
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
58184
58279
  }
58185
58280
  return [...builtinBlock, ...fsBlock];
@@ -58189,13 +58284,13 @@ var AgentsScanner = class {
58189
58284
  // src/observer/session-observer.ts
58190
58285
  var import_node_fs33 = __toESM(require("fs"), 1);
58191
58286
  var import_node_os13 = __toESM(require("os"), 1);
58192
- var import_node_path41 = __toESM(require("path"), 1);
58287
+ var import_node_path42 = __toESM(require("path"), 1);
58193
58288
  init_claude_history();
58194
58289
 
58195
58290
  // src/observer/subagent-meta-observer.ts
58196
58291
  var import_node_fs32 = __toESM(require("fs"), 1);
58197
58292
  var import_node_os12 = __toESM(require("os"), 1);
58198
- var import_node_path40 = __toESM(require("path"), 1);
58293
+ var import_node_path41 = __toESM(require("path"), 1);
58199
58294
  init_claude_history();
58200
58295
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
58201
58296
  var SubagentMetaObserver = class {
@@ -58208,7 +58303,7 @@ var SubagentMetaObserver = class {
58208
58303
  watches = /* @__PURE__ */ new Map();
58209
58304
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
58210
58305
  resolveSubagentDir(cwd, toolSessionId) {
58211
- return import_node_path40.default.join(
58306
+ return import_node_path41.default.join(
58212
58307
  this.home,
58213
58308
  ".claude",
58214
58309
  "projects",
@@ -58264,7 +58359,7 @@ var SubagentMetaObserver = class {
58264
58359
  if (!m2) return;
58265
58360
  const agentId = m2[1];
58266
58361
  if (w2.emitted.has(agentId)) return;
58267
- const file = import_node_path40.default.join(w2.dirPath, name);
58362
+ const file = import_node_path41.default.join(w2.dirPath, name);
58268
58363
  let raw;
58269
58364
  try {
58270
58365
  raw = import_node_fs32.default.readFileSync(file, "utf8");
@@ -58324,7 +58419,7 @@ var SessionObserver = class {
58324
58419
  metaObserver;
58325
58420
  resolveJsonlPath(cwd, toolSessionId, override) {
58326
58421
  if (override) return override;
58327
- return import_node_path41.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
58422
+ return import_node_path42.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
58328
58423
  }
58329
58424
  start(args) {
58330
58425
  this.stop(args.sessionId);
@@ -58350,10 +58445,10 @@ var SessionObserver = class {
58350
58445
  lastDeriveMs: 0
58351
58446
  };
58352
58447
  try {
58353
- import_node_fs33.default.mkdirSync(import_node_path41.default.dirname(filePath), { recursive: true });
58448
+ import_node_fs33.default.mkdirSync(import_node_path42.default.dirname(filePath), { recursive: true });
58354
58449
  } catch {
58355
58450
  }
58356
- w2.watcher = import_node_fs33.default.watch(import_node_path41.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
58451
+ w2.watcher = import_node_fs33.default.watch(import_node_path42.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
58357
58452
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
58358
58453
  this.poll(w2);
58359
58454
  });
@@ -58450,7 +58545,7 @@ var SessionObserver = class {
58450
58545
  const now = Date.now();
58451
58546
  if (now - w2.lastRelocateScanMs < 1e3) return;
58452
58547
  w2.lastRelocateScanMs = now;
58453
- const projectsRoot = import_node_path41.default.join(this.home, ".claude", "projects");
58548
+ const projectsRoot = import_node_path42.default.join(this.home, ".claude", "projects");
58454
58549
  const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
58455
58550
  if (!found || found === w2.filePath) return;
58456
58551
  try {
@@ -58459,7 +58554,7 @@ var SessionObserver = class {
58459
58554
  }
58460
58555
  w2.filePath = found;
58461
58556
  try {
58462
- w2.watcher = import_node_fs33.default.watch(import_node_path41.default.dirname(found), { persistent: false }, (_event, changedName) => {
58557
+ w2.watcher = import_node_fs33.default.watch(import_node_path42.default.dirname(found), { persistent: false }, (_event, changedName) => {
58463
58558
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
58464
58559
  this.poll(w2);
58465
58560
  });
@@ -58582,7 +58677,7 @@ function listRegistered() {
58582
58677
  var import_node_child_process10 = require("child_process");
58583
58678
  var import_node_fs34 = __toESM(require("fs"), 1);
58584
58679
  var import_node_os14 = __toESM(require("os"), 1);
58585
- var import_node_path42 = __toESM(require("path"), 1);
58680
+ var import_node_path43 = __toESM(require("path"), 1);
58586
58681
  var TITLE_GEN_DIR_PREFIX = "clawd-title-";
58587
58682
  var TITLE_MODEL_BY_TOOL = {
58588
58683
  claude: "haiku",
@@ -58653,7 +58748,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
58653
58748
  if (!text) return null;
58654
58749
  let workDir;
58655
58750
  try {
58656
- workDir = import_node_fs34.default.mkdtempSync(import_node_path42.default.join(import_node_os14.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
58751
+ workDir = import_node_fs34.default.mkdtempSync(import_node_path43.default.join(import_node_os14.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
58657
58752
  } catch {
58658
58753
  return null;
58659
58754
  }
@@ -58663,8 +58758,8 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
58663
58758
  } catch {
58664
58759
  }
58665
58760
  };
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");
58761
+ const outFile = import_node_path43.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
58762
+ const schemaFile = import_node_path43.default.join(workDir, "title-schema.json");
58668
58763
  if (tool === "codex") {
58669
58764
  try {
58670
58765
  import_node_fs34.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
@@ -59428,7 +59523,7 @@ async function authenticate(token, deps) {
59428
59523
 
59429
59524
  // src/legacy-cleanup.ts
59430
59525
  var fs48 = __toESM(require("fs/promises"), 1);
59431
- var path50 = __toESM(require("path"), 1);
59526
+ var path51 = __toESM(require("path"), 1);
59432
59527
  var LEGACY_FILES = [
59433
59528
  "personal-capability.json",
59434
59529
  "received-capabilities.json",
@@ -59437,7 +59532,7 @@ var LEGACY_FILES = [
59437
59532
  async function cleanupLegacyCapabilityFiles(dataDir, logger) {
59438
59533
  const removed = [];
59439
59534
  for (const name of LEGACY_FILES) {
59440
- const p2 = path50.join(dataDir, name);
59535
+ const p2 = path51.join(dataDir, name);
59441
59536
  try {
59442
59537
  await fs48.unlink(p2);
59443
59538
  removed.push(name);
@@ -59452,7 +59547,7 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
59452
59547
 
59453
59548
  // src/inbox/inbox-store.ts
59454
59549
  var fs49 = __toESM(require("fs"), 1);
59455
- var path51 = __toESM(require("path"), 1);
59550
+ var path52 = __toESM(require("path"), 1);
59456
59551
  var INBOX_SUBDIR = "inbox";
59457
59552
  var InboxStore = class {
59458
59553
  constructor(dataDir) {
@@ -59550,10 +59645,10 @@ var InboxStore = class {
59550
59645
  }
59551
59646
  }
59552
59647
  dirPath() {
59553
- return path51.join(this.dataDir, INBOX_SUBDIR);
59648
+ return path52.join(this.dataDir, INBOX_SUBDIR);
59554
59649
  }
59555
59650
  filePath(peerDeviceId) {
59556
- return path51.join(this.dirPath(), `${peerDeviceId}.jsonl`);
59651
+ return path52.join(this.dirPath(), `${peerDeviceId}.jsonl`);
59557
59652
  }
59558
59653
  };
59559
59654
  function parseAllLines(raw) {
@@ -59642,7 +59737,7 @@ var InboxManager = class {
59642
59737
 
59643
59738
  // src/state/contact-store.ts
59644
59739
  var fs50 = __toESM(require("fs"), 1);
59645
- var path52 = __toESM(require("path"), 1);
59740
+ var path53 = __toESM(require("path"), 1);
59646
59741
  var FILE_NAME = "contacts.json";
59647
59742
  var ContactStore = class {
59648
59743
  constructor(dataDir) {
@@ -59652,7 +59747,7 @@ var ContactStore = class {
59652
59747
  contacts = /* @__PURE__ */ new Map();
59653
59748
  load() {
59654
59749
  this.contacts.clear();
59655
- const file = path52.join(this.dataDir, FILE_NAME);
59750
+ const file = path53.join(this.dataDir, FILE_NAME);
59656
59751
  let raw;
59657
59752
  try {
59658
59753
  raw = fs50.readFileSync(file, "utf8");
@@ -59736,7 +59831,7 @@ var ContactStore = class {
59736
59831
  return true;
59737
59832
  }
59738
59833
  flush() {
59739
- const file = path52.join(this.dataDir, FILE_NAME);
59834
+ const file = path53.join(this.dataDir, FILE_NAME);
59740
59835
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
59741
59836
  const content = JSON.stringify(
59742
59837
  { contacts: Array.from(this.contacts.values()) },
@@ -59858,52 +59953,52 @@ async function connectRemote(args) {
59858
59953
 
59859
59954
  // src/migrations/2026-05-20-flatten-sessions.ts
59860
59955
  var fs51 = __toESM(require("fs"), 1);
59861
- var path53 = __toESM(require("path"), 1);
59956
+ var path54 = __toESM(require("path"), 1);
59862
59957
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
59863
59958
  function migrateFlattenSessions(opts) {
59864
59959
  const dataDir = opts.dataDir;
59865
59960
  const now = opts.now ?? Date.now;
59866
- const sessionsDir = path53.join(dataDir, "sessions");
59867
- const flagPath = path53.join(sessionsDir, MIGRATION_FLAG_NAME);
59961
+ const sessionsDir = path54.join(dataDir, "sessions");
59962
+ const flagPath = path54.join(sessionsDir, MIGRATION_FLAG_NAME);
59868
59963
  if (existsSync3(flagPath)) {
59869
59964
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
59870
59965
  }
59871
59966
  let movedBare = 0;
59872
59967
  let movedVmOwner = 0;
59873
59968
  let archivedListener = 0;
59874
- const defaultDir = path53.join(sessionsDir, "default");
59969
+ const defaultDir = path54.join(sessionsDir, "default");
59875
59970
  if (existsSync3(defaultDir)) {
59876
59971
  for (const entry of readdirSafe(defaultDir)) {
59877
59972
  if (!entry.endsWith(".json")) continue;
59878
- const src = path53.join(defaultDir, entry);
59879
- const dst = path53.join(sessionsDir, entry);
59973
+ const src = path54.join(defaultDir, entry);
59974
+ const dst = path54.join(sessionsDir, entry);
59880
59975
  fs51.renameSync(src, dst);
59881
59976
  movedBare += 1;
59882
59977
  }
59883
59978
  rmdirIfEmpty(defaultDir);
59884
59979
  }
59885
59980
  for (const pid of readdirSafe(sessionsDir)) {
59886
- const personaDir = path53.join(sessionsDir, pid);
59981
+ const personaDir = path54.join(sessionsDir, pid);
59887
59982
  if (!isDir(personaDir)) continue;
59888
59983
  if (pid === "default") continue;
59889
- const ownerSrc = path53.join(personaDir, "owner");
59984
+ const ownerSrc = path54.join(personaDir, "owner");
59890
59985
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
59891
- const ownerDst = path53.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
59986
+ const ownerDst = path54.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
59892
59987
  fs51.mkdirSync(ownerDst, { recursive: true });
59893
59988
  for (const file of readdirSafe(ownerSrc)) {
59894
59989
  if (!file.endsWith(".json")) continue;
59895
- fs51.renameSync(path53.join(ownerSrc, file), path53.join(ownerDst, file));
59990
+ fs51.renameSync(path54.join(ownerSrc, file), path54.join(ownerDst, file));
59896
59991
  movedVmOwner += 1;
59897
59992
  }
59898
59993
  rmdirIfEmpty(ownerSrc);
59899
59994
  }
59900
- const listenerSrc = path53.join(personaDir, "listener");
59995
+ const listenerSrc = path54.join(personaDir, "listener");
59901
59996
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
59902
- const archiveDst = path53.join(dataDir, ".legacy", `listener-${pid}`);
59997
+ const archiveDst = path54.join(dataDir, ".legacy", `listener-${pid}`);
59903
59998
  fs51.mkdirSync(archiveDst, { recursive: true });
59904
59999
  for (const file of readdirSafe(listenerSrc)) {
59905
60000
  if (!file.endsWith(".json")) continue;
59906
- fs51.renameSync(path53.join(listenerSrc, file), path53.join(archiveDst, file));
60001
+ fs51.renameSync(path54.join(listenerSrc, file), path54.join(archiveDst, file));
59907
60002
  archivedListener += 1;
59908
60003
  }
59909
60004
  rmdirIfEmpty(listenerSrc);
@@ -59951,13 +60046,13 @@ function rmdirIfEmpty(p2) {
59951
60046
 
59952
60047
  // src/migrations/2026-08-18-drop-seeded-projects.ts
59953
60048
  var fs52 = __toESM(require("fs"), 1);
59954
- var path54 = __toESM(require("path"), 1);
60049
+ var path55 = __toESM(require("path"), 1);
59955
60050
  var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
59956
60051
  function dropSeededProjects(opts) {
59957
60052
  fs52.mkdirSync(opts.dataDir, { recursive: true });
59958
- const flag = path54.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
60053
+ const flag = path55.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
59959
60054
  if (fs52.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
59960
- const file = path54.join(opts.dataDir, "projects.json");
60055
+ const file = path55.join(opts.dataDir, "projects.json");
59961
60056
  let raw = null;
59962
60057
  let dropped = 0;
59963
60058
  try {
@@ -59967,9 +60062,9 @@ function dropSeededProjects(opts) {
59967
60062
  }
59968
60063
  let backup = null;
59969
60064
  if (raw != null && dropped > 0) {
59970
- const dir = path54.join(opts.dataDir, "backups");
60065
+ const dir = path55.join(opts.dataDir, "backups");
59971
60066
  fs52.mkdirSync(dir, { recursive: true });
59972
- backup = path54.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
60067
+ backup = path55.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
59973
60068
  fs52.writeFileSync(backup, raw);
59974
60069
  }
59975
60070
  if (raw != null || dropped > 0) {
@@ -59981,10 +60076,10 @@ function dropSeededProjects(opts) {
59981
60076
 
59982
60077
  // src/transport/http-router.ts
59983
60078
  var import_node_fs36 = __toESM(require("fs"), 1);
59984
- var import_node_path46 = __toESM(require("path"), 1);
60079
+ var import_node_path47 = __toESM(require("path"), 1);
59985
60080
 
59986
60081
  // src/attachment/mime.ts
59987
- var import_node_path43 = __toESM(require("path"), 1);
60082
+ var import_node_path44 = __toESM(require("path"), 1);
59988
60083
  var TEXT_PLAIN = "text/plain; charset=utf-8";
59989
60084
  var EXT_TO_NATIVE_MIME = {
59990
60085
  // 图片
@@ -60091,7 +60186,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
60091
60186
  ".mk"
60092
60187
  ]);
60093
60188
  function lookupMime(filePathOrName) {
60094
- const ext = import_node_path43.default.extname(filePathOrName).toLowerCase();
60189
+ const ext = import_node_path44.default.extname(filePathOrName).toLowerCase();
60095
60190
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
60096
60191
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
60097
60192
  return "application/octet-stream";
@@ -60162,7 +60257,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
60162
60257
 
60163
60258
  // src/attachment/upload.ts
60164
60259
  var import_node_fs35 = __toESM(require("fs"), 1);
60165
- var import_node_path44 = __toESM(require("path"), 1);
60260
+ var import_node_path45 = __toESM(require("path"), 1);
60166
60261
  var import_node_crypto11 = __toESM(require("crypto"), 1);
60167
60262
  var import_promises10 = require("stream/promises");
60168
60263
  var UploadError = class extends Error {
@@ -60174,14 +60269,14 @@ var UploadError = class extends Error {
60174
60269
  code;
60175
60270
  };
60176
60271
  function assertValidFileName(fileName) {
60177
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path44.default.basename(fileName)) {
60272
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path45.default.basename(fileName)) {
60178
60273
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
60179
60274
  }
60180
60275
  }
60181
60276
  var HASH_PREFIX_LEN = 16;
60182
60277
  async function writeUploadedAttachment(args) {
60183
60278
  assertValidFileName(args.fileName);
60184
- const attachmentsRoot = import_node_path44.default.join(args.baseDir, ".attachments");
60279
+ const attachmentsRoot = import_node_path45.default.join(args.baseDir, ".attachments");
60185
60280
  try {
60186
60281
  import_node_fs35.default.mkdirSync(attachmentsRoot, { recursive: true });
60187
60282
  } catch (err) {
@@ -60189,7 +60284,7 @@ async function writeUploadedAttachment(args) {
60189
60284
  }
60190
60285
  const hasher = import_node_crypto11.default.createHash("sha256");
60191
60286
  let actualSize = 0;
60192
- const tmpPath = import_node_path44.default.join(
60287
+ const tmpPath = import_node_path45.default.join(
60193
60288
  attachmentsRoot,
60194
60289
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto11.default.randomBytes(4).toString("hex")}`
60195
60290
  );
@@ -60224,7 +60319,7 @@ async function writeUploadedAttachment(args) {
60224
60319
  );
60225
60320
  }
60226
60321
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
60227
- const hashDir = import_node_path44.default.join(attachmentsRoot, attachmentId);
60322
+ const hashDir = import_node_path45.default.join(attachmentsRoot, attachmentId);
60228
60323
  let finalFileName;
60229
60324
  let hashDirExists = false;
60230
60325
  try {
@@ -60242,7 +60337,7 @@ async function writeUploadedAttachment(args) {
60242
60337
  try {
60243
60338
  import_node_fs35.default.mkdirSync(hashDir, { recursive: true });
60244
60339
  finalFileName = args.fileName;
60245
- import_node_fs35.default.renameSync(tmpPath, import_node_path44.default.join(hashDir, finalFileName));
60340
+ import_node_fs35.default.renameSync(tmpPath, import_node_path45.default.join(hashDir, finalFileName));
60246
60341
  } catch (err) {
60247
60342
  try {
60248
60343
  import_node_fs35.default.unlinkSync(tmpPath);
@@ -60251,7 +60346,7 @@ async function writeUploadedAttachment(args) {
60251
60346
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
60252
60347
  }
60253
60348
  }
60254
- const absPath = import_node_path44.default.join(hashDir, finalFileName);
60349
+ const absPath = import_node_path45.default.join(hashDir, finalFileName);
60255
60350
  const relPath = absPath;
60256
60351
  args.groupFileStore.upsert(args.scope, args.sessionId, {
60257
60352
  relPath: absPath,
@@ -60266,7 +60361,7 @@ async function writeUploadedAttachment(args) {
60266
60361
 
60267
60362
  // src/extension/import.ts
60268
60363
  var import_promises11 = __toESM(require("fs/promises"), 1);
60269
- var import_node_path45 = __toESM(require("path"), 1);
60364
+ var import_node_path46 = __toESM(require("path"), 1);
60270
60365
  var import_node_os15 = __toESM(require("os"), 1);
60271
60366
  var import_jszip = __toESM(require_lib3(), 1);
60272
60367
  var ImportError = class extends Error {
@@ -60284,7 +60379,7 @@ async function importZip(buf, root) {
60284
60379
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
60285
60380
  }
60286
60381
  for (const name of Object.keys(zip.files)) {
60287
- if (name.includes("..") || name.startsWith("/") || import_node_path45.default.isAbsolute(name)) {
60382
+ if (name.includes("..") || name.startsWith("/") || import_node_path46.default.isAbsolute(name)) {
60288
60383
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
60289
60384
  }
60290
60385
  }
@@ -60317,7 +60412,7 @@ async function importZip(buf, root) {
60317
60412
  );
60318
60413
  }
60319
60414
  }
60320
- const destDir = import_node_path45.default.join(root, manifest.id);
60415
+ const destDir = import_node_path46.default.join(root, manifest.id);
60321
60416
  let destExists = false;
60322
60417
  try {
60323
60418
  await import_promises11.default.access(destDir);
@@ -60327,15 +60422,15 @@ async function importZip(buf, root) {
60327
60422
  if (destExists) {
60328
60423
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
60329
60424
  }
60330
- const stage = await import_promises11.default.mkdtemp(import_node_path45.default.join(import_node_os15.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
60425
+ const stage = await import_promises11.default.mkdtemp(import_node_path46.default.join(import_node_os15.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
60331
60426
  try {
60332
60427
  for (const [name, entry] of Object.entries(zip.files)) {
60333
- const dest = import_node_path45.default.join(stage, name);
60428
+ const dest = import_node_path46.default.join(stage, name);
60334
60429
  if (entry.dir) {
60335
60430
  await import_promises11.default.mkdir(dest, { recursive: true });
60336
60431
  continue;
60337
60432
  }
60338
- await import_promises11.default.mkdir(import_node_path45.default.dirname(dest), { recursive: true });
60433
+ await import_promises11.default.mkdir(import_node_path46.default.dirname(dest), { recursive: true });
60339
60434
  const content = await entry.async("nodebuffer");
60340
60435
  await import_promises11.default.writeFile(dest, content);
60341
60436
  }
@@ -60365,7 +60460,7 @@ var SHARE_UI_ASSET_MIME = {
60365
60460
  ".wasm": "application/wasm"
60366
60461
  };
60367
60462
  function shareUiAssetMime(filePath) {
60368
- const ext = import_node_path46.default.extname(filePath).toLowerCase();
60463
+ const ext = import_node_path47.default.extname(filePath).toLowerCase();
60369
60464
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
60370
60465
  }
60371
60466
  var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
@@ -60464,7 +60559,7 @@ function isValidUploadFileName(fileName) {
60464
60559
  if (fileName === "." || fileName === "..") return false;
60465
60560
  if (fileName.startsWith(".")) return false;
60466
60561
  if (fileName.includes("/") || fileName.includes("\\")) return false;
60467
- return fileName === import_node_path46.default.basename(fileName);
60562
+ return fileName === import_node_path47.default.basename(fileName);
60468
60563
  }
60469
60564
  function createHttpRouter(deps) {
60470
60565
  return async (req, res) => {
@@ -60700,7 +60795,7 @@ function createHttpRouter(deps) {
60700
60795
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
60701
60796
  return true;
60702
60797
  }
60703
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path46.default.basename(r.absPath)));
60798
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path47.default.basename(r.absPath)));
60704
60799
  return true;
60705
60800
  }
60706
60801
  const ctx = deps.authResolver.resolveFromHeader(
@@ -60821,7 +60916,7 @@ function createHttpRouter(deps) {
60821
60916
  return true;
60822
60917
  }
60823
60918
  let absPath;
60824
- if (import_node_path46.default.isAbsolute(pathParam)) {
60919
+ if (import_node_path47.default.isAbsolute(pathParam)) {
60825
60920
  absPath = pathParam;
60826
60921
  } else if (deps.sessionStore) {
60827
60922
  const file = deps.sessionStore.read(sid);
@@ -60829,7 +60924,7 @@ function createHttpRouter(deps) {
60829
60924
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
60830
60925
  return true;
60831
60926
  }
60832
- absPath = import_node_path46.default.join(file.cwd, pathParam);
60927
+ absPath = import_node_path47.default.join(file.cwd, pathParam);
60833
60928
  } else {
60834
60929
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
60835
60930
  return true;
@@ -60931,7 +61026,7 @@ function streamFile(res, absPath, logger) {
60931
61026
  return;
60932
61027
  }
60933
61028
  const mime = lookupMime(absPath);
60934
- const basename2 = import_node_path46.default.basename(absPath);
61029
+ const basename2 = import_node_path47.default.basename(absPath);
60935
61030
  res.writeHead(200, {
60936
61031
  "Content-Type": mime,
60937
61032
  "Content-Length": String(stat.size),
@@ -60949,7 +61044,7 @@ function streamFile(res, absPath, logger) {
60949
61044
 
60950
61045
  // src/attachment/gc.ts
60951
61046
  var import_node_fs37 = __toESM(require("fs"), 1);
60952
- var import_node_path47 = __toESM(require("path"), 1);
61047
+ var import_node_path48 = __toESM(require("path"), 1);
60953
61048
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
60954
61049
  function runAttachmentGc(args) {
60955
61050
  const now = (args.now ?? Date.now)();
@@ -60958,12 +61053,12 @@ function runAttachmentGc(args) {
60958
61053
  for (const { scope, sessionId } of args.sessionScopes) {
60959
61054
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
60960
61055
  if (entry.stale) continue;
60961
- if (import_node_path47.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
61056
+ if (import_node_path48.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
60962
61057
  }
60963
61058
  }
60964
61059
  const visited = /* @__PURE__ */ new Set();
60965
61060
  for (const { scope, sessionId } of args.sessionScopes) {
60966
- const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path47.default.join(
61061
+ const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path48.default.join(
60967
61062
  args.dataDir,
60968
61063
  "sessions",
60969
61064
  ...scopeSubPath(scope).map(safeFileName),
@@ -60976,7 +61071,7 @@ function runAttachmentGc(args) {
60976
61071
  return true;
60977
61072
  });
60978
61073
  for (const rootDir of roots) {
60979
- const attRoot = import_node_path47.default.join(rootDir, ".attachments");
61074
+ const attRoot = import_node_path48.default.join(rootDir, ".attachments");
60980
61075
  let hashDirs;
60981
61076
  try {
60982
61077
  hashDirs = import_node_fs37.default.readdirSync(attRoot);
@@ -60986,7 +61081,7 @@ function runAttachmentGc(args) {
60986
61081
  continue;
60987
61082
  }
60988
61083
  for (const hashDir of hashDirs) {
60989
- const hashDirAbs = import_node_path47.default.join(attRoot, hashDir);
61084
+ const hashDirAbs = import_node_path48.default.join(attRoot, hashDir);
60990
61085
  let files;
60991
61086
  try {
60992
61087
  files = import_node_fs37.default.readdirSync(hashDirAbs);
@@ -60994,7 +61089,7 @@ function runAttachmentGc(args) {
60994
61089
  continue;
60995
61090
  }
60996
61091
  for (const name of files) {
60997
- const file = import_node_path47.default.join(hashDirAbs, name);
61092
+ const file = import_node_path48.default.join(hashDirAbs, name);
60998
61093
  let stat;
60999
61094
  try {
61000
61095
  stat = import_node_fs37.default.statSync(file);
@@ -61026,7 +61121,7 @@ function runAttachmentGc(args) {
61026
61121
 
61027
61122
  // src/attachment/group.ts
61028
61123
  var import_node_fs38 = __toESM(require("fs"), 1);
61029
- var import_node_path48 = __toESM(require("path"), 1);
61124
+ var import_node_path49 = __toESM(require("path"), 1);
61030
61125
  var import_node_crypto12 = __toESM(require("crypto"), 1);
61031
61126
  init_protocol();
61032
61127
  var GroupFileStore = class {
@@ -61038,11 +61133,11 @@ var GroupFileStore = class {
61038
61133
  this.logger = opts.logger;
61039
61134
  }
61040
61135
  rootForScope(scope) {
61041
- return import_node_path48.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
61136
+ return import_node_path49.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
61042
61137
  }
61043
61138
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
61044
61139
  filePath(scope, sessionId) {
61045
- return import_node_path48.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
61140
+ return import_node_path49.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
61046
61141
  }
61047
61142
  cacheKey(scope, sessionId) {
61048
61143
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -61077,7 +61172,7 @@ var GroupFileStore = class {
61077
61172
  }
61078
61173
  writeFile(scope, sessionId, entries) {
61079
61174
  const file = this.filePath(scope, sessionId);
61080
- import_node_fs38.default.mkdirSync(import_node_path48.default.dirname(file), { recursive: true });
61175
+ import_node_fs38.default.mkdirSync(import_node_path49.default.dirname(file), { recursive: true });
61081
61176
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
61082
61177
  import_node_fs38.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
61083
61178
  import_node_fs38.default.renameSync(tmp, file);
@@ -61167,9 +61262,9 @@ var GroupFileStore = class {
61167
61262
 
61168
61263
  // src/discovery/state-file.ts
61169
61264
  var import_node_fs39 = __toESM(require("fs"), 1);
61170
- var import_node_path49 = __toESM(require("path"), 1);
61265
+ var import_node_path50 = __toESM(require("path"), 1);
61171
61266
  function defaultStateFilePath(dataDir) {
61172
- return import_node_path49.default.join(dataDir, "state.json");
61267
+ return import_node_path50.default.join(dataDir, "state.json");
61173
61268
  }
61174
61269
  function isPidAlive(pid) {
61175
61270
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -61205,7 +61300,7 @@ var StateFileManager = class {
61205
61300
  return { status: "stale", existing };
61206
61301
  }
61207
61302
  write(state) {
61208
- import_node_fs39.default.mkdirSync(import_node_path49.default.dirname(this.file), { recursive: true });
61303
+ import_node_fs39.default.mkdirSync(import_node_path50.default.dirname(this.file), { recursive: true });
61209
61304
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
61210
61305
  import_node_fs39.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
61211
61306
  import_node_fs39.default.renameSync(tmp, this.file);
@@ -61233,13 +61328,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
61233
61328
 
61234
61329
  // src/tunnel/tunnel-manager.ts
61235
61330
  var import_node_fs43 = __toESM(require("fs"), 1);
61236
- var import_node_path53 = __toESM(require("path"), 1);
61331
+ var import_node_path54 = __toESM(require("path"), 1);
61237
61332
  var import_node_crypto13 = __toESM(require("crypto"), 1);
61238
61333
  var import_node_child_process13 = require("child_process");
61239
61334
 
61240
61335
  // src/tunnel/tunnel-store.ts
61241
61336
  var import_node_fs40 = __toESM(require("fs"), 1);
61242
- var import_node_path50 = __toESM(require("path"), 1);
61337
+ var import_node_path51 = __toESM(require("path"), 1);
61243
61338
  var TunnelStore = class {
61244
61339
  constructor(filePath) {
61245
61340
  this.filePath = filePath;
@@ -61258,7 +61353,7 @@ var TunnelStore = class {
61258
61353
  }
61259
61354
  }
61260
61355
  async set(v2) {
61261
- const dir = import_node_path50.default.dirname(this.filePath);
61356
+ const dir = import_node_path51.default.dirname(this.filePath);
61262
61357
  await import_node_fs40.default.promises.mkdir(dir, { recursive: true });
61263
61358
  const data = JSON.stringify(v2, null, 2);
61264
61359
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
@@ -61370,7 +61465,7 @@ function escape(v2) {
61370
61465
  // src/tunnel/frpc-binary.ts
61371
61466
  var import_node_fs41 = __toESM(require("fs"), 1);
61372
61467
  var import_node_os16 = __toESM(require("os"), 1);
61373
- var import_node_path51 = __toESM(require("path"), 1);
61468
+ var import_node_path52 = __toESM(require("path"), 1);
61374
61469
  var import_node_child_process11 = require("child_process");
61375
61470
  var import_node_stream3 = require("stream");
61376
61471
  var import_promises12 = require("stream/promises");
@@ -61409,13 +61504,13 @@ async function ensureFrpcBinary(opts) {
61409
61504
  }
61410
61505
  const version2 = opts.version ?? FRPC_VERSION;
61411
61506
  const platform = opts.platform ?? detectPlatform();
61412
- const binDir = import_node_path51.default.join(opts.dataDir, "bin");
61507
+ const binDir = import_node_path52.default.join(opts.dataDir, "bin");
61413
61508
  import_node_fs41.default.mkdirSync(binDir, { recursive: true });
61414
61509
  cleanupStaleArtifacts(binDir);
61415
- const stableBin = import_node_path51.default.join(binDir, "frpc");
61510
+ const stableBin = import_node_path52.default.join(binDir, "frpc");
61416
61511
  if (import_node_fs41.default.existsSync(stableBin)) return stableBin;
61417
61512
  const partialBin = `${stableBin}.partial`;
61418
- const tarballPath = import_node_path51.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
61513
+ const tarballPath = import_node_path52.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
61419
61514
  try {
61420
61515
  const url = frpcDownloadUrl(version2, platform);
61421
61516
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -61441,7 +61536,7 @@ function cleanupStaleArtifacts(binDir) {
61441
61536
  }
61442
61537
  for (const name of entries) {
61443
61538
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
61444
- const full = import_node_path51.default.join(binDir, name);
61539
+ const full = import_node_path52.default.join(binDir, name);
61445
61540
  try {
61446
61541
  import_node_fs41.default.rmSync(full, { recursive: true, force: true });
61447
61542
  } catch {
@@ -61467,7 +61562,7 @@ async function downloadToFile(url, dest, fetchImpl) {
61467
61562
  await (0, import_promises12.pipeline)(nodeStream, out);
61468
61563
  }
61469
61564
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
61470
- const work = import_node_path51.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
61565
+ const work = import_node_path52.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
61471
61566
  import_node_fs41.default.mkdirSync(work, { recursive: true });
61472
61567
  try {
61473
61568
  await new Promise((resolve9, reject) => {
@@ -61476,7 +61571,7 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
61476
61571
  proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
61477
61572
  });
61478
61573
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
61479
- const src = import_node_path51.default.join(work, dirName, "frpc");
61574
+ const src = import_node_path52.default.join(work, dirName, "frpc");
61480
61575
  if (!import_node_fs41.default.existsSync(src)) {
61481
61576
  throw new Error(`frpc not found inside tarball at ${src}`);
61482
61577
  }
@@ -61488,10 +61583,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
61488
61583
 
61489
61584
  // src/tunnel/frpc-process.ts
61490
61585
  var import_node_fs42 = __toESM(require("fs"), 1);
61491
- var import_node_path52 = __toESM(require("path"), 1);
61586
+ var import_node_path53 = __toESM(require("path"), 1);
61492
61587
  var import_node_child_process12 = require("child_process");
61493
61588
  function frpcPidFilePath(dataDir) {
61494
- return import_node_path52.default.join(dataDir, "frpc.pid");
61589
+ return import_node_path53.default.join(dataDir, "frpc.pid");
61495
61590
  }
61496
61591
  function writeFrpcPid(dataDir, pid) {
61497
61592
  try {
@@ -61533,7 +61628,7 @@ function defaultSleep2(ms) {
61533
61628
  }
61534
61629
  async function killStaleFrpc(deps) {
61535
61630
  const pidFile = frpcPidFilePath(deps.dataDir);
61536
- const tomlPath = import_node_path52.default.join(deps.dataDir, "frpc.toml");
61631
+ const tomlPath = import_node_path53.default.join(deps.dataDir, "frpc.toml");
61537
61632
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
61538
61633
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
61539
61634
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -61605,7 +61700,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
61605
61700
  var TunnelManager = class {
61606
61701
  constructor(deps) {
61607
61702
  this.deps = deps;
61608
- this.store = deps.store ?? new TunnelStore(import_node_path53.default.join(deps.dataDir, "tunnel.json"));
61703
+ this.store = deps.store ?? new TunnelStore(import_node_path54.default.join(deps.dataDir, "tunnel.json"));
61609
61704
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
61610
61705
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
61611
61706
  }
@@ -61732,7 +61827,7 @@ var TunnelManager = class {
61732
61827
  dataDir: this.deps.dataDir,
61733
61828
  override: this.deps.frpcBinaryOverride ?? void 0
61734
61829
  });
61735
- const tomlPath = import_node_path53.default.join(this.deps.dataDir, "frpc.toml");
61830
+ const tomlPath = import_node_path54.default.join(this.deps.dataDir, "frpc.toml");
61736
61831
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto13.default.randomBytes(3).toString("hex")}`;
61737
61832
  const toml = buildFrpcToml({
61738
61833
  serverAddr: t.frpsHost,
@@ -61747,9 +61842,9 @@ var TunnelManager = class {
61747
61842
  const proc = (this.deps.spawnImpl ?? import_node_child_process13.spawn)(frpcBin, ["-c", tomlPath], {
61748
61843
  stdio: ["ignore", "pipe", "pipe"]
61749
61844
  });
61750
- const logDir = import_node_path53.default.join(this.deps.dataDir, "log");
61845
+ const logDir = import_node_path54.default.join(this.deps.dataDir, "log");
61751
61846
  import_node_fs43.default.mkdirSync(logDir, { recursive: true });
61752
- const logFilePath = import_node_path53.default.join(logDir, "frpc.log");
61847
+ const logFilePath = import_node_path54.default.join(logDir, "frpc.log");
61753
61848
  const logStream = import_node_fs43.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
61754
61849
  logStream.on("error", () => {
61755
61850
  });
@@ -61833,15 +61928,15 @@ async function waitForFrpcReady(proc, timeoutMs) {
61833
61928
 
61834
61929
  // src/tunnel/device-key.ts
61835
61930
  var import_node_os17 = __toESM(require("os"), 1);
61836
- var import_node_path54 = __toESM(require("path"), 1);
61931
+ var import_node_path55 = __toESM(require("path"), 1);
61837
61932
  var import_node_crypto14 = __toESM(require("crypto"), 1);
61838
61933
  var DERIVE_SALT = "clawd-tunnel-device-v1";
61839
61934
  function deriveStableDeviceKey(opts = {}) {
61840
61935
  const hostname = opts.hostname ?? import_node_os17.default.hostname();
61841
61936
  const uid = opts.uid ?? (typeof import_node_os17.default.userInfo === "function" ? import_node_os17.default.userInfo().uid : 0);
61842
61937
  const home = opts.home ?? import_node_os17.default.homedir();
61843
- const defaultDataDir = import_node_path54.default.resolve(import_node_path54.default.join(home, ".clawd"));
61844
- const normalizedDataDir = opts.dataDir ? import_node_path54.default.resolve(opts.dataDir) : null;
61938
+ const defaultDataDir = import_node_path55.default.resolve(import_node_path55.default.join(home, ".clawd"));
61939
+ const normalizedDataDir = opts.dataDir ? import_node_path55.default.resolve(opts.dataDir) : null;
61845
61940
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
61846
61941
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
61847
61942
  return import_node_crypto14.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
@@ -61849,11 +61944,11 @@ function deriveStableDeviceKey(opts = {}) {
61849
61944
 
61850
61945
  // src/auth-store.ts
61851
61946
  var import_node_fs44 = __toESM(require("fs"), 1);
61852
- var import_node_path55 = __toESM(require("path"), 1);
61947
+ var import_node_path56 = __toESM(require("path"), 1);
61853
61948
  var import_node_crypto15 = __toESM(require("crypto"), 1);
61854
61949
  var AUTH_FILE_NAME = "auth.json";
61855
61950
  function authFilePath(dataDir) {
61856
- return import_node_path55.default.join(dataDir, AUTH_FILE_NAME);
61951
+ return import_node_path56.default.join(dataDir, AUTH_FILE_NAME);
61857
61952
  }
61858
61953
  function loadOrCreateAuthFile(opts) {
61859
61954
  const file = authFilePath(opts.dataDir);
@@ -61905,7 +62000,7 @@ function readAuthFile(file) {
61905
62000
  }
61906
62001
  }
61907
62002
  function writeAuthFile(file, content) {
61908
- import_node_fs44.default.mkdirSync(import_node_path55.default.dirname(file), { recursive: true });
62003
+ import_node_fs44.default.mkdirSync(import_node_path56.default.dirname(file), { recursive: true });
61909
62004
  import_node_fs44.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
61910
62005
  try {
61911
62006
  import_node_fs44.default.chmodSync(file, 384);
@@ -61916,10 +62011,10 @@ function writeAuthFile(file, content) {
61916
62011
  // src/owner-profile.ts
61917
62012
  var import_node_fs45 = __toESM(require("fs"), 1);
61918
62013
  var import_node_os18 = __toESM(require("os"), 1);
61919
- var import_node_path56 = __toESM(require("path"), 1);
62014
+ var import_node_path57 = __toESM(require("path"), 1);
61920
62015
  var PROFILE_FILENAME = "profile.json";
61921
62016
  function profilePath(dataDir) {
61922
- return import_node_path56.default.join(dataDir, PROFILE_FILENAME);
62017
+ return import_node_path57.default.join(dataDir, PROFILE_FILENAME);
61923
62018
  }
61924
62019
  function loadOwnerProfile(dataDir) {
61925
62020
  let raw;
@@ -61957,12 +62052,12 @@ function loadOwnerDisplayName(dataDir) {
61957
62052
 
61958
62053
  // src/feishu-auth/owner-identity-store.ts
61959
62054
  var import_node_fs46 = __toESM(require("fs"), 1);
61960
- var import_node_path57 = __toESM(require("path"), 1);
62055
+ var import_node_path58 = __toESM(require("path"), 1);
61961
62056
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
61962
62057
  var OwnerIdentityStore = class {
61963
62058
  file;
61964
62059
  constructor(dataDir) {
61965
- this.file = import_node_path57.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
62060
+ this.file = import_node_path58.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
61966
62061
  }
61967
62062
  read() {
61968
62063
  let raw;
@@ -61995,7 +62090,7 @@ var OwnerIdentityStore = class {
61995
62090
  };
61996
62091
  }
61997
62092
  write(record3) {
61998
- import_node_fs46.default.mkdirSync(import_node_path57.default.dirname(this.file), { recursive: true });
62093
+ import_node_fs46.default.mkdirSync(import_node_path58.default.dirname(this.file), { recursive: true });
61999
62094
  import_node_fs46.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
62000
62095
  try {
62001
62096
  import_node_fs46.default.chmodSync(this.file, 384);
@@ -62141,9 +62236,9 @@ var CentralClientError = class extends Error {
62141
62236
  code;
62142
62237
  cause;
62143
62238
  };
62144
- async function centralRequest(opts, path99, init) {
62239
+ async function centralRequest(opts, path100, init) {
62145
62240
  const f = opts.fetchImpl ?? globalThis.fetch;
62146
- const url = `${opts.api.replace(/\/+$/, "")}${path99}`;
62241
+ const url = `${opts.api.replace(/\/+$/, "")}${path100}`;
62147
62242
  const ctrl = new AbortController();
62148
62243
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
62149
62244
  let res;
@@ -62581,7 +62676,7 @@ function verifyConnectToken(args) {
62581
62676
 
62582
62677
  // src/feishu-auth/server-key.ts
62583
62678
  var fs66 = __toESM(require("fs"), 1);
62584
- var path70 = __toESM(require("path"), 1);
62679
+ var path71 = __toESM(require("path"), 1);
62585
62680
  var FILE_NAME2 = "server-signing-key.json";
62586
62681
  var ServerKeyStore = class {
62587
62682
  constructor(dataDir) {
@@ -62589,7 +62684,7 @@ var ServerKeyStore = class {
62589
62684
  }
62590
62685
  dataDir;
62591
62686
  filePath() {
62592
- return path70.join(this.dataDir, FILE_NAME2);
62687
+ return path71.join(this.dataDir, FILE_NAME2);
62593
62688
  }
62594
62689
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
62595
62690
  read() {
@@ -62624,7 +62719,7 @@ var ServerKeyStore = class {
62624
62719
  init_protocol();
62625
62720
 
62626
62721
  // src/handlers/index.ts
62627
- var import_node_path73 = __toESM(require("path"), 1);
62722
+ var import_node_path74 = __toESM(require("path"), 1);
62628
62723
 
62629
62724
  // src/handlers/session.ts
62630
62725
  init_protocol();
@@ -62632,7 +62727,7 @@ init_protocol();
62632
62727
  // src/session/fork.ts
62633
62728
  var import_node_fs47 = __toESM(require("fs"), 1);
62634
62729
  var import_node_os19 = __toESM(require("os"), 1);
62635
- var import_node_path58 = __toESM(require("path"), 1);
62730
+ var import_node_path59 = __toESM(require("path"), 1);
62636
62731
  var import_node_crypto17 = require("crypto");
62637
62732
  init_claude_history();
62638
62733
  function readJsonlEntries(file) {
@@ -62649,19 +62744,19 @@ function readJsonlEntries(file) {
62649
62744
  return out;
62650
62745
  }
62651
62746
  function forkSession(input) {
62652
- const baseDir = input.baseDir ?? import_node_path58.default.join(import_node_os19.default.homedir(), ".claude");
62653
- let projectDir = import_node_path58.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
62654
- let sourceFile = import_node_path58.default.join(projectDir, `${input.toolSessionId}.jsonl`);
62747
+ const baseDir = input.baseDir ?? import_node_path59.default.join(import_node_os19.default.homedir(), ".claude");
62748
+ let projectDir = import_node_path59.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
62749
+ let sourceFile = import_node_path59.default.join(projectDir, `${input.toolSessionId}.jsonl`);
62655
62750
  if (!import_node_fs47.default.existsSync(sourceFile)) {
62656
62751
  const found = findTranscriptByToolSessionId(
62657
- import_node_path58.default.join(baseDir, "projects"),
62752
+ import_node_path59.default.join(baseDir, "projects"),
62658
62753
  input.toolSessionId
62659
62754
  );
62660
62755
  if (!found) {
62661
62756
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
62662
62757
  }
62663
62758
  sourceFile = found;
62664
- projectDir = import_node_path58.default.dirname(found);
62759
+ projectDir = import_node_path59.default.dirname(found);
62665
62760
  }
62666
62761
  const entries = readJsonlEntries(sourceFile);
62667
62762
  const mainEntries = entries.filter((e) => e.isSidechain !== true);
@@ -62690,8 +62785,8 @@ function forkSession(input) {
62690
62785
  }
62691
62786
  forkedLines.push(JSON.stringify(forked));
62692
62787
  }
62693
- const outDir = input.targetCwd ? import_node_path58.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
62694
- const forkedFilePath = import_node_path58.default.join(outDir, `${forkedToolSessionId}.jsonl`);
62788
+ const outDir = input.targetCwd ? import_node_path59.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
62789
+ const forkedFilePath = import_node_path59.default.join(outDir, `${forkedToolSessionId}.jsonl`);
62695
62790
  import_node_fs47.default.mkdirSync(outDir, { recursive: true });
62696
62791
  import_node_fs47.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
62697
62792
  return { forkedToolSessionId, forkedFilePath };
@@ -62701,16 +62796,16 @@ function forkSession(input) {
62701
62796
  var import_node_fs48 = __toESM(require("fs"), 1);
62702
62797
  var import_promises13 = __toESM(require("fs/promises"), 1);
62703
62798
  var import_node_os20 = __toESM(require("os"), 1);
62704
- var import_node_path59 = __toESM(require("path"), 1);
62799
+ var import_node_path60 = __toESM(require("path"), 1);
62705
62800
  var import_node_module = require("module");
62706
62801
  var import_node_child_process14 = require("child_process");
62707
62802
  var import_meta5 = {};
62708
62803
  function defaultRoots() {
62709
62804
  const home = import_node_os20.default.homedir();
62710
62805
  return {
62711
- claudeProjectsDir: import_node_path59.default.join(home, ".claude", "projects"),
62712
- codexDir: import_node_path59.default.join(home, ".codex"),
62713
- clawdDir: import_node_path59.default.join(home, ".clawd")
62806
+ claudeProjectsDir: import_node_path60.default.join(home, ".claude", "projects"),
62807
+ codexDir: import_node_path60.default.join(home, ".codex"),
62808
+ clawdDir: import_node_path60.default.join(home, ".clawd")
62714
62809
  };
62715
62810
  }
62716
62811
  function width(s) {
@@ -62778,13 +62873,13 @@ async function scanClaude(roots) {
62778
62873
  if (!d.isDirectory()) continue;
62779
62874
  let files;
62780
62875
  try {
62781
- files = import_node_fs48.default.readdirSync(import_node_path59.default.join(roots.claudeProjectsDir, d.name));
62876
+ files = import_node_fs48.default.readdirSync(import_node_path60.default.join(roots.claudeProjectsDir, d.name));
62782
62877
  } catch {
62783
62878
  continue;
62784
62879
  }
62785
62880
  for (const name of files) {
62786
62881
  if (!name.endsWith(".jsonl")) continue;
62787
- const file = import_node_path59.default.join(roots.claudeProjectsDir, d.name, name);
62882
+ const file = import_node_path60.default.join(roots.claudeProjectsDir, d.name, name);
62788
62883
  let st;
62789
62884
  try {
62790
62885
  st = import_node_fs48.default.statSync(file);
@@ -62914,7 +63009,7 @@ async function codexFromRows(rows) {
62914
63009
  async function scanCodex(roots) {
62915
63010
  let dbs = [];
62916
63011
  try {
62917
- 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));
63012
+ dbs = import_node_fs48.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path60.default.join(roots.codexDir, n));
62918
63013
  } catch {
62919
63014
  }
62920
63015
  if (!dbs.length) return [];
@@ -62923,14 +63018,14 @@ async function scanCodex(roots) {
62923
63018
  }
62924
63019
  async function scanExternalSessions(rootsIn) {
62925
63020
  const roots = { ...defaultRoots(), ...rootsIn };
62926
- const personaRoot = import_node_path59.default.join(roots.clawdDir, "personas");
63021
+ const personaRoot = import_node_path60.default.join(roots.clawdDir, "personas");
62927
63022
  const all = [...await scanClaude(roots), ...await scanCodex(roots)];
62928
63023
  const out = [];
62929
63024
  for (const c of all) {
62930
63025
  if (c.skip) continue;
62931
63026
  if (c.turns < 1) continue;
62932
63027
  if (!c.cwd || !isDir2(c.cwd)) continue;
62933
- 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)) {
63028
+ if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path60.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path60.default.sep)) {
62934
63029
  continue;
62935
63030
  }
62936
63031
  out.push({
@@ -62948,12 +63043,12 @@ async function scanExternalSessions(rootsIn) {
62948
63043
 
62949
63044
  // src/session/import-ledger.ts
62950
63045
  var import_node_fs49 = __toESM(require("fs"), 1);
62951
- var import_node_path60 = __toESM(require("path"), 1);
63046
+ var import_node_path61 = __toESM(require("path"), 1);
62952
63047
  var LEDGER_FILENAME = "session-import-ledger.json";
62953
63048
  function readImportLedger(dataDir) {
62954
63049
  try {
62955
63050
  const parsed = JSON.parse(
62956
- import_node_fs49.default.readFileSync(import_node_path60.default.join(dataDir, LEDGER_FILENAME), "utf8")
63051
+ import_node_fs49.default.readFileSync(import_node_path61.default.join(dataDir, LEDGER_FILENAME), "utf8")
62957
63052
  );
62958
63053
  return Array.isArray(parsed) ? parsed : [];
62959
63054
  } catch {
@@ -62961,7 +63056,7 @@ function readImportLedger(dataDir) {
62961
63056
  }
62962
63057
  }
62963
63058
  function appendImportLedger(dataDir, entry) {
62964
- const file = import_node_path60.default.join(dataDir, LEDGER_FILENAME);
63059
+ const file = import_node_path61.default.join(dataDir, LEDGER_FILENAME);
62965
63060
  const entries = readImportLedger(dataDir);
62966
63061
  entries.push(entry);
62967
63062
  import_node_fs49.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
@@ -62969,7 +63064,7 @@ function appendImportLedger(dataDir, entry) {
62969
63064
 
62970
63065
  // src/tools/transcript-search.ts
62971
63066
  var import_node_fs50 = __toESM(require("fs"), 1);
62972
- var import_node_path61 = __toESM(require("path"), 1);
63067
+ var import_node_path62 = __toESM(require("path"), 1);
62973
63068
  var SNIPPET_PAD = 60;
62974
63069
  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/;
62975
63070
  var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
@@ -63062,7 +63157,7 @@ function createCodexRolloutLocator(roots) {
63062
63157
  return;
63063
63158
  }
63064
63159
  for (const entry of entries) {
63065
- const full = import_node_path61.default.join(dir, entry.name);
63160
+ const full = import_node_path62.default.join(dir, entry.name);
63066
63161
  if (entry.isDirectory()) {
63067
63162
  walk2(full, into);
63068
63163
  continue;
@@ -63083,15 +63178,15 @@ function createCodexRolloutLocator(roots) {
63083
63178
  // src/handlers/session.ts
63084
63179
  init_protocol();
63085
63180
  var import_node_os21 = __toESM(require("os"), 1);
63086
- var import_node_path62 = __toESM(require("path"), 1);
63181
+ var import_node_path63 = __toESM(require("path"), 1);
63087
63182
  function canReadSearchHit(ctx, file) {
63088
63183
  if (!ctx || ctx.principal.kind === "owner") return true;
63089
63184
  return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
63090
63185
  }
63091
63186
  var DEFAULT_SEARCH_LIMIT = 9;
63092
63187
  function codexRolloutRoots(dataDir) {
63093
- const roots = [import_node_path62.default.join(import_node_os21.default.homedir(), ".codex", "sessions")];
63094
- if (dataDir) roots.push(import_node_path62.default.join(dataDir, "codex-home", "sessions"));
63188
+ const roots = [import_node_path63.default.join(import_node_os21.default.homedir(), ".codex", "sessions")];
63189
+ if (dataDir) roots.push(import_node_path63.default.join(dataDir, "codex-home", "sessions"));
63095
63190
  return roots;
63096
63191
  }
63097
63192
  function buildSessionHandlers(deps) {
@@ -63640,7 +63735,7 @@ function buildPermissionHandlers(deps) {
63640
63735
  }
63641
63736
 
63642
63737
  // src/handlers/history.ts
63643
- var path77 = __toESM(require("path"), 1);
63738
+ var path78 = __toESM(require("path"), 1);
63644
63739
  init_protocol();
63645
63740
 
63646
63741
  // src/session/recent-dirs.ts
@@ -63658,7 +63753,7 @@ function listRecentDirs(store, limit = 50) {
63658
63753
  }
63659
63754
 
63660
63755
  // src/permission/persona-paths.ts
63661
- var path76 = __toESM(require("path"), 1);
63756
+ var path77 = __toESM(require("path"), 1);
63662
63757
  function getAllowedPersonaIds(grants, action) {
63663
63758
  const ids = /* @__PURE__ */ new Set();
63664
63759
  for (const g2 of grants) {
@@ -63671,42 +63766,42 @@ function getAllowedPersonaIds(grants, action) {
63671
63766
  return ids;
63672
63767
  }
63673
63768
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
63674
- const target = path76.resolve(absPath);
63769
+ const target = path77.resolve(absPath);
63675
63770
  if (userWorkDir) {
63676
- const u = path76.resolve(userWorkDir);
63677
- const usep = u.endsWith(path76.sep) ? "" : path76.sep;
63771
+ const u = path77.resolve(userWorkDir);
63772
+ const usep = u.endsWith(path77.sep) ? "" : path77.sep;
63678
63773
  if (target === u || target.startsWith(u + usep)) return true;
63679
63774
  }
63680
- const root = path76.resolve(personaRoot);
63681
- const sep4 = root.endsWith(path76.sep) ? "" : path76.sep;
63775
+ const root = path77.resolve(personaRoot);
63776
+ const sep4 = root.endsWith(path77.sep) ? "" : path77.sep;
63682
63777
  if (!target.startsWith(root + sep4)) return false;
63683
- const rel = path76.relative(root, target);
63778
+ const rel = path77.relative(root, target);
63684
63779
  if (!rel || rel.startsWith("..")) return false;
63685
- const personaId2 = rel.split(path76.sep)[0];
63780
+ const personaId2 = rel.split(path77.sep)[0];
63686
63781
  if (!personaId2) return false;
63687
63782
  const allowed = getAllowedPersonaIds(grants, action);
63688
63783
  if (allowed === "*") return true;
63689
63784
  return allowed.has(personaId2);
63690
63785
  }
63691
63786
  function personaIdFromPath(absPath, personaRoot) {
63692
- const root = path76.resolve(personaRoot);
63693
- const target = path76.resolve(absPath);
63694
- const sep4 = root.endsWith(path76.sep) ? "" : path76.sep;
63787
+ const root = path77.resolve(personaRoot);
63788
+ const target = path77.resolve(absPath);
63789
+ const sep4 = root.endsWith(path77.sep) ? "" : path77.sep;
63695
63790
  if (!target.startsWith(root + sep4)) return null;
63696
- const rel = path76.relative(root, target);
63791
+ const rel = path77.relative(root, target);
63697
63792
  if (!rel || rel.startsWith("..")) return null;
63698
- const id = rel.split(path76.sep)[0];
63793
+ const id = rel.split(path77.sep)[0];
63699
63794
  return id || null;
63700
63795
  }
63701
63796
  function isPathWithin(dir, absPath) {
63702
- const d = path76.resolve(dir);
63703
- const t = path76.resolve(absPath);
63704
- const sep4 = d.endsWith(path76.sep) ? "" : path76.sep;
63797
+ const d = path77.resolve(dir);
63798
+ const t = path77.resolve(absPath);
63799
+ const sep4 = d.endsWith(path77.sep) ? "" : path77.sep;
63705
63800
  return t === d || t.startsWith(d + sep4);
63706
63801
  }
63707
63802
  function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
63708
63803
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
63709
- return personaIdFromPath(path76.resolve(absPath), personaRoot) === personaId2;
63804
+ return personaIdFromPath(path77.resolve(absPath), personaRoot) === personaId2;
63710
63805
  }
63711
63806
 
63712
63807
  // src/handlers/history.ts
@@ -63759,7 +63854,7 @@ function buildHistoryHandlers(deps) {
63759
63854
  if (!pid) return false;
63760
63855
  return isGuestPathAllowed(
63761
63856
  ctx.grants,
63762
- path77.join(personaRoot, pid),
63857
+ path78.join(personaRoot, pid),
63763
63858
  personaRoot,
63764
63859
  "read",
63765
63860
  userWorkDir
@@ -63771,7 +63866,7 @@ function buildHistoryHandlers(deps) {
63771
63866
  };
63772
63867
  const list = async (frame, _client, ctx) => {
63773
63868
  const args = HistoryListArgs.parse(frame);
63774
- assertGuestPath(ctx, path77.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
63869
+ assertGuestPath(ctx, path78.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
63775
63870
  const sessions = await history.listSessions(args);
63776
63871
  return { response: { type: "history:list", sessions } };
63777
63872
  };
@@ -63819,14 +63914,14 @@ function buildHistoryHandlers(deps) {
63819
63914
  };
63820
63915
  const subagents = async (frame, _client, ctx) => {
63821
63916
  const args = HistorySubagentsArgs.parse(frame);
63822
- assertGuestPath(ctx, path77.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
63917
+ assertGuestPath(ctx, path78.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
63823
63918
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
63824
63919
  const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
63825
63920
  return { response: { type: "history:subagents", subagents: subs } };
63826
63921
  };
63827
63922
  const subagentRead = async (frame, _client, ctx) => {
63828
63923
  const args = HistorySubagentReadArgs.parse(frame);
63829
- assertGuestPath(ctx, path77.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
63924
+ assertGuestPath(ctx, path78.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
63830
63925
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
63831
63926
  const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
63832
63927
  return { response: { type: "history:subagent-read", ...res } };
@@ -63836,7 +63931,7 @@ function buildHistoryHandlers(deps) {
63836
63931
  if (ctx?.principal.kind === "guest" && personaRoot) {
63837
63932
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
63838
63933
  const filtered = dirs.filter(
63839
- (d) => isGuestPathAllowed(ctx.grants, path77.resolve(d.cwd), personaRoot, "read", userWorkDir)
63934
+ (d) => isGuestPathAllowed(ctx.grants, path78.resolve(d.cwd), personaRoot, "read", userWorkDir)
63840
63935
  );
63841
63936
  return { response: { type: "history:recentDirs", dirs: filtered } };
63842
63937
  }
@@ -63855,15 +63950,15 @@ function buildHistoryHandlers(deps) {
63855
63950
  // src/handlers/projects.ts
63856
63951
  var fs71 = __toESM(require("fs"), 1);
63857
63952
  var os23 = __toESM(require("os"), 1);
63858
- var path78 = __toESM(require("path"), 1);
63953
+ var path79 = __toESM(require("path"), 1);
63859
63954
  var import_node_child_process15 = require("child_process");
63860
63955
  init_protocol();
63861
- var DEFAULT_PROJECTS_ROOT = path78.join(os23.homedir(), "Documents", "ChatGPT");
63956
+ var DEFAULT_PROJECTS_ROOT = path79.join(os23.homedir(), "Documents", "ChatGPT");
63862
63957
  function allocateDir(root, name) {
63863
- let candidate = path78.join(root, name);
63958
+ let candidate = path79.join(root, name);
63864
63959
  let n = 2;
63865
63960
  while (fs71.existsSync(candidate)) {
63866
- candidate = path78.join(root, `${name} ${n}`);
63961
+ candidate = path79.join(root, `${name} ${n}`);
63867
63962
  n += 1;
63868
63963
  }
63869
63964
  return candidate;
@@ -63948,7 +64043,7 @@ function buildProjectHandlers(deps) {
63948
64043
  }
63949
64044
 
63950
64045
  // src/handlers/workspace.ts
63951
- var path79 = __toESM(require("path"), 1);
64046
+ var path80 = __toESM(require("path"), 1);
63952
64047
  var os24 = __toESM(require("os"), 1);
63953
64048
  init_protocol();
63954
64049
  init_protocol();
@@ -63990,22 +64085,22 @@ function buildWorkspaceHandlers(deps) {
63990
64085
  const args = WorkspaceListArgs.parse(frame);
63991
64086
  const isGuest = ctx?.principal.kind === "guest";
63992
64087
  const fallbackCwd = isGuest && personaRoot ? personaRoot : os24.homedir();
63993
- const resolvedCwd = path79.resolve(args.cwd ?? fallbackCwd);
63994
- const target = args.path ? path79.resolve(resolvedCwd, args.path) : resolvedCwd;
64088
+ const resolvedCwd = path80.resolve(args.cwd ?? fallbackCwd);
64089
+ const target = args.path ? path80.resolve(resolvedCwd, args.path) : resolvedCwd;
63995
64090
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
63996
64091
  const res = workspace.list({ ...args, cwd: resolvedCwd });
63997
64092
  return { response: { type: "workspace:list", ...res } };
63998
64093
  };
63999
64094
  const read = async (frame, _client, ctx) => {
64000
64095
  const args = WorkspaceReadArgs.parse(frame);
64001
- const target = path79.isAbsolute(args.path) ? path79.resolve(args.path) : path79.resolve(args.cwd, args.path);
64096
+ const target = path80.isAbsolute(args.path) ? path80.resolve(args.path) : path80.resolve(args.cwd, args.path);
64002
64097
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
64003
64098
  const res = workspace.read(args);
64004
64099
  return { response: { type: "workspace:read", ...res } };
64005
64100
  };
64006
64101
  const skillsList = async (frame, _client, ctx) => {
64007
64102
  const args = SkillsListArgs.parse(frame);
64008
- const cwdAbs = path79.resolve(args.cwd);
64103
+ const cwdAbs = path80.resolve(args.cwd);
64009
64104
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
64010
64105
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
64011
64106
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -64017,7 +64112,7 @@ function buildWorkspaceHandlers(deps) {
64017
64112
  };
64018
64113
  const agentsList = async (frame, _client, ctx) => {
64019
64114
  const args = AgentsListArgs.parse(frame);
64020
- const cwdAbs = path79.resolve(args.cwd);
64115
+ const cwdAbs = path80.resolve(args.cwd);
64021
64116
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
64022
64117
  if (args.tool === "codex") {
64023
64118
  return { response: { type: "agents:list", agents: [] } };
@@ -64039,18 +64134,18 @@ function buildWorkspaceHandlers(deps) {
64039
64134
  }
64040
64135
 
64041
64136
  // src/handlers/git.ts
64042
- var path81 = __toESM(require("path"), 1);
64137
+ var path82 = __toESM(require("path"), 1);
64043
64138
  init_protocol();
64044
64139
  init_protocol();
64045
64140
 
64046
64141
  // src/workspace/git.ts
64047
64142
  var import_node_child_process16 = require("child_process");
64048
64143
  var import_node_fs51 = __toESM(require("fs"), 1);
64049
- var import_node_path63 = __toESM(require("path"), 1);
64144
+ var import_node_path64 = __toESM(require("path"), 1);
64050
64145
  var import_node_util = require("util");
64051
64146
  var pexec = (0, import_node_util.promisify)(import_node_child_process16.execFile);
64052
64147
  function normalizePath(p2) {
64053
- const resolved = import_node_path63.default.resolve(p2);
64148
+ const resolved = import_node_path64.default.resolve(p2);
64054
64149
  try {
64055
64150
  return import_node_fs51.default.realpathSync(resolved);
64056
64151
  } catch {
@@ -64126,7 +64221,7 @@ async function listGitBranches(cwd) {
64126
64221
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
64127
64222
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
64128
64223
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
64129
- if (!isGuestPathAllowed(ctx.grants, path81.resolve(cwd), personaRoot, "read", userWorkDir)) {
64224
+ if (!isGuestPathAllowed(ctx.grants, path82.resolve(cwd), personaRoot, "read", userWorkDir)) {
64130
64225
  throw new ClawdError(
64131
64226
  ERROR_CODES.UNAUTHORIZED,
64132
64227
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -64974,21 +65069,21 @@ function computeMethodAccess(args) {
64974
65069
  }
64975
65070
 
64976
65071
  // src/version.ts
64977
- var version = "0.2.468".length > 0 ? "0.2.468" : "dev";
65072
+ var version = "0.2.469".length > 0 ? "0.2.469" : "dev";
64978
65073
 
64979
65074
  // src/cli-probe/probe.ts
64980
65075
  var fs73 = __toESM(require("fs"), 1);
64981
- var path82 = __toESM(require("path"), 1);
65076
+ var path83 = __toESM(require("path"), 1);
64982
65077
  var PKG_NAME = "@clawos-dev/clawd";
64983
65078
  var BIN_NAME = "clawd";
64984
65079
  var MAX_PARENT_HOPS = 5;
64985
65080
  function probeGlobalCli(pathEnv) {
64986
65081
  if (!pathEnv) return null;
64987
- for (const dir of pathEnv.split(path82.delimiter)) {
65082
+ for (const dir of pathEnv.split(path83.delimiter)) {
64988
65083
  if (!dir) continue;
64989
65084
  let real;
64990
65085
  try {
64991
- real = fs73.realpathSync(path82.join(dir, BIN_NAME));
65086
+ real = fs73.realpathSync(path83.join(dir, BIN_NAME));
64992
65087
  } catch {
64993
65088
  continue;
64994
65089
  }
@@ -64998,15 +65093,15 @@ function probeGlobalCli(pathEnv) {
64998
65093
  return null;
64999
65094
  }
65000
65095
  function readOwnPackageVersion(entryPath) {
65001
- let dir = path82.dirname(entryPath);
65096
+ let dir = path83.dirname(entryPath);
65002
65097
  for (let i = 0; i < MAX_PARENT_HOPS; i++) {
65003
65098
  try {
65004
- const raw = fs73.readFileSync(path82.join(dir, "package.json"), "utf8");
65099
+ const raw = fs73.readFileSync(path83.join(dir, "package.json"), "utf8");
65005
65100
  const pkg = JSON.parse(raw);
65006
65101
  if (pkg.name !== PKG_NAME) return null;
65007
65102
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
65008
65103
  } catch {
65009
- const parent = path82.dirname(dir);
65104
+ const parent = path83.dirname(dir);
65010
65105
  if (parent === dir) return null;
65011
65106
  dir = parent;
65012
65107
  }
@@ -65178,7 +65273,7 @@ function buildPersonaHandlers(deps) {
65178
65273
  }
65179
65274
 
65180
65275
  // src/handlers/attachment.ts
65181
- var import_node_path64 = __toESM(require("path"), 1);
65276
+ var import_node_path65 = __toESM(require("path"), 1);
65182
65277
  init_protocol();
65183
65278
  init_protocol();
65184
65279
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -65258,12 +65353,12 @@ function buildAttachmentHandlers(deps) {
65258
65353
  `session ${args.sessionId} scope unresolved`
65259
65354
  );
65260
65355
  }
65261
- const cwdAbs = import_node_path64.default.resolve(sessionFile.cwd);
65262
- const candidateAbs = import_node_path64.default.isAbsolute(args.relPath) ? import_node_path64.default.resolve(args.relPath) : import_node_path64.default.resolve(cwdAbs, args.relPath);
65356
+ const cwdAbs = import_node_path65.default.resolve(sessionFile.cwd);
65357
+ const candidateAbs = import_node_path65.default.isAbsolute(args.relPath) ? import_node_path65.default.resolve(args.relPath) : import_node_path65.default.resolve(cwdAbs, args.relPath);
65263
65358
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
65264
65359
  const entries = deps.groupFileStore.list(scope, args.sessionId);
65265
65360
  const entry = entries.find((e) => {
65266
- const storedAbs = import_node_path64.default.isAbsolute(e.relPath) ? import_node_path64.default.resolve(e.relPath) : import_node_path64.default.resolve(cwdAbs, e.relPath);
65361
+ const storedAbs = import_node_path65.default.isAbsolute(e.relPath) ? import_node_path65.default.resolve(e.relPath) : import_node_path65.default.resolve(cwdAbs, e.relPath);
65267
65362
  return storedAbs === candidateAbs && !e.stale;
65268
65363
  });
65269
65364
  if (!entry) {
@@ -65288,7 +65383,7 @@ function buildAttachmentHandlers(deps) {
65288
65383
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
65289
65384
  const f = deps.sessionStore.read(sessionId);
65290
65385
  if (!f) return;
65291
- assertGuestAttachmentPath(ctx, import_node_path64.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
65386
+ assertGuestAttachmentPath(ctx, import_node_path65.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
65292
65387
  }
65293
65388
  const groupAdd = async (frame, _client, ctx) => {
65294
65389
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -65303,8 +65398,8 @@ function buildAttachmentHandlers(deps) {
65303
65398
  if (!scope) {
65304
65399
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
65305
65400
  }
65306
- const cwdAbs = import_node_path64.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
65307
- const candidateAbs = import_node_path64.default.isAbsolute(args.relPath) ? import_node_path64.default.resolve(args.relPath) : import_node_path64.default.resolve(cwdAbs, args.relPath);
65401
+ const cwdAbs = import_node_path65.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
65402
+ const candidateAbs = import_node_path65.default.isAbsolute(args.relPath) ? import_node_path65.default.resolve(args.relPath) : import_node_path65.default.resolve(cwdAbs, args.relPath);
65308
65403
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
65309
65404
  const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
65310
65405
  const size = 0;
@@ -65363,19 +65458,19 @@ function buildAttachmentHandlers(deps) {
65363
65458
 
65364
65459
  // src/handlers/extension.ts
65365
65460
  var import_promises17 = __toESM(require("fs/promises"), 1);
65366
- var import_node_path69 = __toESM(require("path"), 1);
65461
+ var import_node_path70 = __toESM(require("path"), 1);
65367
65462
  init_protocol();
65368
65463
 
65369
65464
  // src/extension/bundle-zip.ts
65370
65465
  var import_promises14 = __toESM(require("fs/promises"), 1);
65371
- var import_node_path65 = __toESM(require("path"), 1);
65466
+ var import_node_path66 = __toESM(require("path"), 1);
65372
65467
  var import_node_crypto18 = __toESM(require("crypto"), 1);
65373
65468
  var import_jszip2 = __toESM(require_lib3(), 1);
65374
65469
  async function bundleExtensionDir(dir) {
65375
65470
  const entries = await listFilesSorted(dir);
65376
65471
  const zip = new import_jszip2.default();
65377
65472
  for (const rel of entries) {
65378
- const abs = import_node_path65.default.join(dir, rel);
65473
+ const abs = import_node_path66.default.join(dir, rel);
65379
65474
  const content = await import_promises14.default.readFile(abs);
65380
65475
  zip.file(rel, content, { date: FIXED_DATE });
65381
65476
  }
@@ -65396,7 +65491,7 @@ async function listFilesSorted(rootDir) {
65396
65491
  return out;
65397
65492
  }
65398
65493
  async function walk(absRoot, relPrefix, out) {
65399
- const dirAbs = import_node_path65.default.join(absRoot, relPrefix);
65494
+ const dirAbs = import_node_path66.default.join(absRoot, relPrefix);
65400
65495
  const entries = await import_promises14.default.readdir(dirAbs, { withFileTypes: true });
65401
65496
  for (const e of entries) {
65402
65497
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -65450,25 +65545,25 @@ function computePublishCheck(args) {
65450
65545
 
65451
65546
  // src/extension/install-flow.ts
65452
65547
  var import_promises15 = __toESM(require("fs/promises"), 1);
65453
- var import_node_path67 = __toESM(require("path"), 1);
65548
+ var import_node_path68 = __toESM(require("path"), 1);
65454
65549
  var import_node_os24 = __toESM(require("os"), 1);
65455
65550
  var import_node_crypto19 = __toESM(require("crypto"), 1);
65456
65551
  var import_jszip3 = __toESM(require_lib3(), 1);
65457
65552
 
65458
65553
  // src/extension/paths.ts
65459
65554
  var import_node_os23 = __toESM(require("os"), 1);
65460
- var import_node_path66 = __toESM(require("path"), 1);
65555
+ var import_node_path67 = __toESM(require("path"), 1);
65461
65556
  function clawdHomeRoot(override) {
65462
- return override ?? process.env.CLAWD_HOME ?? import_node_path66.default.join(import_node_os23.default.homedir(), ".clawd");
65557
+ return override ?? process.env.CLAWD_HOME ?? import_node_path67.default.join(import_node_os23.default.homedir(), ".clawd");
65463
65558
  }
65464
65559
  function extensionsRoot(override) {
65465
- return import_node_path66.default.join(clawdHomeRoot(override), "extensions");
65560
+ return import_node_path67.default.join(clawdHomeRoot(override), "extensions");
65466
65561
  }
65467
65562
  function publishedChannelsFile(override) {
65468
- return import_node_path66.default.join(clawdHomeRoot(override), "extensions-published.json");
65563
+ return import_node_path67.default.join(clawdHomeRoot(override), "extensions-published.json");
65469
65564
  }
65470
65565
  function bundleCacheRoot(override) {
65471
- return import_node_path66.default.join(clawdHomeRoot(override), "extension-bundles");
65566
+ return import_node_path67.default.join(clawdHomeRoot(override), "extension-bundles");
65472
65567
  }
65473
65568
 
65474
65569
  // src/extension/install-flow.ts
@@ -65495,7 +65590,7 @@ async function installFromChannel(args, deps) {
65495
65590
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
65496
65591
  }
65497
65592
  for (const name of Object.keys(zip.files)) {
65498
- if (name.includes("..") || name.startsWith("/") || import_node_path67.default.isAbsolute(name)) {
65593
+ if (name.includes("..") || name.startsWith("/") || import_node_path68.default.isAbsolute(name)) {
65499
65594
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
65500
65595
  }
65501
65596
  }
@@ -65527,7 +65622,7 @@ async function installFromChannel(args, deps) {
65527
65622
  );
65528
65623
  }
65529
65624
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
65530
- const destDir = import_node_path67.default.join(deps.extensionsRoot, localExtId);
65625
+ const destDir = import_node_path68.default.join(deps.extensionsRoot, localExtId);
65531
65626
  let destExists = false;
65532
65627
  try {
65533
65628
  await import_promises15.default.access(destDir);
@@ -65541,16 +65636,16 @@ async function installFromChannel(args, deps) {
65541
65636
  );
65542
65637
  }
65543
65638
  const stage = await import_promises15.default.mkdtemp(
65544
- import_node_path67.default.join(import_node_os24.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
65639
+ import_node_path68.default.join(import_node_os24.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
65545
65640
  );
65546
65641
  try {
65547
65642
  for (const [name, entry] of Object.entries(zip.files)) {
65548
- const dest = import_node_path67.default.join(stage, name);
65643
+ const dest = import_node_path68.default.join(stage, name);
65549
65644
  if (entry.dir) {
65550
65645
  await import_promises15.default.mkdir(dest, { recursive: true });
65551
65646
  continue;
65552
65647
  }
65553
- await import_promises15.default.mkdir(import_node_path67.default.dirname(dest), { recursive: true });
65648
+ await import_promises15.default.mkdir(import_node_path68.default.dirname(dest), { recursive: true });
65554
65649
  if (name === "manifest.json") {
65555
65650
  const rewritten = { ...parsed.data, id: localExtId };
65556
65651
  await import_promises15.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -65571,7 +65666,7 @@ async function installFromChannel(args, deps) {
65571
65666
 
65572
65667
  // src/extension/update-flow.ts
65573
65668
  var import_promises16 = __toESM(require("fs/promises"), 1);
65574
- var import_node_path68 = __toESM(require("path"), 1);
65669
+ var import_node_path69 = __toESM(require("path"), 1);
65575
65670
  var import_node_os25 = __toESM(require("os"), 1);
65576
65671
  var import_node_crypto20 = __toESM(require("crypto"), 1);
65577
65672
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -65588,11 +65683,11 @@ async function updateFromChannel(args, deps) {
65588
65683
  channelRef.extId,
65589
65684
  channelRef.ownerPrincipalId
65590
65685
  );
65591
- const liveDir = import_node_path68.default.join(deps.extensionsRoot, localExtId);
65686
+ const liveDir = import_node_path69.default.join(deps.extensionsRoot, localExtId);
65592
65687
  const prevDir = `${liveDir}.prev`;
65593
65688
  let existingVersion;
65594
65689
  try {
65595
- const raw = await import_promises16.default.readFile(import_node_path68.default.join(liveDir, "manifest.json"), "utf8");
65690
+ const raw = await import_promises16.default.readFile(import_node_path69.default.join(liveDir, "manifest.json"), "utf8");
65596
65691
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
65597
65692
  if (!parsed2.success) {
65598
65693
  throw new UpdateError(
@@ -65625,7 +65720,7 @@ async function updateFromChannel(args, deps) {
65625
65720
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
65626
65721
  }
65627
65722
  for (const name of Object.keys(zip.files)) {
65628
- if (name.includes("..") || name.startsWith("/") || import_node_path68.default.isAbsolute(name)) {
65723
+ if (name.includes("..") || name.startsWith("/") || import_node_path69.default.isAbsolute(name)) {
65629
65724
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
65630
65725
  }
65631
65726
  }
@@ -65660,16 +65755,16 @@ async function updateFromChannel(args, deps) {
65660
65755
  await import_promises16.default.rm(prevDir, { recursive: true, force: true });
65661
65756
  await import_promises16.default.rename(liveDir, prevDir);
65662
65757
  const stage = await import_promises16.default.mkdtemp(
65663
- import_node_path68.default.join(import_node_os25.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
65758
+ import_node_path69.default.join(import_node_os25.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
65664
65759
  );
65665
65760
  try {
65666
65761
  for (const [name, entry] of Object.entries(zip.files)) {
65667
- const dest = import_node_path68.default.join(stage, name);
65762
+ const dest = import_node_path69.default.join(stage, name);
65668
65763
  if (entry.dir) {
65669
65764
  await import_promises16.default.mkdir(dest, { recursive: true });
65670
65765
  continue;
65671
65766
  }
65672
- await import_promises16.default.mkdir(import_node_path68.default.dirname(dest), { recursive: true });
65767
+ await import_promises16.default.mkdir(import_node_path69.default.dirname(dest), { recursive: true });
65673
65768
  if (name === "manifest.json") {
65674
65769
  const rewritten = { ...parsed.data, id: localExtId };
65675
65770
  await import_promises16.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -65736,7 +65831,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
65736
65831
  );
65737
65832
  }
65738
65833
  }
65739
- const manifestPath = import_node_path69.default.join(root, extId, "manifest.json");
65834
+ const manifestPath = import_node_path70.default.join(root, extId, "manifest.json");
65740
65835
  const manifest = await readManifest(root, extId);
65741
65836
  const next = { ...manifest, version: newVersion };
65742
65837
  const tmp = `${manifestPath}.tmp`;
@@ -65744,7 +65839,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
65744
65839
  await import_promises17.default.rename(tmp, manifestPath);
65745
65840
  }
65746
65841
  async function readManifest(root, extId) {
65747
- const file = import_node_path69.default.join(root, extId, "manifest.json");
65842
+ const file = import_node_path70.default.join(root, extId, "manifest.json");
65748
65843
  let raw;
65749
65844
  try {
65750
65845
  raw = await import_promises17.default.readFile(file, "utf8");
@@ -65828,7 +65923,7 @@ function buildExtensionHandlers(deps) {
65828
65923
  };
65829
65924
  async function buildSnapshotMeta(extId) {
65830
65925
  const manifest = await readManifest(deps.root, extId);
65831
- const { sha256, buffer } = await bundleExtensionDir(import_node_path69.default.join(deps.root, extId));
65926
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path70.default.join(deps.root, extId));
65832
65927
  return { manifest, contentHash: sha256, buffer };
65833
65928
  }
65834
65929
  const publish = async (frame, _client, ctx) => {
@@ -66071,7 +66166,7 @@ var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
66071
66166
 
66072
66167
  // src/handlers/app-builder.ts
66073
66168
  init_protocol();
66074
- var import_node_path70 = require("path");
66169
+ var import_node_path71 = require("path");
66075
66170
  var import_node_fs52 = require("fs");
66076
66171
  var DEFAULT_TEMPLATE = "nestjs-react";
66077
66172
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
@@ -66218,13 +66313,13 @@ function buildAppBuilderHandlers(deps) {
66218
66313
  const created = await deps.createProjectOnDisk({
66219
66314
  store: userStore,
66220
66315
  name: f.name,
66221
- templateSrcDir: (0, import_node_path70.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE),
66222
- scaffoldScript: (0, import_node_path70.join)(deps.deployKitRoot, "scripts", "new-extension.sh"),
66316
+ templateSrcDir: (0, import_node_path71.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE),
66317
+ scaffoldScript: (0, import_node_path71.join)(deps.deployKitRoot, "scripts", "new-extension.sh"),
66223
66318
  reservedPorts,
66224
66319
  // 凭据只进 scaffold 子进程的 env,且**只给这个 persona 的 kit 模板声明要的那几个变量**
66225
66320
  // (M1b Step 5)。整表塞进去粒度只到「进程」——那会把 service-role key 交给一个用不到
66226
66321
  // 它的脚本。new-extension.sh 用它把模板的 `${VAR}` 渲成项目可跑的 server/.env。
66227
- extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path70.join)(personaRoot, "extension-kit")),
66322
+ extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path71.join)(personaRoot, "extension-kit")),
66228
66323
  ...deps.logger ? { logger: deps.logger } : {}
66229
66324
  });
66230
66325
  project = created.project;
@@ -66423,7 +66518,7 @@ function buildAppBuilderHandlers(deps) {
66423
66518
  await userStore.clearPublishJob(args.name);
66424
66519
  }
66425
66520
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
66426
- const scriptPath = (0, import_node_path70.join)(deps.deployKitRoot, "scripts", "publish.sh");
66521
+ const scriptPath = (0, import_node_path71.join)(deps.deployKitRoot, "scripts", "publish.sh");
66427
66522
  deps.logger?.info("app-builder.publish.start", {
66428
66523
  name: args.name,
66429
66524
  sessionId: boundSession.sessionId,
@@ -66439,7 +66534,7 @@ function buildAppBuilderHandlers(deps) {
66439
66534
  // 凭据只进 publish.sh 这个子进程的 env,且只给它的 kit 模板声明要的那几个变量
66440
66535
  // (M1b Step 5)。那个进程里跑着 `eval "$BUILD_CMD"`——项目自带的构建命令会继承这份
66441
66536
  // env,多给一个变量就是多交一个凭据给它。personaRoot 上面已按绑定 session 的 persona 解析。
66442
- extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path70.join)(personaRoot, "extension-kit")),
66537
+ extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path71.join)(personaRoot, "extension-kit")),
66443
66538
  hooks: {
66444
66539
  // 元数据每次写盘(publishJob 起落 / prodUrl 回填)后重推一帧:UI 渲染 PublishProgress
66445
66540
  // 三段 checklist 依赖 project.publishJob.status==='in-flight',而 publishJob 字段只有
@@ -67175,7 +67270,7 @@ function buildVisitorHandlers(deps) {
67175
67270
 
67176
67271
  // src/extension/registry.ts
67177
67272
  var import_promises19 = __toESM(require("fs/promises"), 1);
67178
- var import_node_path71 = __toESM(require("path"), 1);
67273
+ var import_node_path72 = __toESM(require("path"), 1);
67179
67274
  async function loadAll(root) {
67180
67275
  let entries;
67181
67276
  try {
@@ -67188,13 +67283,13 @@ async function loadAll(root) {
67188
67283
  for (const ent of entries) {
67189
67284
  if (!ent.isDirectory()) continue;
67190
67285
  if (ent.name.startsWith(".")) continue;
67191
- records.push(await loadOne(import_node_path71.default.join(root, ent.name), ent.name));
67286
+ records.push(await loadOne(import_node_path72.default.join(root, ent.name), ent.name));
67192
67287
  }
67193
67288
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
67194
67289
  return records;
67195
67290
  }
67196
67291
  async function loadOne(dir, dirName) {
67197
- const manifestPath = import_node_path71.default.join(dir, "manifest.json");
67292
+ const manifestPath = import_node_path72.default.join(dir, "manifest.json");
67198
67293
  let raw;
67199
67294
  try {
67200
67295
  raw = await import_promises19.default.readFile(manifestPath, "utf8");
@@ -67239,7 +67334,7 @@ async function loadOne(dir, dirName) {
67239
67334
 
67240
67335
  // src/extension/uninstall.ts
67241
67336
  var import_promises20 = __toESM(require("fs/promises"), 1);
67242
- var import_node_path72 = __toESM(require("path"), 1);
67337
+ var import_node_path73 = __toESM(require("path"), 1);
67243
67338
  var UninstallError = class extends Error {
67244
67339
  constructor(code, message) {
67245
67340
  super(message);
@@ -67248,7 +67343,7 @@ var UninstallError = class extends Error {
67248
67343
  code;
67249
67344
  };
67250
67345
  async function uninstall(deps) {
67251
- const dir = import_node_path72.default.join(deps.root, deps.extId);
67346
+ const dir = import_node_path73.default.join(deps.root, deps.extId);
67252
67347
  try {
67253
67348
  await import_promises20.default.access(dir);
67254
67349
  } catch {
@@ -67484,7 +67579,7 @@ function buildMethodHandlers(deps) {
67484
67579
  broadcast: deps.broadcastToOwners
67485
67580
  }),
67486
67581
  ...buildMasterHandlers({
67487
- authorityTablePath: import_node_path73.default.join(deps.masterDataDir, "master-authority.json")
67582
+ authorityTablePath: import_node_path74.default.join(deps.masterDataDir, "master-authority.json")
67488
67583
  }),
67489
67584
  ...buildTopicHandlers({
67490
67585
  topicStore: deps.topicStore,
@@ -67530,8 +67625,8 @@ function refreshPathFromLoginShell() {
67530
67625
  timeout: 3e3,
67531
67626
  stdio: ["ignore", "pipe", "ignore"]
67532
67627
  });
67533
- const path99 = out.trim();
67534
- if (path99) process.env.PATH = path99;
67628
+ const path100 = out.trim();
67629
+ if (path100) process.env.PATH = path100;
67535
67630
  } catch {
67536
67631
  }
67537
67632
  }
@@ -67657,7 +67752,7 @@ function buildOnboardingHandlers(deps) {
67657
67752
  // src/app-builder-plugin/project-store.ts
67658
67753
  var import_node_fs53 = require("fs");
67659
67754
  var import_node_child_process21 = require("child_process");
67660
- var import_node_path74 = require("path");
67755
+ var import_node_path75 = require("path");
67661
67756
  init_protocol();
67662
67757
  var PROJECTS_DIR = "projects";
67663
67758
  var META_FILE = ".clawd-project.json";
@@ -67687,14 +67782,14 @@ var ProjectStore = class {
67687
67782
  }
67688
67783
  /** projects/<name>/.clawd-project.json 路径 */
67689
67784
  metaPath(name) {
67690
- return (0, import_node_path74.join)(this.projectsRoot(), name, META_FILE);
67785
+ return (0, import_node_path75.join)(this.projectsRoot(), name, META_FILE);
67691
67786
  }
67692
67787
  /** projects/<name>/ 目录路径(cwd 用) */
67693
67788
  projectDir(name) {
67694
- return (0, import_node_path74.join)(this.projectsRoot(), name);
67789
+ return (0, import_node_path75.join)(this.projectsRoot(), name);
67695
67790
  }
67696
67791
  projectsRoot() {
67697
- return (0, import_node_path74.join)(this.root, PROJECTS_DIR);
67792
+ return (0, import_node_path75.join)(this.root, PROJECTS_DIR);
67698
67793
  }
67699
67794
  async list() {
67700
67795
  let entries;
@@ -68200,7 +68295,7 @@ var PublishJobRegistry = class {
68200
68295
  // src/app-builder-plugin/publish-job-runner.ts
68201
68296
  var import_node_child_process23 = require("child_process");
68202
68297
  var import_node_fs54 = require("fs");
68203
- var import_node_path75 = require("path");
68298
+ var import_node_path76 = require("path");
68204
68299
 
68205
68300
  // src/app-builder-plugin/publish-stage-parser.ts
68206
68301
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -68232,7 +68327,7 @@ async function startPublishJob(deps, args) {
68232
68327
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
68233
68328
  }
68234
68329
  const projDir = projectDir(args.name);
68235
- const logPath = (0, import_node_path75.join)(projDir, ".publish.log");
68330
+ const logPath = (0, import_node_path76.join)(projDir, ".publish.log");
68236
68331
  let logStream = null;
68237
68332
  try {
68238
68333
  logStream = (0, import_node_fs54.createWriteStream)(logPath, { flags: "w" });
@@ -68579,9 +68674,9 @@ async function recoverInterruptedPublishJobs(store, logger) {
68579
68674
 
68580
68675
  // src/app-builder-plugin/mcp-config.ts
68581
68676
  var import_node_fs55 = __toESM(require("fs"), 1);
68582
- var import_node_path76 = __toESM(require("path"), 1);
68677
+ var import_node_path77 = __toESM(require("path"), 1);
68583
68678
  function appBuilderMcpConfigPath(dataDir) {
68584
- return import_node_path76.default.join(dataDir, "app-builder.mcp.json");
68679
+ return import_node_path77.default.join(dataDir, "app-builder.mcp.json");
68585
68680
  }
68586
68681
  function writeAppBuilderMcpConfig(args) {
68587
68682
  const cfgPath = appBuilderMcpConfigPath(args.dataDir);
@@ -68595,8 +68690,8 @@ function writeAppBuilderMcpConfig(args) {
68595
68690
  env: {
68596
68691
  CLAWD_DAEMON_TOKEN: args.daemonToken,
68597
68692
  CLAWD_DAEMON_URL: args.daemonUrl,
68598
- CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT: import_node_path76.default.join(args.deployKitScriptsDir, "new-extension.sh"),
68599
- CLAWD_APP_BUILDER_PUBLISH_SCRIPT: import_node_path76.default.join(args.deployKitScriptsDir, "publish.sh"),
68693
+ CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT: import_node_path77.default.join(args.deployKitScriptsDir, "new-extension.sh"),
68694
+ CLAWD_APP_BUILDER_PUBLISH_SCRIPT: import_node_path77.default.join(args.deployKitScriptsDir, "publish.sh"),
68600
68695
  ...args.logPath ? { CLAWD_APP_BUILDER_LOG: args.logPath } : {}
68601
68696
  }
68602
68697
  }
@@ -68644,7 +68739,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
68644
68739
 
68645
68740
  // src/extension/runtime.ts
68646
68741
  var import_node_child_process25 = require("child_process");
68647
- var import_node_path77 = __toESM(require("path"), 1);
68742
+ var import_node_path78 = __toESM(require("path"), 1);
68648
68743
  var import_promises21 = require("timers/promises");
68649
68744
 
68650
68745
  // src/extension/port-allocator.ts
@@ -68745,7 +68840,7 @@ var Runtime = class {
68745
68840
  /\$CLAWOS_EXT_PORT/g,
68746
68841
  String(port)
68747
68842
  );
68748
- const dir = import_node_path77.default.join(this.root, extId);
68843
+ const dir = import_node_path78.default.join(this.root, extId);
68749
68844
  const env = {
68750
68845
  ...process.env,
68751
68846
  CLAWOS_EXT_PORT: String(port),
@@ -68857,7 +68952,7 @@ ${handle.stderrTail}`
68857
68952
 
68858
68953
  // src/extension/published-channels.ts
68859
68954
  var import_promises22 = __toESM(require("fs/promises"), 1);
68860
- var import_node_path78 = __toESM(require("path"), 1);
68955
+ var import_node_path79 = __toESM(require("path"), 1);
68861
68956
  init_zod();
68862
68957
  var PublishedChannelsError = class extends Error {
68863
68958
  constructor(code, message) {
@@ -68956,7 +69051,7 @@ var PublishedChannelStore = class {
68956
69051
  )
68957
69052
  };
68958
69053
  const tmp = `${this.filePath}.tmp`;
68959
- await import_promises22.default.mkdir(import_node_path78.default.dirname(this.filePath), { recursive: true });
69054
+ await import_promises22.default.mkdir(import_node_path79.default.dirname(this.filePath), { recursive: true });
68960
69055
  await import_promises22.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
68961
69056
  await import_promises22.default.rename(tmp, this.filePath);
68962
69057
  }
@@ -68964,7 +69059,7 @@ var PublishedChannelStore = class {
68964
69059
 
68965
69060
  // src/extension/bundle-cache.ts
68966
69061
  var import_promises23 = __toESM(require("fs/promises"), 1);
68967
- var import_node_path79 = __toESM(require("path"), 1);
69062
+ var import_node_path80 = __toESM(require("path"), 1);
68968
69063
  var BundleCache = class {
68969
69064
  constructor(rootDir) {
68970
69065
  this.rootDir = rootDir;
@@ -68973,14 +69068,14 @@ var BundleCache = class {
68973
69068
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
68974
69069
  async write(snapshotHash, buffer) {
68975
69070
  await import_promises23.default.mkdir(this.rootDir, { recursive: true });
68976
- const file = import_node_path79.default.join(this.rootDir, `${snapshotHash}.zip`);
69071
+ const file = import_node_path80.default.join(this.rootDir, `${snapshotHash}.zip`);
68977
69072
  const tmp = `${file}.tmp`;
68978
69073
  await import_promises23.default.writeFile(tmp, buffer, { mode: 384 });
68979
69074
  await import_promises23.default.rename(tmp, file);
68980
69075
  }
68981
69076
  /** Returns the bundle bytes, or null when the file doesn't exist. */
68982
69077
  async read(snapshotHash) {
68983
- const file = import_node_path79.default.join(this.rootDir, `${snapshotHash}.zip`);
69078
+ const file = import_node_path80.default.join(this.rootDir, `${snapshotHash}.zip`);
68984
69079
  try {
68985
69080
  return await import_promises23.default.readFile(file);
68986
69081
  } catch (e) {
@@ -68990,7 +69085,7 @@ var BundleCache = class {
68990
69085
  }
68991
69086
  /** Idempotent — missing file is not an error. */
68992
69087
  async delete(snapshotHash) {
68993
- const file = import_node_path79.default.join(this.rootDir, `${snapshotHash}.zip`);
69088
+ const file = import_node_path80.default.join(this.rootDir, `${snapshotHash}.zip`);
68994
69089
  await import_promises23.default.rm(file, { force: true });
68995
69090
  }
68996
69091
  };
@@ -69013,24 +69108,24 @@ async function startDaemon(config) {
69013
69108
  sampling: logShippingCfg.sampling,
69014
69109
  homeDir: import_node_os28.default.homedir()
69015
69110
  });
69016
- const logDir = import_node_path80.default.join(config.dataDir, "log");
69111
+ const logDir = import_node_path81.default.join(config.dataDir, "log");
69017
69112
  import_node_fs56.default.mkdirSync(logDir, { recursive: true });
69018
69113
  const logger = createLogger({
69019
69114
  level: config.logLevel,
69020
- file: import_node_path80.default.join(logDir, "clawd.log"),
69115
+ file: import_node_path81.default.join(logDir, "clawd.log"),
69021
69116
  logClient
69022
69117
  });
69023
69118
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
69024
69119
  const screenIdleProbeLogger = createFileOnlyLogger({
69025
- file: import_node_path80.default.join(logDir, "screen-idle-probe.log"),
69120
+ file: import_node_path81.default.join(logDir, "screen-idle-probe.log"),
69026
69121
  level: "debug"
69027
69122
  });
69028
69123
  logger.info("screen-idle probe logger enabled", {
69029
- file: import_node_path80.default.join(logDir, "screen-idle-probe.log")
69124
+ file: import_node_path81.default.join(logDir, "screen-idle-probe.log")
69030
69125
  });
69031
69126
  const CAP_TARGETS = [
69032
- import_node_path80.default.join(logDir, "clawd.log"),
69033
- import_node_path80.default.join(logDir, "screen-idle-probe.log")
69127
+ import_node_path81.default.join(logDir, "clawd.log"),
69128
+ import_node_path81.default.join(logDir, "screen-idle-probe.log")
69034
69129
  ];
69035
69130
  const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
69036
69131
  const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
@@ -69152,8 +69247,8 @@ async function startDaemon(config) {
69152
69247
  const agents = new AgentsScanner();
69153
69248
  const history = new ClaudeHistoryReader();
69154
69249
  let transport = null;
69155
- const personaStore = new PersonaStore(import_node_path80.default.join(config.dataDir, "personas"));
69156
- const usersRoot = import_node_path80.default.join(config.dataDir, "users");
69250
+ const personaStore = new PersonaStore(import_node_path81.default.join(config.dataDir, "personas"));
69251
+ const usersRoot = import_node_path81.default.join(config.dataDir, "users");
69157
69252
  const defaultsRoot = findDefaultsRoot(logger);
69158
69253
  if (defaultsRoot) {
69159
69254
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -69177,7 +69272,7 @@ async function startDaemon(config) {
69177
69272
  retirePersonaBuilder({ store: personaStore, logger });
69178
69273
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
69179
69274
  const dispatchStore = createDispatchStore({
69180
- filePath: import_node_path80.default.join(config.dataDir, "dispatch.json"),
69275
+ filePath: import_node_path81.default.join(config.dataDir, "dispatch.json"),
69181
69276
  now: () => Date.now(),
69182
69277
  onFlushError: (err) => logger.error("dispatch store flush failed", {
69183
69278
  reason: err instanceof Error ? err.message : String(err)
@@ -69186,7 +69281,7 @@ async function startDaemon(config) {
69186
69281
  await dispatchStore.load();
69187
69282
  dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
69188
69283
  const channelStore = createChannelStore({
69189
- filePath: import_node_path80.default.join(config.dataDir, "channels.json"),
69284
+ filePath: import_node_path81.default.join(config.dataDir, "channels.json"),
69190
69285
  now: () => Date.now(),
69191
69286
  genId: () => `ch-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
69192
69287
  onFlushError: (err) => logger.error("channel store flush failed", {
@@ -69195,7 +69290,7 @@ async function startDaemon(config) {
69195
69290
  });
69196
69291
  await channelStore.load();
69197
69292
  const topicStore = createTopicStore({
69198
- filePath: import_node_path80.default.join(config.dataDir, "topics.json"),
69293
+ filePath: import_node_path81.default.join(config.dataDir, "topics.json"),
69199
69294
  now: () => Date.now(),
69200
69295
  genId: () => `tp-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
69201
69296
  onFlushError: (err) => logger.error("topic store flush failed", {
@@ -69222,28 +69317,28 @@ async function startDaemon(config) {
69222
69317
  });
69223
69318
  }
69224
69319
  });
69225
- const here = typeof __dirname === "string" ? __dirname : import_node_path80.default.dirname((0, import_node_url5.fileURLToPath)(import_meta8.url));
69320
+ const here = typeof __dirname === "string" ? __dirname : import_node_path81.default.dirname((0, import_node_url5.fileURLToPath)(import_meta8.url));
69226
69321
  const mcpConfigs = [];
69227
69322
  const secretsBundleRoot = findSecretsBundleRoot(logger);
69228
- const localSecretsDir = import_node_path80.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
69323
+ const localSecretsDir = import_node_path81.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
69229
69324
  const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
69230
69325
  const resolvePersonaMcpConfig = (personaId2) => renderPersonaMcpSecrets({
69231
69326
  personaId: personaId2,
69232
- personaDir: import_node_path80.default.join(config.dataDir, "personas", personaId2),
69327
+ personaDir: import_node_path81.default.join(config.dataDir, "personas", personaId2),
69233
69328
  secrets: readSecrets(),
69234
- outDir: import_node_path80.default.join(config.dataDir, "persona-mcp"),
69329
+ outDir: import_node_path81.default.join(config.dataDir, "persona-mcp"),
69235
69330
  logger
69236
69331
  });
69237
69332
  const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
69238
69333
  const dispatchServerCandidates = [
69239
- import_node_path80.default.join(here, "dispatch", "mcp-server.cjs"),
69334
+ import_node_path81.default.join(here, "dispatch", "mcp-server.cjs"),
69240
69335
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
69241
- import_node_path80.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
69336
+ import_node_path81.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
69242
69337
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
69243
69338
  ];
69244
69339
  const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69245
69340
  if (dispatchServerScriptPath) {
69246
- const dispatchLogPath = import_node_path80.default.join(logDir, "dispatch-mcp-server.log");
69341
+ const dispatchLogPath = import_node_path81.default.join(logDir, "dispatch-mcp-server.log");
69247
69342
  const dispatchCfgPath = writeDispatchMcpConfig({
69248
69343
  dataDir: config.dataDir,
69249
69344
  serverScriptPath: dispatchServerScriptPath,
@@ -69263,12 +69358,12 @@ async function startDaemon(config) {
69263
69358
  });
69264
69359
  }
69265
69360
  const ticketServerCandidates = [
69266
- import_node_path80.default.join(here, "ticket", "mcp-server.cjs"),
69267
- import_node_path80.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
69361
+ import_node_path81.default.join(here, "ticket", "mcp-server.cjs"),
69362
+ import_node_path81.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
69268
69363
  ];
69269
69364
  const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69270
69365
  if (ticketServerScriptPath) {
69271
- const ticketLogPath = import_node_path80.default.join(logDir, "ticket-mcp-server.log");
69366
+ const ticketLogPath = import_node_path81.default.join(logDir, "ticket-mcp-server.log");
69272
69367
  const ticketCfgPath = writeTicketMcpConfig({
69273
69368
  dataDir: config.dataDir,
69274
69369
  serverScriptPath: ticketServerScriptPath,
@@ -69290,12 +69385,12 @@ async function startDaemon(config) {
69290
69385
  });
69291
69386
  }
69292
69387
  const shiftServerCandidates = [
69293
- import_node_path80.default.join(here, "shift", "mcp-server.cjs"),
69294
- import_node_path80.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
69388
+ import_node_path81.default.join(here, "shift", "mcp-server.cjs"),
69389
+ import_node_path81.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
69295
69390
  ];
69296
69391
  const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69297
69392
  if (shiftServerScriptPath) {
69298
- const shiftLogPath = import_node_path80.default.join(logDir, "shift-mcp-server.log");
69393
+ const shiftLogPath = import_node_path81.default.join(logDir, "shift-mcp-server.log");
69299
69394
  const shiftCfgPath = await writeShiftMcpConfig({
69300
69395
  dataDir: config.dataDir,
69301
69396
  serverScriptPath: shiftServerScriptPath,
@@ -69316,12 +69411,12 @@ async function startDaemon(config) {
69316
69411
  );
69317
69412
  }
69318
69413
  const inboxServerCandidates = [
69319
- import_node_path80.default.join(here, "inbox", "mcp-server.cjs"),
69320
- import_node_path80.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
69414
+ import_node_path81.default.join(here, "inbox", "mcp-server.cjs"),
69415
+ import_node_path81.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
69321
69416
  ];
69322
69417
  const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69323
69418
  if (inboxServerScriptPath) {
69324
- const inboxLogPath = import_node_path80.default.join(logDir, "inbox-mcp-server.log");
69419
+ const inboxLogPath = import_node_path81.default.join(logDir, "inbox-mcp-server.log");
69325
69420
  const inboxCfgPath = await writeInboxMcpConfig({
69326
69421
  dataDir: config.dataDir,
69327
69422
  serverScriptPath: inboxServerScriptPath,
@@ -69342,8 +69437,8 @@ async function startDaemon(config) {
69342
69437
  );
69343
69438
  }
69344
69439
  const peerOpsServerCandidates = [
69345
- import_node_path80.default.join(here, "peer-ops", "mcp-server.cjs"),
69346
- import_node_path80.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
69440
+ import_node_path81.default.join(here, "peer-ops", "mcp-server.cjs"),
69441
+ import_node_path81.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
69347
69442
  ];
69348
69443
  const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69349
69444
  if (peerOpsServerScriptPath) {
@@ -69365,12 +69460,12 @@ async function startDaemon(config) {
69365
69460
  );
69366
69461
  }
69367
69462
  const rpcToolServerCandidates = [
69368
- import_node_path80.default.join(here, "rpc-tool", "mcp-server.cjs"),
69369
- import_node_path80.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
69463
+ import_node_path81.default.join(here, "rpc-tool", "mcp-server.cjs"),
69464
+ import_node_path81.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
69370
69465
  ];
69371
69466
  const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69372
69467
  if (rpcToolServerScriptPath) {
69373
- const rpcToolLogPath = import_node_path80.default.join(logDir, "rpc-tool-mcp-server.log");
69468
+ const rpcToolLogPath = import_node_path81.default.join(logDir, "rpc-tool-mcp-server.log");
69374
69469
  const rpcToolCfgPath = writeRpcToolMcpConfig({
69375
69470
  dataDir: config.dataDir,
69376
69471
  serverScriptPath: rpcToolServerScriptPath,
@@ -69391,18 +69486,18 @@ async function startDaemon(config) {
69391
69486
  );
69392
69487
  }
69393
69488
  const appBuilderServerCandidates = [
69394
- import_node_path80.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
69395
- import_node_path80.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
69489
+ import_node_path81.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
69490
+ import_node_path81.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
69396
69491
  ];
69397
69492
  const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
69398
69493
  if (appBuilderServerScriptPath) {
69399
- const appBuilderLogPath = import_node_path80.default.join(logDir, "app-builder-mcp-server.log");
69494
+ const appBuilderLogPath = import_node_path81.default.join(logDir, "app-builder-mcp-server.log");
69400
69495
  const appBuilderCfgPath = writeAppBuilderMcpConfig({
69401
69496
  dataDir: config.dataDir,
69402
69497
  serverScriptPath: appBuilderServerScriptPath,
69403
69498
  daemonToken: resolvedAuthToken,
69404
69499
  daemonUrl: mcpDaemonUrl,
69405
- deployKitScriptsDir: import_node_path80.default.join(config.dataDir, "deploy-kit", "scripts"),
69500
+ deployKitScriptsDir: import_node_path81.default.join(config.dataDir, "deploy-kit", "scripts"),
69406
69501
  logPath: appBuilderLogPath
69407
69502
  });
69408
69503
  mcpConfigs.push({ id: "app-builder", path: appBuilderCfgPath, personas: APP_BUILDER_PERSONAS });
@@ -69418,7 +69513,7 @@ async function startDaemon(config) {
69418
69513
  );
69419
69514
  }
69420
69515
  const shiftStore = createShiftStore({
69421
- filePath: import_node_path80.default.join(config.dataDir, "shift.json"),
69516
+ filePath: import_node_path81.default.join(config.dataDir, "shift.json"),
69422
69517
  ownerIdProvider: () => ownerPrincipalId,
69423
69518
  now: () => Date.now()
69424
69519
  });
@@ -69440,7 +69535,7 @@ async function startDaemon(config) {
69440
69535
  getAdapter,
69441
69536
  historyReader: history,
69442
69537
  dataDir: config.dataDir,
69443
- personaRoot: import_node_path80.default.join(config.dataDir, "personas"),
69538
+ personaRoot: import_node_path81.default.join(config.dataDir, "personas"),
69444
69539
  // dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
69445
69540
  // personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
69446
69541
  getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
@@ -69497,7 +69592,7 @@ async function startDaemon(config) {
69497
69592
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
69498
69593
  attachmentGroup: {
69499
69594
  onFileEdit: (input) => {
69500
- const absPath = import_node_path80.default.isAbsolute(input.relPath) ? input.relPath : import_node_path80.default.join(input.cwd, input.relPath);
69595
+ const absPath = import_node_path81.default.isAbsolute(input.relPath) ? input.relPath : import_node_path81.default.join(input.cwd, input.relPath);
69501
69596
  let size = 0;
69502
69597
  try {
69503
69598
  size = import_node_fs56.default.statSync(absPath).size;
@@ -69530,9 +69625,9 @@ async function startDaemon(config) {
69530
69625
  logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
69531
69626
  }
69532
69627
  const projectsStore = new ProjectsStore({
69533
- file: import_node_path80.default.join(config.dataDir, "projects.json"),
69628
+ file: import_node_path81.default.join(config.dataDir, "projects.json"),
69534
69629
  clawdDir: config.dataDir,
69535
- codexStateFile: import_node_path80.default.join(import_node_os28.default.homedir(), ".codex", ".codex-global-state.json"),
69630
+ codexStateFile: import_node_path81.default.join(import_node_os28.default.homedir(), ".codex", ".codex-global-state.json"),
69536
69631
  logger
69537
69632
  });
69538
69633
  const observer = new SessionObserver({
@@ -69592,12 +69687,12 @@ async function startDaemon(config) {
69592
69687
  screenIdleProbeLogger
69593
69688
  }) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
69594
69689
  registerAdapter("claude", claudeAdapter);
69595
- const codexIsolatedHome = import_node_path80.default.join(config.dataDir, "codex-home");
69690
+ const codexIsolatedHome = import_node_path81.default.join(config.dataDir, "codex-home");
69596
69691
  try {
69597
69692
  import_node_fs56.default.mkdirSync(codexIsolatedHome, { recursive: true });
69598
69693
  for (const f of ["auth.json", "config.toml"]) {
69599
- const link = import_node_path80.default.join(codexIsolatedHome, f);
69600
- const target = import_node_path80.default.join(import_node_os28.default.homedir(), ".codex", f);
69694
+ const link = import_node_path81.default.join(codexIsolatedHome, f);
69695
+ const target = import_node_path81.default.join(import_node_os28.default.homedir(), ".codex", f);
69601
69696
  if (!import_node_fs56.default.existsSync(link) && import_node_fs56.default.existsSync(target)) import_node_fs56.default.symlinkSync(target, link);
69602
69697
  }
69603
69698
  } catch (err) {
@@ -69611,11 +69706,11 @@ async function startDaemon(config) {
69611
69706
  // projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
69612
69707
  codexHomeFor: (cwd) => resolveCodexHome({
69613
69708
  cwd,
69614
- personaRoot: import_node_path80.default.join(config.dataDir, "personas"),
69709
+ personaRoot: import_node_path81.default.join(config.dataDir, "personas"),
69615
69710
  // 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
69616
69711
  // Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
69617
69712
  projectPaths: projectsStore.listMerged().map((x) => x.path),
69618
- sharedHome: import_node_path80.default.join(import_node_os28.default.homedir(), ".codex"),
69713
+ sharedHome: import_node_path81.default.join(import_node_os28.default.homedir(), ".codex"),
69619
69714
  isolatedHome: codexIsolatedHome
69620
69715
  })
69621
69716
  })
@@ -69900,11 +69995,11 @@ async function startDaemon(config) {
69900
69995
  // 'persona/<pid>/owner',default 走 'default'。
69901
69996
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
69902
69997
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
69903
- personaRoot: import_node_path80.default.join(config.dataDir, "personas"),
69998
+ personaRoot: import_node_path81.default.join(config.dataDir, "personas"),
69904
69999
  usersRoot
69905
70000
  },
69906
70001
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
69907
- personaRoot: import_node_path80.default.join(config.dataDir, "personas"),
70002
+ personaRoot: import_node_path81.default.join(config.dataDir, "personas"),
69908
70003
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
69909
70004
  usersRoot,
69910
70005
  // v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
@@ -70005,11 +70100,11 @@ async function startDaemon(config) {
70005
70100
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
70006
70101
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
70007
70102
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
70008
- appBuilderPersonaRoot: import_node_path80.default.join(config.dataDir, "personas", "persona-app-builder"),
70103
+ appBuilderPersonaRoot: import_node_path81.default.join(config.dataDir, "personas", "persona-app-builder"),
70009
70104
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
70010
- deployKitRoot: import_node_path80.default.join(config.dataDir, "deploy-kit"),
70105
+ deployKitRoot: import_node_path81.default.join(config.dataDir, "deploy-kit"),
70011
70106
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
70012
- resolvePersonaRoot: (personaId2) => import_node_path80.default.join(config.dataDir, "personas", personaId2),
70107
+ resolvePersonaRoot: (personaId2) => import_node_path81.default.join(config.dataDir, "personas", personaId2),
70013
70108
  // 凭据表(M1b Step 5):与 MCP 那条同一张表、同一个来源,只是交付给另一个子进程。
70014
70109
  readSecrets,
70015
70110
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
@@ -70124,12 +70219,12 @@ async function startDaemon(config) {
70124
70219
  });
70125
70220
  Object.assign(handlers, shiftHandlers);
70126
70221
  const deployReceipts = createReceiptStore({
70127
- filePath: import_node_path80.default.join(config.dataDir, "deploy.json"),
70222
+ filePath: import_node_path81.default.join(config.dataDir, "deploy.json"),
70128
70223
  now: () => Date.now(),
70129
70224
  onFlushError: (err) => logger.error("deploy receipts flush failed", { error: String(err) })
70130
70225
  });
70131
70226
  const deploySecrets = createSecretStore({
70132
- filePath: import_node_path80.default.join(config.dataDir, "deploy-secrets.json"),
70227
+ filePath: import_node_path81.default.join(config.dataDir, "deploy-secrets.json"),
70133
70228
  now: () => Date.now(),
70134
70229
  onFlushError: (err) => logger.error("deploy secrets flush failed", { error: String(err) })
70135
70230
  });
@@ -70205,13 +70300,13 @@ async function startDaemon(config) {
70205
70300
  hasPersona: (personaId2) => personaStore.has(personaId2),
70206
70301
  startScan: (deployId, personaId2) => {
70207
70302
  const assetLines = SCANNABLE_ASSETS.map(
70208
- (name) => ` - ${name}\uFF1A${import_node_path80.default.join(config.dataDir, name)}`
70303
+ (a) => ` - ${a.name}${a.path ? `\uFF08${a.path(config.dataDir)}\uFF09` : ""}\uFF1A${a.what}`
70209
70304
  ).join("\n");
70210
70305
  const prompt = [
70211
70306
  `\u626B\u63CF persona\u300C${personaId2}\u300D\u7684\u90E8\u7F72\u73AF\u5883\uFF0CdeployId=${deployId}\u3002`,
70212
70307
  "",
70213
70308
  `persona \u76EE\u5F55\uFF1A${personaStore.personaDirPath(personaId2)}`,
70214
- "\u53EF\u4EE5\u8BFB\u5230\u7684 persona \u76EE\u5F55\u4E4B\u5916\u7684\u5171\u4EAB\u8D44\u4EA7\uFF1A",
70309
+ "\u53EF\u4EE5\u58F0\u660E\u7684 persona \u76EE\u5F55\u4E4B\u5916\u7684\u5171\u4EAB\u8D44\u4EA7\uFF08\u7528\u5230\u54EA\u6761\u5C31\u62A5\u54EA\u6761\uFF09\uFF1A",
70215
70310
  assetLines || " \uFF08\u65E0\uFF09",
70216
70311
  "",
70217
70312
  "\u6309 scan-persona-for-deploy skill \u5E72\u6D3B\uFF1A\u8FB9\u67E5\u8FB9\u7528 deploy:reportFinding \u4E0A\u62A5\uFF0C",
@@ -70270,7 +70365,7 @@ async function startDaemon(config) {
70270
70365
  });
70271
70366
  shiftScheduler.start();
70272
70367
  logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
70273
- const larkBotStore = createLarkBotBindingStore(import_node_path80.default.join(config.dataDir, "personas"));
70368
+ const larkBotStore = createLarkBotBindingStore(import_node_path81.default.join(config.dataDir, "personas"));
70274
70369
  const larkBotCloud = createLarkBotCloudClient({
70275
70370
  api: config.clawosApi ?? DEFAULT_CLAWOS_API,
70276
70371
  apiKey: resolveClawdTicketsApiKey(),
@@ -70284,7 +70379,7 @@ async function startDaemon(config) {
70284
70379
  store: larkBotStore,
70285
70380
  fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
70286
70381
  // 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
70287
- mediaRootFor: (chatId) => import_node_path80.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
70382
+ mediaRootFor: (chatId) => import_node_path81.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
70288
70383
  isShuttingDown: () => larkDraining,
70289
70384
  logger: {
70290
70385
  warn: (msg) => logger.warn(msg),
@@ -70589,8 +70684,8 @@ async function startDaemon(config) {
70589
70684
  const lines = [
70590
70685
  `Tunnel: ${r.url}`,
70591
70686
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
70592
- `Frpc config: ${import_node_path80.default.join(config.dataDir, "frpc.toml")}`,
70593
- `Frpc log: ${import_node_path80.default.join(logDir, "frpc.log")}`
70687
+ `Frpc config: ${import_node_path81.default.join(config.dataDir, "frpc.toml")}`,
70688
+ `Frpc log: ${import_node_path81.default.join(logDir, "frpc.log")}`
70594
70689
  ];
70595
70690
  const width2 = Math.max(...lines.map((l) => l.length));
70596
70691
  const bar = "\u2550".repeat(width2 + 4);
@@ -70603,7 +70698,7 @@ ${bar}
70603
70698
 
70604
70699
  `);
70605
70700
  try {
70606
- const connectPath = import_node_path80.default.join(config.dataDir, "connect.txt");
70701
+ const connectPath = import_node_path81.default.join(config.dataDir, "connect.txt");
70607
70702
  import_node_fs56.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
70608
70703
  } catch {
70609
70704
  }
@@ -70693,7 +70788,7 @@ ${bar}
70693
70788
  };
70694
70789
  }
70695
70790
  function migrateDropPersonsDir(dataDir) {
70696
- const dir = import_node_path80.default.join(dataDir, "persons");
70791
+ const dir = import_node_path81.default.join(dataDir, "persons");
70697
70792
  try {
70698
70793
  import_node_fs56.default.rmSync(dir, { recursive: true, force: true });
70699
70794
  } catch {