@clawos-dev/clawd 0.2.293 → 0.2.295

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: path78, errorMaps, issueData } = params;
454
- const fullPath = [...path78, ...issueData.path || []];
453
+ const { data, path: path79, errorMaps, issueData } = params;
454
+ const fullPath = [...path79, ...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, path78, key) {
765
+ constructor(parent, value, path79, key) {
766
766
  this._cachedPath = [];
767
767
  this.parent = parent;
768
768
  this.data = value;
769
- this._path = path78;
769
+ this._path = path79;
770
770
  this._key = key;
771
771
  }
772
772
  get path() {
@@ -7034,8 +7034,10 @@ var init_schemas = __esm({
7034
7034
  * 由 daemon lark-bot-connector 模块写入,UI 只读(sidebar 按此字段隐藏,Drawer 群清单按此聚合)。
7035
7035
  */
7036
7036
  larkChatId: external_exports.string().min(1).optional(),
7037
- /** 飞书群名快照(展示用,随事件里的群名更新,可能滞后于飞书侧改名) */
7037
+ /** 飞书会话名快照(展示用):群会话为群名、私聊会话为对方用户名;随事件更新,可能滞后 */
7038
7038
  larkChatName: external_exports.string().min(1).optional(),
7039
+ /** lark 会话类型(spec 2026-08-06 P9):p2p 与群的 chat_id 形态无法区分,UI 文案分支需要。可选=兼容老数据(缺省按 group 展示) */
7040
+ larkChatType: external_exports.enum(["p2p", "group"]).optional(),
7039
7041
  createdAt: external_exports.string().min(1),
7040
7042
  updatedAt: external_exports.string().min(1)
7041
7043
  });
@@ -8769,8 +8771,8 @@ var require_req = __commonJS({
8769
8771
  if (req.originalUrl) {
8770
8772
  _req.url = req.originalUrl;
8771
8773
  } else {
8772
- const path78 = req.path;
8773
- _req.url = typeof path78 === "string" ? path78 : req.url ? req.url.path || req.url : void 0;
8774
+ const path79 = req.path;
8775
+ _req.url = typeof path79 === "string" ? path79 : req.url ? req.url.path || req.url : void 0;
8774
8776
  }
8775
8777
  if (req.query) {
8776
8778
  _req.query = req.query;
@@ -8935,14 +8937,14 @@ var require_redact = __commonJS({
8935
8937
  }
8936
8938
  return obj;
8937
8939
  }
8938
- function parsePath(path78) {
8940
+ function parsePath(path79) {
8939
8941
  const parts = [];
8940
8942
  let current = "";
8941
8943
  let inBrackets = false;
8942
8944
  let inQuotes = false;
8943
8945
  let quoteChar = "";
8944
- for (let i = 0; i < path78.length; i++) {
8945
- const char = path78[i];
8946
+ for (let i = 0; i < path79.length; i++) {
8947
+ const char = path79[i];
8946
8948
  if (!inBrackets && char === ".") {
8947
8949
  if (current) {
8948
8950
  parts.push(current);
@@ -9073,10 +9075,10 @@ var require_redact = __commonJS({
9073
9075
  return current;
9074
9076
  }
9075
9077
  function redactPaths(obj, paths, censor, remove = false) {
9076
- for (const path78 of paths) {
9077
- const parts = parsePath(path78);
9078
+ for (const path79 of paths) {
9079
+ const parts = parsePath(path79);
9078
9080
  if (parts.includes("*")) {
9079
- redactWildcardPath(obj, parts, censor, path78, remove);
9081
+ redactWildcardPath(obj, parts, censor, path79, remove);
9080
9082
  } else {
9081
9083
  if (remove) {
9082
9084
  removeKey(obj, parts);
@@ -9161,8 +9163,8 @@ var require_redact = __commonJS({
9161
9163
  }
9162
9164
  } else {
9163
9165
  if (afterWildcard.includes("*")) {
9164
- const wrappedCensor = typeof censor === "function" ? (value, path78) => {
9165
- const fullPath = [...pathArray.slice(0, pathLength), ...path78];
9166
+ const wrappedCensor = typeof censor === "function" ? (value, path79) => {
9167
+ const fullPath = [...pathArray.slice(0, pathLength), ...path79];
9166
9168
  return censor(value, fullPath);
9167
9169
  } : censor;
9168
9170
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -9197,8 +9199,8 @@ var require_redact = __commonJS({
9197
9199
  return null;
9198
9200
  }
9199
9201
  const pathStructure = /* @__PURE__ */ new Map();
9200
- for (const path78 of pathsToClone) {
9201
- const parts = parsePath(path78);
9202
+ for (const path79 of pathsToClone) {
9203
+ const parts = parsePath(path79);
9202
9204
  let current = pathStructure;
9203
9205
  for (let i = 0; i < parts.length; i++) {
9204
9206
  const part = parts[i];
@@ -9250,24 +9252,24 @@ var require_redact = __commonJS({
9250
9252
  }
9251
9253
  return cloneSelectively(obj, pathStructure);
9252
9254
  }
9253
- function validatePath(path78) {
9254
- if (typeof path78 !== "string") {
9255
+ function validatePath(path79) {
9256
+ if (typeof path79 !== "string") {
9255
9257
  throw new Error("Paths must be (non-empty) strings");
9256
9258
  }
9257
- if (path78 === "") {
9259
+ if (path79 === "") {
9258
9260
  throw new Error("Invalid redaction path ()");
9259
9261
  }
9260
- if (path78.includes("..")) {
9261
- throw new Error(`Invalid redaction path (${path78})`);
9262
+ if (path79.includes("..")) {
9263
+ throw new Error(`Invalid redaction path (${path79})`);
9262
9264
  }
9263
- if (path78.includes(",")) {
9264
- throw new Error(`Invalid redaction path (${path78})`);
9265
+ if (path79.includes(",")) {
9266
+ throw new Error(`Invalid redaction path (${path79})`);
9265
9267
  }
9266
9268
  let bracketCount = 0;
9267
9269
  let inQuotes = false;
9268
9270
  let quoteChar = "";
9269
- for (let i = 0; i < path78.length; i++) {
9270
- const char = path78[i];
9271
+ for (let i = 0; i < path79.length; i++) {
9272
+ const char = path79[i];
9271
9273
  if ((char === '"' || char === "'") && bracketCount > 0) {
9272
9274
  if (!inQuotes) {
9273
9275
  inQuotes = true;
@@ -9281,20 +9283,20 @@ var require_redact = __commonJS({
9281
9283
  } else if (char === "]" && !inQuotes) {
9282
9284
  bracketCount--;
9283
9285
  if (bracketCount < 0) {
9284
- throw new Error(`Invalid redaction path (${path78})`);
9286
+ throw new Error(`Invalid redaction path (${path79})`);
9285
9287
  }
9286
9288
  }
9287
9289
  }
9288
9290
  if (bracketCount !== 0) {
9289
- throw new Error(`Invalid redaction path (${path78})`);
9291
+ throw new Error(`Invalid redaction path (${path79})`);
9290
9292
  }
9291
9293
  }
9292
9294
  function validatePaths(paths) {
9293
9295
  if (!Array.isArray(paths)) {
9294
9296
  throw new TypeError("paths must be an array");
9295
9297
  }
9296
- for (const path78 of paths) {
9297
- validatePath(path78);
9298
+ for (const path79 of paths) {
9299
+ validatePath(path79);
9298
9300
  }
9299
9301
  }
9300
9302
  function slowRedact(options = {}) {
@@ -9462,8 +9464,8 @@ var require_redaction = __commonJS({
9462
9464
  if (shape[k2] === null) {
9463
9465
  o[k2] = (value) => topCensor(value, [k2]);
9464
9466
  } else {
9465
- const wrappedCensor = typeof censor === "function" ? (value, path78) => {
9466
- return censor(value, [k2, ...path78]);
9467
+ const wrappedCensor = typeof censor === "function" ? (value, path79) => {
9468
+ return censor(value, [k2, ...path79]);
9467
9469
  } : censor;
9468
9470
  o[k2] = Redact({
9469
9471
  paths: shape[k2],
@@ -9681,10 +9683,10 @@ var require_atomic_sleep = __commonJS({
9681
9683
  var require_sonic_boom = __commonJS({
9682
9684
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
9683
9685
  "use strict";
9684
- var fs68 = require("fs");
9686
+ var fs69 = require("fs");
9685
9687
  var EventEmitter3 = require("events");
9686
9688
  var inherits = require("util").inherits;
9687
- var path78 = require("path");
9689
+ var path79 = require("path");
9688
9690
  var sleep2 = require_atomic_sleep();
9689
9691
  var assert = require("assert");
9690
9692
  var BUSY_WRITE_TIMEOUT = 100;
@@ -9738,20 +9740,20 @@ var require_sonic_boom = __commonJS({
9738
9740
  const mode = sonic.mode;
9739
9741
  if (sonic.sync) {
9740
9742
  try {
9741
- if (sonic.mkdir) fs68.mkdirSync(path78.dirname(file), { recursive: true });
9742
- const fd = fs68.openSync(file, flags, mode);
9743
+ if (sonic.mkdir) fs69.mkdirSync(path79.dirname(file), { recursive: true });
9744
+ const fd = fs69.openSync(file, flags, mode);
9743
9745
  fileOpened(null, fd);
9744
9746
  } catch (err) {
9745
9747
  fileOpened(err);
9746
9748
  throw err;
9747
9749
  }
9748
9750
  } else if (sonic.mkdir) {
9749
- fs68.mkdir(path78.dirname(file), { recursive: true }, (err) => {
9751
+ fs69.mkdir(path79.dirname(file), { recursive: true }, (err) => {
9750
9752
  if (err) return fileOpened(err);
9751
- fs68.open(file, flags, mode, fileOpened);
9753
+ fs69.open(file, flags, mode, fileOpened);
9752
9754
  });
9753
9755
  } else {
9754
- fs68.open(file, flags, mode, fileOpened);
9756
+ fs69.open(file, flags, mode, fileOpened);
9755
9757
  }
9756
9758
  }
9757
9759
  function SonicBoom(opts) {
@@ -9792,8 +9794,8 @@ var require_sonic_boom = __commonJS({
9792
9794
  this.flush = flushBuffer;
9793
9795
  this.flushSync = flushBufferSync;
9794
9796
  this._actualWrite = actualWriteBuffer;
9795
- fsWriteSync = () => fs68.writeSync(this.fd, this._writingBuf);
9796
- fsWrite = () => fs68.write(this.fd, this._writingBuf, this.release);
9797
+ fsWriteSync = () => fs69.writeSync(this.fd, this._writingBuf);
9798
+ fsWrite = () => fs69.write(this.fd, this._writingBuf, this.release);
9797
9799
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
9798
9800
  this._writingBuf = "";
9799
9801
  this.write = write;
@@ -9802,15 +9804,15 @@ var require_sonic_boom = __commonJS({
9802
9804
  this._actualWrite = actualWrite;
9803
9805
  fsWriteSync = () => {
9804
9806
  if (Buffer.isBuffer(this._writingBuf)) {
9805
- return fs68.writeSync(this.fd, this._writingBuf);
9807
+ return fs69.writeSync(this.fd, this._writingBuf);
9806
9808
  }
9807
- return fs68.writeSync(this.fd, this._writingBuf, "utf8");
9809
+ return fs69.writeSync(this.fd, this._writingBuf, "utf8");
9808
9810
  };
9809
9811
  fsWrite = () => {
9810
9812
  if (Buffer.isBuffer(this._writingBuf)) {
9811
- return fs68.write(this.fd, this._writingBuf, this.release);
9813
+ return fs69.write(this.fd, this._writingBuf, this.release);
9812
9814
  }
9813
- return fs68.write(this.fd, this._writingBuf, "utf8", this.release);
9815
+ return fs69.write(this.fd, this._writingBuf, "utf8", this.release);
9814
9816
  };
9815
9817
  } else {
9816
9818
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -9867,7 +9869,7 @@ var require_sonic_boom = __commonJS({
9867
9869
  }
9868
9870
  }
9869
9871
  if (this._fsync) {
9870
- fs68.fsyncSync(this.fd);
9872
+ fs69.fsyncSync(this.fd);
9871
9873
  }
9872
9874
  const len = this._len;
9873
9875
  if (this._reopening) {
@@ -9981,7 +9983,7 @@ var require_sonic_boom = __commonJS({
9981
9983
  const onDrain = () => {
9982
9984
  if (!this._fsync) {
9983
9985
  try {
9984
- fs68.fsync(this.fd, (err) => {
9986
+ fs69.fsync(this.fd, (err) => {
9985
9987
  this._flushPending = false;
9986
9988
  cb(err);
9987
9989
  });
@@ -10083,7 +10085,7 @@ var require_sonic_boom = __commonJS({
10083
10085
  const fd = this.fd;
10084
10086
  this.once("ready", () => {
10085
10087
  if (fd !== this.fd) {
10086
- fs68.close(fd, (err) => {
10088
+ fs69.close(fd, (err) => {
10087
10089
  if (err) {
10088
10090
  return this.emit("error", err);
10089
10091
  }
@@ -10132,7 +10134,7 @@ var require_sonic_boom = __commonJS({
10132
10134
  buf = this._bufs[0];
10133
10135
  }
10134
10136
  try {
10135
- const n = Buffer.isBuffer(buf) ? fs68.writeSync(this.fd, buf) : fs68.writeSync(this.fd, buf, "utf8");
10137
+ const n = Buffer.isBuffer(buf) ? fs69.writeSync(this.fd, buf) : fs69.writeSync(this.fd, buf, "utf8");
10136
10138
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
10137
10139
  buf = releasedBufObj.writingBuf;
10138
10140
  this._len = releasedBufObj.len;
@@ -10148,7 +10150,7 @@ var require_sonic_boom = __commonJS({
10148
10150
  }
10149
10151
  }
10150
10152
  try {
10151
- fs68.fsyncSync(this.fd);
10153
+ fs69.fsyncSync(this.fd);
10152
10154
  } catch {
10153
10155
  }
10154
10156
  }
@@ -10169,7 +10171,7 @@ var require_sonic_boom = __commonJS({
10169
10171
  buf = mergeBuf(this._bufs[0], this._lens[0]);
10170
10172
  }
10171
10173
  try {
10172
- const n = fs68.writeSync(this.fd, buf);
10174
+ const n = fs69.writeSync(this.fd, buf);
10173
10175
  buf = buf.subarray(n);
10174
10176
  this._len = Math.max(this._len - n, 0);
10175
10177
  if (buf.length <= 0) {
@@ -10197,13 +10199,13 @@ var require_sonic_boom = __commonJS({
10197
10199
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
10198
10200
  if (this.sync) {
10199
10201
  try {
10200
- const written = Buffer.isBuffer(this._writingBuf) ? fs68.writeSync(this.fd, this._writingBuf) : fs68.writeSync(this.fd, this._writingBuf, "utf8");
10202
+ const written = Buffer.isBuffer(this._writingBuf) ? fs69.writeSync(this.fd, this._writingBuf) : fs69.writeSync(this.fd, this._writingBuf, "utf8");
10201
10203
  release(null, written);
10202
10204
  } catch (err) {
10203
10205
  release(err);
10204
10206
  }
10205
10207
  } else {
10206
- fs68.write(this.fd, this._writingBuf, release);
10208
+ fs69.write(this.fd, this._writingBuf, release);
10207
10209
  }
10208
10210
  }
10209
10211
  function actualWriteBuffer() {
@@ -10212,7 +10214,7 @@ var require_sonic_boom = __commonJS({
10212
10214
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
10213
10215
  if (this.sync) {
10214
10216
  try {
10215
- const written = fs68.writeSync(this.fd, this._writingBuf);
10217
+ const written = fs69.writeSync(this.fd, this._writingBuf);
10216
10218
  release(null, written);
10217
10219
  } catch (err) {
10218
10220
  release(err);
@@ -10221,7 +10223,7 @@ var require_sonic_boom = __commonJS({
10221
10223
  if (kCopyBuffer) {
10222
10224
  this._writingBuf = Buffer.from(this._writingBuf);
10223
10225
  }
10224
- fs68.write(this.fd, this._writingBuf, release);
10226
+ fs69.write(this.fd, this._writingBuf, release);
10225
10227
  }
10226
10228
  }
10227
10229
  function actualClose(sonic) {
@@ -10237,12 +10239,12 @@ var require_sonic_boom = __commonJS({
10237
10239
  sonic._lens = [];
10238
10240
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
10239
10241
  try {
10240
- fs68.fsync(sonic.fd, closeWrapped);
10242
+ fs69.fsync(sonic.fd, closeWrapped);
10241
10243
  } catch {
10242
10244
  }
10243
10245
  function closeWrapped() {
10244
10246
  if (sonic.fd !== 1 && sonic.fd !== 2) {
10245
- fs68.close(sonic.fd, done);
10247
+ fs69.close(sonic.fd, done);
10246
10248
  } else {
10247
10249
  done();
10248
10250
  }
@@ -13377,11 +13379,11 @@ var init_lib = __esm({
13377
13379
  }
13378
13380
  }
13379
13381
  },
13380
- addToPath: function addToPath(path78, added, removed, oldPosInc, options) {
13381
- var last = path78.lastComponent;
13382
+ addToPath: function addToPath(path79, added, removed, oldPosInc, options) {
13383
+ var last = path79.lastComponent;
13382
13384
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
13383
13385
  return {
13384
- oldPos: path78.oldPos + oldPosInc,
13386
+ oldPos: path79.oldPos + oldPosInc,
13385
13387
  lastComponent: {
13386
13388
  count: last.count + 1,
13387
13389
  added,
@@ -13391,7 +13393,7 @@ var init_lib = __esm({
13391
13393
  };
13392
13394
  } else {
13393
13395
  return {
13394
- oldPos: path78.oldPos + oldPosInc,
13396
+ oldPos: path79.oldPos + oldPosInc,
13395
13397
  lastComponent: {
13396
13398
  count: 1,
13397
13399
  added,
@@ -13900,10 +13902,10 @@ function attachmentToHistoryMessage(o, ts) {
13900
13902
  const memories = raw.map((m2) => {
13901
13903
  if (!m2 || typeof m2 !== "object") return null;
13902
13904
  const rec3 = m2;
13903
- const path78 = typeof rec3.path === "string" ? rec3.path : null;
13905
+ const path79 = typeof rec3.path === "string" ? rec3.path : null;
13904
13906
  const content = typeof rec3.content === "string" ? rec3.content : null;
13905
- if (!path78 || content == null) return null;
13906
- const entry = { path: path78, content };
13907
+ if (!path79 || content == null) return null;
13908
+ const entry = { path: path79, content };
13907
13909
  if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
13908
13910
  return entry;
13909
13911
  }).filter((m2) => m2 !== null);
@@ -14720,10 +14722,10 @@ function parseAttachment(obj) {
14720
14722
  const memories = raw.map((m2) => {
14721
14723
  if (!m2 || typeof m2 !== "object") return null;
14722
14724
  const rec3 = m2;
14723
- const path78 = typeof rec3.path === "string" ? rec3.path : null;
14725
+ const path79 = typeof rec3.path === "string" ? rec3.path : null;
14724
14726
  const content = typeof rec3.content === "string" ? rec3.content : null;
14725
- if (!path78 || content == null) return null;
14726
- const out = { path: path78, content };
14727
+ if (!path79 || content == null) return null;
14728
+ const out = { path: path79, content };
14727
14729
  if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
14728
14730
  return out;
14729
14731
  }).filter((m2) => m2 !== null);
@@ -35692,8 +35694,8 @@ var require_utils = __commonJS({
35692
35694
  var result = transform[inputType][outputType](input);
35693
35695
  return result;
35694
35696
  };
35695
- exports2.resolve = function(path78) {
35696
- var parts = path78.split("/");
35697
+ exports2.resolve = function(path79) {
35698
+ var parts = path79.split("/");
35697
35699
  var result = [];
35698
35700
  for (var index = 0; index < parts.length; index++) {
35699
35701
  var part = parts[index];
@@ -41546,18 +41548,18 @@ var require_object = __commonJS({
41546
41548
  var object = new ZipObject(name, zipObjectContent, o);
41547
41549
  this.files[name] = object;
41548
41550
  };
41549
- var parentFolder = function(path78) {
41550
- if (path78.slice(-1) === "/") {
41551
- path78 = path78.substring(0, path78.length - 1);
41551
+ var parentFolder = function(path79) {
41552
+ if (path79.slice(-1) === "/") {
41553
+ path79 = path79.substring(0, path79.length - 1);
41552
41554
  }
41553
- var lastSlash = path78.lastIndexOf("/");
41554
- return lastSlash > 0 ? path78.substring(0, lastSlash) : "";
41555
+ var lastSlash = path79.lastIndexOf("/");
41556
+ return lastSlash > 0 ? path79.substring(0, lastSlash) : "";
41555
41557
  };
41556
- var forceTrailingSlash = function(path78) {
41557
- if (path78.slice(-1) !== "/") {
41558
- path78 += "/";
41558
+ var forceTrailingSlash = function(path79) {
41559
+ if (path79.slice(-1) !== "/") {
41560
+ path79 += "/";
41559
41561
  }
41560
- return path78;
41562
+ return path79;
41561
41563
  };
41562
41564
  var folderAdd = function(name, createFolders) {
41563
41565
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -42559,7 +42561,7 @@ var require_lib3 = __commonJS({
42559
42561
  // src/run-case/recorder.ts
42560
42562
  function startRunCaseRecorder(opts) {
42561
42563
  const now = opts.now ?? Date.now;
42562
- const dir = import_node_path65.default.dirname(opts.recordPath);
42564
+ const dir = import_node_path66.default.dirname(opts.recordPath);
42563
42565
  let stream = null;
42564
42566
  let closing = false;
42565
42567
  let closedSettled = false;
@@ -42573,8 +42575,8 @@ function startRunCaseRecorder(opts) {
42573
42575
  });
42574
42576
  const ensureStream = () => {
42575
42577
  if (stream) return stream;
42576
- import_node_fs49.default.mkdirSync(dir, { recursive: true });
42577
- stream = import_node_fs49.default.createWriteStream(opts.recordPath, { flags: "a" });
42578
+ import_node_fs50.default.mkdirSync(dir, { recursive: true });
42579
+ stream = import_node_fs50.default.createWriteStream(opts.recordPath, { flags: "a" });
42578
42580
  stream.on("close", () => closedResolve());
42579
42581
  return stream;
42580
42582
  };
@@ -42599,12 +42601,12 @@ function startRunCaseRecorder(opts) {
42599
42601
  };
42600
42602
  return { tap, close, closed };
42601
42603
  }
42602
- var import_node_fs49, import_node_path65;
42604
+ var import_node_fs50, import_node_path66;
42603
42605
  var init_recorder = __esm({
42604
42606
  "src/run-case/recorder.ts"() {
42605
42607
  "use strict";
42606
- import_node_fs49 = __toESM(require("fs"), 1);
42607
- import_node_path65 = __toESM(require("path"), 1);
42608
+ import_node_fs50 = __toESM(require("fs"), 1);
42609
+ import_node_path66 = __toESM(require("path"), 1);
42608
42610
  }
42609
42611
  });
42610
42612
 
@@ -42647,7 +42649,7 @@ var init_wire = __esm({
42647
42649
  // src/run-case/controller.ts
42648
42650
  async function runController(opts) {
42649
42651
  const now = opts.now ?? Date.now;
42650
- const cwd = opts.cwd ?? (0, import_node_fs50.mkdtempSync)(import_node_path66.default.join(import_node_os23.default.tmpdir(), "clawd-runcase-"));
42652
+ const cwd = opts.cwd ?? (0, import_node_fs51.mkdtempSync)(import_node_path67.default.join(import_node_os23.default.tmpdir(), "clawd-runcase-"));
42651
42653
  const ownsCwd = opts.cwd === void 0;
42652
42654
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
42653
42655
  const spawnCtx = { cwd };
@@ -42808,19 +42810,19 @@ async function runController(opts) {
42808
42810
  if (sigintHandler) process.off("SIGINT", sigintHandler);
42809
42811
  if (ownsCwd) {
42810
42812
  try {
42811
- (0, import_node_fs50.rmSync)(cwd, { recursive: true, force: true });
42813
+ (0, import_node_fs51.rmSync)(cwd, { recursive: true, force: true });
42812
42814
  } catch {
42813
42815
  }
42814
42816
  }
42815
42817
  return exitCode ?? 0;
42816
42818
  }
42817
- var import_node_fs50, import_node_os23, import_node_path66;
42819
+ var import_node_fs51, import_node_os23, import_node_path67;
42818
42820
  var init_controller = __esm({
42819
42821
  "src/run-case/controller.ts"() {
42820
42822
  "use strict";
42821
- import_node_fs50 = require("fs");
42823
+ import_node_fs51 = require("fs");
42822
42824
  import_node_os23 = __toESM(require("os"), 1);
42823
- import_node_path66 = __toESM(require("path"), 1);
42825
+ import_node_path67 = __toESM(require("path"), 1);
42824
42826
  init_claude();
42825
42827
  init_stdout_splitter();
42826
42828
  init_permission_stdio();
@@ -43095,8 +43097,8 @@ Env (advanced):
43095
43097
  `;
43096
43098
 
43097
43099
  // src/index.ts
43098
- var import_node_path64 = __toESM(require("path"), 1);
43099
- var import_node_fs48 = __toESM(require("fs"), 1);
43100
+ var import_node_path65 = __toESM(require("path"), 1);
43101
+ var import_node_fs49 = __toESM(require("fs"), 1);
43100
43102
  var import_node_os22 = __toESM(require("os"), 1);
43101
43103
 
43102
43104
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
@@ -43778,6 +43780,9 @@ var FORCED_DENY_READ = ["~/"];
43778
43780
  function personaEditDeny(personaDir) {
43779
43781
  return `Edit(${tildePath(personaDir)}/**)`;
43780
43782
  }
43783
+ function personaReadAllow(personaDir) {
43784
+ return `Read(${tildePath(personaDir)}/**)`;
43785
+ }
43781
43786
  function tildePath(p2) {
43782
43787
  const home = (0, import_node_os2.homedir)();
43783
43788
  return p2.startsWith(`${home}/`) ? `~${p2.slice(home.length)}` : p2;
@@ -43850,6 +43855,7 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
43850
43855
  fsv.denyWrite = unionArr((fsv.denyWrite ?? []).filter((p2) => p2 !== "~/"), [spawnCwd]);
43851
43856
  fsv.allowRead = unionArr(fsv.allowRead, [userWorkDir]);
43852
43857
  fsv.allowWrite = unionArr(fsv.allowWrite, [userWorkDir]);
43858
+ s.permissions.allow = unionArr(s.permissions.allow, [`Read(${tildePath(userWorkDir)}/**)`]);
43853
43859
  return s;
43854
43860
  }
43855
43861
 
@@ -43995,17 +44001,24 @@ function extractLarkReplyText(events) {
43995
44001
  break;
43996
44002
  }
43997
44003
  }
43998
- const tail = events.slice(lastUserIdx + 1);
44004
+ const texts = events.slice(lastUserIdx + 1).filter((ev) => ev.kind === "text");
44005
+ const snapshots = texts.filter((ev) => !ev.partialId);
44006
+ if (snapshots.length > 0) {
44007
+ return snapshots.map((ev) => ev.text).filter((t) => t.length > 0).join("\n").trim();
44008
+ }
43999
44009
  const order = [];
44000
- const latest = /* @__PURE__ */ new Map();
44001
- let anon = 0;
44002
- for (const ev of tail) {
44003
- if (ev.kind !== "text") continue;
44004
- const key = ev.partialId ?? `__snapshot_${anon++}`;
44005
- if (!latest.has(key)) order.push(key);
44006
- latest.set(key, ev.text);
44010
+ const chunks = /* @__PURE__ */ new Map();
44011
+ for (const ev of texts) {
44012
+ const key = ev.partialId ?? "";
44013
+ let list = chunks.get(key);
44014
+ if (!list) {
44015
+ list = [];
44016
+ chunks.set(key, list);
44017
+ order.push(key);
44018
+ }
44019
+ list.push(ev.text);
44007
44020
  }
44008
- return order.map((k2) => latest.get(k2) ?? "").filter((t) => t.length > 0).join("\n").trim();
44021
+ return order.map((k2) => (chunks.get(k2) ?? []).join("")).filter((t) => t.length > 0).join("\n").trim();
44009
44022
  }
44010
44023
 
44011
44024
  // src/session/runner.ts
@@ -47181,8 +47194,9 @@ var SessionManager = class {
47181
47194
  // guest 三件套:creatorPrincipalId=capId(scopeForFile 回落防线)、
47182
47195
  // creatorDisplayName(reducer guest 分支硬性要求,缺则 spawn 抛)
47183
47196
  creatorPrincipalId: capId,
47184
- creatorDisplayName: `\u98DE\u4E66\u7FA4\xB7${args.chatName ?? args.chatId}`,
47197
+ creatorDisplayName: `${(args.chatType ?? "group") === "p2p" ? "\u98DE\u4E66\u79C1\u804A" : "\u98DE\u4E66\u7FA4"}\xB7${args.chatName ?? args.chatId}`,
47185
47198
  larkChatId: args.chatId,
47199
+ larkChatType: args.chatType ?? "group",
47186
47200
  ...args.chatName ? { larkChatName: args.chatName } : {},
47187
47201
  createdAt: now,
47188
47202
  updatedAt: now
@@ -47752,7 +47766,10 @@ var PersonaStore = class {
47752
47766
  /**
47753
47767
  * persona 基线注入:Edit-deny(绝对 '~/<persona>/**')并进 permissions.deny + 剥掉历史相对
47754
47768
  * 'Edit(./**)';persona 目录 '~/' 路径 union 进 sandbox.filesystem.allowRead(guest 读权
47755
- * 落盘即真源,compose 不再运行时注入——spec 2026-08-06-persona-workdir-discipline §1-§2)。
47769
+ * 落盘即真源,compose 不再运行时注入——spec 2026-08-06-persona-workdir-discipline §1-§2);
47770
+ * `Read(~/<persona>/**)` union 进 permissions.allow——OS 沙箱层可读只放行了 Bash,CC 自带
47771
+ * Read 工具在最严格 base(dontAsk + 无 allow)下仍被拒,工具层与 OS 层必须同构放行
47772
+ * (guest「自由读 persona 目录、只写自己 userWorkDir」,spec 2026-08-06-lark-dm §P10 通用化)。
47756
47773
  */
47757
47774
  injectPersonaBaseline(personaId2, settings) {
47758
47775
  const dir = this.personaDir(personaId2);
@@ -47760,6 +47777,9 @@ var PersonaStore = class {
47760
47777
  const rule = personaEditDeny(dir);
47761
47778
  const rawDeny = s.permissions && typeof s.permissions === "object" ? s.permissions.deny : void 0;
47762
47779
  const prevDeny = (Array.isArray(rawDeny) ? rawDeny : []).filter((r) => r !== "Edit(./**)" && r !== rule);
47780
+ const readRule = personaReadAllow(dir);
47781
+ const rawAllow = s.permissions && typeof s.permissions === "object" ? s.permissions.allow : void 0;
47782
+ const prevAllow = (Array.isArray(rawAllow) ? rawAllow : []).filter((r) => r !== readRule);
47763
47783
  const readPath = tildePath(dir);
47764
47784
  const sandbox = s.sandbox && typeof s.sandbox === "object" && !Array.isArray(s.sandbox) ? s.sandbox : {};
47765
47785
  const rawFs = sandbox.filesystem;
@@ -47770,6 +47790,7 @@ var PersonaStore = class {
47770
47790
  ...s,
47771
47791
  permissions: {
47772
47792
  ...s.permissions && typeof s.permissions === "object" ? s.permissions : {},
47793
+ allow: [...prevAllow, readRule],
47773
47794
  deny: [...prevDeny, rule]
47774
47795
  },
47775
47796
  sandbox: { ...sandbox, filesystem: { ...filesystem, allowRead: [...prevRead, readPath] } }
@@ -48654,7 +48675,10 @@ function migrateSandboxAllowRead(args) {
48654
48675
  continue;
48655
48676
  }
48656
48677
  const allowRead = raw.sandbox?.filesystem?.allowRead;
48657
- if (Array.isArray(allowRead) && allowRead.includes(readPath)) continue;
48678
+ const permAllow = raw.permissions?.allow;
48679
+ const readRule = personaReadAllow(args.store.personaDirPath(personaId2));
48680
+ if (Array.isArray(allowRead) && allowRead.includes(readPath) && Array.isArray(permAllow) && permAllow.includes(readRule))
48681
+ continue;
48658
48682
  args.store.writeSandboxSettings(personaId2, raw);
48659
48683
  n++;
48660
48684
  args.logger.info("persona.sandbox.allow-read.migrated", { personaId: personaId2 });
@@ -49301,8 +49325,8 @@ function turnStartInput(text) {
49301
49325
  const items = [];
49302
49326
  let leftover = text;
49303
49327
  for (const m2 of text.matchAll(SKILL_RE)) {
49304
- const [marker, name, path78] = m2;
49305
- items.push({ type: "skill", name, path: path78 });
49328
+ const [marker, name, path79] = m2;
49329
+ items.push({ type: "skill", name, path: path79 });
49306
49330
  leftover = leftover.replace(marker, "");
49307
49331
  }
49308
49332
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -51996,14 +52020,62 @@ function createLarkBotCloudClient(opts) {
51996
52020
  async claimEvents() {
51997
52021
  const json = await request("POST", "/api/lark-bot/events/claim");
51998
52022
  return json.items ?? [];
52023
+ },
52024
+ async fetchResource(appId, messageId, fileKey, maxBytes) {
52025
+ const ac = new AbortController();
52026
+ const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? 15e3);
52027
+ const qs = new URLSearchParams({
52028
+ appId,
52029
+ messageId,
52030
+ fileKey,
52031
+ ...maxBytes ? { maxBytes: String(maxBytes) } : {}
52032
+ }).toString();
52033
+ let res;
52034
+ try {
52035
+ res = await f(`${base}/api/lark-bot/resource?${qs}`, {
52036
+ method: "GET",
52037
+ signal: ac.signal,
52038
+ headers: {
52039
+ authorization: `Bearer ${opts.apiKey}`,
52040
+ "x-did": encodeURIComponent(opts.deviceId),
52041
+ "x-name": encodeURIComponent(opts.displayName),
52042
+ "x-scene": "daemon"
52043
+ }
52044
+ });
52045
+ } catch (err) {
52046
+ throw new LarkBotCloudError(`lark-bot cloud resource fetch failed: ${err.message}`);
52047
+ } finally {
52048
+ clearTimeout(timer);
52049
+ }
52050
+ if (!res.ok) {
52051
+ throw new LarkBotCloudError(`lark-bot cloud resource: HTTP ${res.status}`, res.status);
52052
+ }
52053
+ const data = Buffer.from(await res.arrayBuffer());
52054
+ const contentType = res.headers.get("content-type") ?? "application/octet-stream";
52055
+ return { data, contentType };
51999
52056
  }
52000
52057
  };
52001
52058
  }
52002
52059
 
52003
52060
  // src/lark-bot-connector/chat-router.ts
52061
+ var import_node_fs27 = __toESM(require("fs"), 1);
52062
+ var import_node_path28 = __toESM(require("path"), 1);
52004
52063
  init_protocol();
52005
52064
  var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
52006
52065
  var DEFAULT_TURN_TIMEOUT_MS = 10 * 60 * 1e3;
52066
+ var MAX_IMAGE_BYTES = 8 * 1024 * 1024;
52067
+ var EXT_BY_MIME = {
52068
+ "image/png": "png",
52069
+ "image/jpeg": "jpg",
52070
+ "image/gif": "gif",
52071
+ "image/webp": "webp"
52072
+ };
52073
+ var IMAGE_OVERSIZE_TEXT = "[\u56FE\u7247\u6D88\u606F\uFF0C\u8D85\u51FA\u5927\u5C0F\u9650\u5236]";
52074
+ var IMAGE_UNAVAILABLE_TEXT = "[\u56FE\u7247\u6D88\u606F\uFF0C\u6682\u4E0D\u652F\u6301\u67E5\u770B]";
52075
+ function safeMediaName(raw) {
52076
+ const cleaned = raw.replace(/[^a-zA-Z0-9_\-.]/g, "_").replace(/^\.+/, (d) => "_".repeat(d.length));
52077
+ return (cleaned || "msg").replace(/\.\./g, "__");
52078
+ }
52007
52079
  function createLarkChatRouter(deps) {
52008
52080
  const timeoutMs = deps.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;
52009
52081
  const replyDelays = deps.replyRetryDelaysMs ?? [2e3, 8e3, 3e4];
@@ -52016,7 +52088,34 @@ function createLarkChatRouter(deps) {
52016
52088
  return;
52017
52089
  }
52018
52090
  const speaker = env.senderName || env.senderOpenId || "\u672A\u77E5\u6210\u5458";
52019
- const body = env.text?.trim() ? env.text : "[\u975E\u6587\u672C\u6D88\u606F]";
52091
+ const imageLines = [];
52092
+ for (const [i, key] of (env.imageKeys ?? []).entries()) {
52093
+ try {
52094
+ if (!deps.fetchResource || !deps.mediaRootFor) throw new Error("resource pipeline not wired");
52095
+ const r = await deps.fetchResource(env.appId, env.messageId, key, MAX_IMAGE_BYTES);
52096
+ if (r.data.byteLength > MAX_IMAGE_BYTES) {
52097
+ deps.logger?.warn(`larkBot image oversize ${key}: ${r.data.byteLength}B`);
52098
+ imageLines.push(IMAGE_OVERSIZE_TEXT);
52099
+ continue;
52100
+ }
52101
+ const ext = EXT_BY_MIME[r.contentType];
52102
+ if (!ext) {
52103
+ deps.logger?.warn(`larkBot image unsupported mime ${key}: ${r.contentType}`);
52104
+ imageLines.push(IMAGE_UNAVAILABLE_TEXT);
52105
+ continue;
52106
+ }
52107
+ const dir = deps.mediaRootFor(env.chatId);
52108
+ import_node_fs27.default.mkdirSync(dir, { recursive: true });
52109
+ const p2 = import_node_path28.default.join(dir, `${safeMediaName(env.messageId)}-${i}.${ext}`);
52110
+ import_node_fs27.default.writeFileSync(p2, r.data);
52111
+ imageLines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
52112
+ } catch (err) {
52113
+ deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
52114
+ imageLines.push(IMAGE_UNAVAILABLE_TEXT);
52115
+ }
52116
+ }
52117
+ const rawBody = [env.text?.trim(), ...imageLines].filter(Boolean).join("\n");
52118
+ const body = rawBody || "[\u975E\u6587\u672C\u6D88\u606F]";
52020
52119
  const text = `${body}
52021
52120
 
52022
52121
  ${formatLarkSpeakerReminder(speaker)}`;
@@ -52024,6 +52123,7 @@ ${formatLarkSpeakerReminder(speaker)}`;
52024
52123
  personaId: env.personaId,
52025
52124
  chatId: env.chatId,
52026
52125
  chatName: env.chatName,
52126
+ chatType: env.chatType ?? "group",
52027
52127
  senderOpenId: env.senderOpenId ?? "",
52028
52128
  senderName: env.senderName ?? env.senderOpenId ?? "\u672A\u77E5\u6210\u5458",
52029
52129
  text
@@ -52786,7 +52886,7 @@ var CodexHistoryReader = class {
52786
52886
  };
52787
52887
 
52788
52888
  // src/tools/codex-skills.ts
52789
- var import_node_path28 = __toESM(require("path"), 1);
52889
+ var import_node_path29 = __toESM(require("path"), 1);
52790
52890
  function str3(v2) {
52791
52891
  return typeof v2 === "string" ? v2 : void 0;
52792
52892
  }
@@ -52801,13 +52901,13 @@ function mapSkillsListResponse(res) {
52801
52901
  const r = s ?? {};
52802
52902
  const name = str3(r.name);
52803
52903
  if (!name) continue;
52804
- const path78 = str3(r.path);
52904
+ const path79 = str3(r.path);
52805
52905
  const description = str3(r.description);
52806
52906
  const isPlugin = name.includes(":");
52807
52907
  out.push({
52808
52908
  name,
52809
52909
  source: isPlugin ? "plugin" : "project",
52810
- ...path78 ? { path: path78 } : {},
52910
+ ...path79 ? { path: path79 } : {},
52811
52911
  ...description ? { description } : {},
52812
52912
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
52813
52913
  });
@@ -52823,30 +52923,30 @@ async function listCodexSkills(cwd, deps = {}) {
52823
52923
  // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
52824
52924
  // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
52825
52925
  beforeRequest: (client) => {
52826
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path28.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
52926
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path29.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
52827
52927
  }
52828
52928
  });
52829
52929
  return mapSkillsListResponse(res);
52830
52930
  }
52831
52931
 
52832
52932
  // src/workspace/browser.ts
52833
- var import_node_fs27 = __toESM(require("fs"), 1);
52933
+ var import_node_fs28 = __toESM(require("fs"), 1);
52834
52934
  var import_node_os8 = __toESM(require("os"), 1);
52835
- var import_node_path29 = __toESM(require("path"), 1);
52935
+ var import_node_path30 = __toESM(require("path"), 1);
52836
52936
  init_protocol();
52837
52937
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
52838
52938
  function resolveInsideCwd(cwd, subpath) {
52839
- const absCwd = import_node_path29.default.resolve(cwd);
52840
- const joined = import_node_path29.default.resolve(absCwd, subpath ?? ".");
52841
- const rel = import_node_path29.default.relative(absCwd, joined);
52842
- if (rel.startsWith("..") || import_node_path29.default.isAbsolute(rel)) {
52939
+ const absCwd = import_node_path30.default.resolve(cwd);
52940
+ const joined = import_node_path30.default.resolve(absCwd, subpath ?? ".");
52941
+ const rel = import_node_path30.default.relative(absCwd, joined);
52942
+ if (rel.startsWith("..") || import_node_path30.default.isAbsolute(rel)) {
52843
52943
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
52844
52944
  }
52845
52945
  return joined;
52846
52946
  }
52847
52947
  function ensureCwd(cwd) {
52848
52948
  try {
52849
- const stat = import_node_fs27.default.statSync(cwd);
52949
+ const stat = import_node_fs28.default.statSync(cwd);
52850
52950
  if (!stat.isDirectory()) {
52851
52951
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
52852
52952
  }
@@ -52860,7 +52960,7 @@ var WorkspaceBrowser = class {
52860
52960
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
52861
52961
  ensureCwd(cwd);
52862
52962
  const full = resolveInsideCwd(cwd, args.path);
52863
- const dirents = import_node_fs27.default.readdirSync(full, { withFileTypes: true });
52963
+ const dirents = import_node_fs28.default.readdirSync(full, { withFileTypes: true });
52864
52964
  const entries = [];
52865
52965
  for (const d of dirents) {
52866
52966
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -52870,7 +52970,7 @@ var WorkspaceBrowser = class {
52870
52970
  mtime: ""
52871
52971
  };
52872
52972
  try {
52873
- const st = import_node_fs27.default.statSync(import_node_path29.default.join(full, d.name));
52973
+ const st = import_node_fs28.default.statSync(import_node_path30.default.join(full, d.name));
52874
52974
  entry.mtime = new Date(st.mtimeMs).toISOString();
52875
52975
  if (d.isFile()) entry.size = st.size;
52876
52976
  } catch {
@@ -52886,14 +52986,14 @@ var WorkspaceBrowser = class {
52886
52986
  read(args) {
52887
52987
  ensureCwd(args.cwd);
52888
52988
  const full = resolveInsideCwd(args.cwd, args.path);
52889
- const st = import_node_fs27.default.statSync(full);
52989
+ const st = import_node_fs28.default.statSync(full);
52890
52990
  if (!st.isFile()) {
52891
52991
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
52892
52992
  }
52893
52993
  if (st.size > MAX_FILE_BYTES) {
52894
52994
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
52895
52995
  }
52896
- const buf = import_node_fs27.default.readFileSync(full);
52996
+ const buf = import_node_fs28.default.readFileSync(full);
52897
52997
  const isBinary = buf.includes(0);
52898
52998
  if (isBinary) {
52899
52999
  return {
@@ -52915,20 +53015,20 @@ var WorkspaceBrowser = class {
52915
53015
  };
52916
53016
 
52917
53017
  // src/skills/agents-scanner.ts
52918
- var import_node_fs28 = __toESM(require("fs"), 1);
53018
+ var import_node_fs29 = __toESM(require("fs"), 1);
52919
53019
  var import_node_os9 = __toESM(require("os"), 1);
52920
- var import_node_path30 = __toESM(require("path"), 1);
53020
+ var import_node_path31 = __toESM(require("path"), 1);
52921
53021
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
52922
53022
  function isDirLikeSync2(p2) {
52923
53023
  try {
52924
- return import_node_fs28.default.statSync(p2).isDirectory();
53024
+ return import_node_fs29.default.statSync(p2).isDirectory();
52925
53025
  } catch {
52926
53026
  return false;
52927
53027
  }
52928
53028
  }
52929
53029
  function fileExistsSync(p2) {
52930
53030
  try {
52931
- return import_node_fs28.default.statSync(p2).isFile();
53031
+ return import_node_fs29.default.statSync(p2).isFile();
52932
53032
  } catch {
52933
53033
  return false;
52934
53034
  }
@@ -52936,7 +53036,7 @@ function fileExistsSync(p2) {
52936
53036
  function parseAgentFile(filePath) {
52937
53037
  let content;
52938
53038
  try {
52939
- content = import_node_fs28.default.readFileSync(filePath, "utf8");
53039
+ content = import_node_fs29.default.readFileSync(filePath, "utf8");
52940
53040
  } catch {
52941
53041
  return {};
52942
53042
  }
@@ -52949,16 +53049,16 @@ function parseAgentFile(filePath) {
52949
53049
  function scanAgentsDir(dir, source, seen, out) {
52950
53050
  let entries;
52951
53051
  try {
52952
- entries = import_node_fs28.default.readdirSync(dir, { withFileTypes: true });
53052
+ entries = import_node_fs29.default.readdirSync(dir, { withFileTypes: true });
52953
53053
  } catch {
52954
53054
  return;
52955
53055
  }
52956
53056
  for (const ent of entries) {
52957
53057
  if (!ent.name.endsWith(".md")) continue;
52958
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path30.default.join(dir, ent.name)))) {
53058
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path31.default.join(dir, ent.name)))) {
52959
53059
  continue;
52960
53060
  }
52961
- const filePath = import_node_path30.default.join(dir, ent.name);
53061
+ const filePath = import_node_path31.default.join(dir, ent.name);
52962
53062
  const baseName = ent.name.replace(/\.md$/, "");
52963
53063
  if (seen.has(baseName)) continue;
52964
53064
  seen.add(baseName);
@@ -52976,12 +53076,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
52976
53076
  function walk2(dir, namespaces) {
52977
53077
  let entries;
52978
53078
  try {
52979
- entries = import_node_fs28.default.readdirSync(dir, { withFileTypes: true });
53079
+ entries = import_node_fs29.default.readdirSync(dir, { withFileTypes: true });
52980
53080
  } catch {
52981
53081
  return;
52982
53082
  }
52983
53083
  for (const ent of entries) {
52984
- const childPath = import_node_path30.default.join(dir, ent.name);
53084
+ const childPath = import_node_path31.default.join(dir, ent.name);
52985
53085
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
52986
53086
  walk2(childPath, [...namespaces, ent.name]);
52987
53087
  continue;
@@ -53006,13 +53106,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
53006
53106
  walk2(root, []);
53007
53107
  }
53008
53108
  function readInstalledPlugins2(home) {
53009
- const pluginsDir = import_node_path30.default.join(home, ".claude", "plugins");
53010
- const v2 = import_node_path30.default.join(pluginsDir, "installed_plugins_v2.json");
53011
- const v1 = import_node_path30.default.join(pluginsDir, "installed_plugins.json");
53109
+ const pluginsDir = import_node_path31.default.join(home, ".claude", "plugins");
53110
+ const v2 = import_node_path31.default.join(pluginsDir, "installed_plugins_v2.json");
53111
+ const v1 = import_node_path31.default.join(pluginsDir, "installed_plugins.json");
53012
53112
  let raw = null;
53013
53113
  for (const candidate of [v2, v1]) {
53014
53114
  try {
53015
- raw = import_node_fs28.default.readFileSync(candidate, "utf8");
53115
+ raw = import_node_fs29.default.readFileSync(candidate, "utf8");
53016
53116
  break;
53017
53117
  } catch {
53018
53118
  }
@@ -53037,19 +53137,19 @@ function readInstalledPlugins2(home) {
53037
53137
  return out;
53038
53138
  }
53039
53139
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
53040
- let cur = import_node_path30.default.resolve(startCwd);
53041
- const fsRoot = import_node_path30.default.parse(cur).root;
53140
+ let cur = import_node_path31.default.resolve(startCwd);
53141
+ const fsRoot = import_node_path31.default.parse(cur).root;
53042
53142
  while (true) {
53043
- scanAgentsDir(import_node_path30.default.join(cur, ".claude", "agents"), "project", seen, out);
53143
+ scanAgentsDir(import_node_path31.default.join(cur, ".claude", "agents"), "project", seen, out);
53044
53144
  let hasGit = false;
53045
53145
  try {
53046
- hasGit = import_node_fs28.default.existsSync(import_node_path30.default.join(cur, ".git"));
53146
+ hasGit = import_node_fs29.default.existsSync(import_node_path31.default.join(cur, ".git"));
53047
53147
  } catch {
53048
53148
  }
53049
53149
  if (hasGit) return;
53050
53150
  if (cur === home) return;
53051
53151
  if (cur === fsRoot) return;
53052
- const parent = import_node_path30.default.dirname(cur);
53152
+ const parent = import_node_path31.default.dirname(cur);
53053
53153
  if (parent === cur) return;
53054
53154
  cur = parent;
53055
53155
  }
@@ -53084,7 +53184,7 @@ var AgentsScanner = class {
53084
53184
  }
53085
53185
  const fsBlock = [];
53086
53186
  scanAgentsDir(
53087
- import_node_path30.default.join(this.home, ".claude", "agents"),
53187
+ import_node_path31.default.join(this.home, ".claude", "agents"),
53088
53188
  "global",
53089
53189
  seen,
53090
53190
  fsBlock
@@ -53098,7 +53198,7 @@ var AgentsScanner = class {
53098
53198
  ...this.extraPluginRoots
53099
53199
  ];
53100
53200
  for (const { name, root } of plugins) {
53101
- const agentsRoot = import_node_path30.default.join(root, "agents");
53201
+ const agentsRoot = import_node_path31.default.join(root, "agents");
53102
53202
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
53103
53203
  }
53104
53204
  return [...builtinBlock, ...fsBlock];
@@ -53106,15 +53206,15 @@ var AgentsScanner = class {
53106
53206
  };
53107
53207
 
53108
53208
  // src/observer/session-observer.ts
53109
- var import_node_fs30 = __toESM(require("fs"), 1);
53209
+ var import_node_fs31 = __toESM(require("fs"), 1);
53110
53210
  var import_node_os11 = __toESM(require("os"), 1);
53111
- var import_node_path32 = __toESM(require("path"), 1);
53211
+ var import_node_path33 = __toESM(require("path"), 1);
53112
53212
  init_claude_history();
53113
53213
 
53114
53214
  // src/observer/subagent-meta-observer.ts
53115
- var import_node_fs29 = __toESM(require("fs"), 1);
53215
+ var import_node_fs30 = __toESM(require("fs"), 1);
53116
53216
  var import_node_os10 = __toESM(require("os"), 1);
53117
- var import_node_path31 = __toESM(require("path"), 1);
53217
+ var import_node_path32 = __toESM(require("path"), 1);
53118
53218
  init_claude_history();
53119
53219
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
53120
53220
  var SubagentMetaObserver = class {
@@ -53127,7 +53227,7 @@ var SubagentMetaObserver = class {
53127
53227
  watches = /* @__PURE__ */ new Map();
53128
53228
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
53129
53229
  resolveSubagentDir(cwd, toolSessionId) {
53130
- return import_node_path31.default.join(
53230
+ return import_node_path32.default.join(
53131
53231
  this.home,
53132
53232
  ".claude",
53133
53233
  "projects",
@@ -53157,7 +53257,7 @@ var SubagentMetaObserver = class {
53157
53257
  attachWatcher(w2) {
53158
53258
  if (w2.watcher) return;
53159
53259
  try {
53160
- w2.watcher = import_node_fs29.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
53260
+ w2.watcher = import_node_fs30.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
53161
53261
  if (!name) return;
53162
53262
  const m2 = META_RE.exec(String(name));
53163
53263
  if (!m2) return;
@@ -53169,7 +53269,7 @@ var SubagentMetaObserver = class {
53169
53269
  scan(w2) {
53170
53270
  let entries;
53171
53271
  try {
53172
- entries = import_node_fs29.default.readdirSync(w2.dirPath);
53272
+ entries = import_node_fs30.default.readdirSync(w2.dirPath);
53173
53273
  } catch {
53174
53274
  return;
53175
53275
  }
@@ -53183,10 +53283,10 @@ var SubagentMetaObserver = class {
53183
53283
  if (!m2) return;
53184
53284
  const agentId = m2[1];
53185
53285
  if (w2.emitted.has(agentId)) return;
53186
- const file = import_node_path31.default.join(w2.dirPath, name);
53286
+ const file = import_node_path32.default.join(w2.dirPath, name);
53187
53287
  let raw;
53188
53288
  try {
53189
- raw = import_node_fs29.default.readFileSync(file, "utf8");
53289
+ raw = import_node_fs30.default.readFileSync(file, "utf8");
53190
53290
  } catch {
53191
53291
  return;
53192
53292
  }
@@ -53243,14 +53343,14 @@ var SessionObserver = class {
53243
53343
  metaObserver;
53244
53344
  resolveJsonlPath(cwd, toolSessionId, override) {
53245
53345
  if (override) return override;
53246
- return import_node_path32.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
53346
+ return import_node_path33.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
53247
53347
  }
53248
53348
  start(args) {
53249
53349
  this.stop(args.sessionId);
53250
53350
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
53251
53351
  let size = 0;
53252
53352
  try {
53253
- size = import_node_fs30.default.statSync(filePath).size;
53353
+ size = import_node_fs31.default.statSync(filePath).size;
53254
53354
  } catch {
53255
53355
  }
53256
53356
  const w2 = {
@@ -53263,16 +53363,16 @@ var SessionObserver = class {
53263
53363
  adapter: args.adapter,
53264
53364
  prevIsRejectSentinel: false,
53265
53365
  toolSessionId: args.toolSessionId,
53266
- sawFile: import_node_fs30.default.existsSync(filePath),
53366
+ sawFile: import_node_fs31.default.existsSync(filePath),
53267
53367
  lastRelocateScanMs: 0,
53268
53368
  pendingCwdDerive: false,
53269
53369
  lastDeriveMs: 0
53270
53370
  };
53271
53371
  try {
53272
- import_node_fs30.default.mkdirSync(import_node_path32.default.dirname(filePath), { recursive: true });
53372
+ import_node_fs31.default.mkdirSync(import_node_path33.default.dirname(filePath), { recursive: true });
53273
53373
  } catch {
53274
53374
  }
53275
- w2.watcher = import_node_fs30.default.watch(import_node_path32.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
53375
+ w2.watcher = import_node_fs31.default.watch(import_node_path33.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
53276
53376
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
53277
53377
  this.poll(w2);
53278
53378
  });
@@ -53295,7 +53395,7 @@ var SessionObserver = class {
53295
53395
  // 异常静默吞,不阻塞 watcher 启动
53296
53396
  hydrateMetaTail(w2, maxLines = 200) {
53297
53397
  try {
53298
- const raw = import_node_fs30.default.readFileSync(w2.filePath, "utf8");
53398
+ const raw = import_node_fs31.default.readFileSync(w2.filePath, "utf8");
53299
53399
  if (!raw) return;
53300
53400
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
53301
53401
  if (allLines.length === 0) return;
@@ -53319,7 +53419,7 @@ var SessionObserver = class {
53319
53419
  poll(w2) {
53320
53420
  let size = 0;
53321
53421
  try {
53322
- size = import_node_fs30.default.statSync(w2.filePath).size;
53422
+ size = import_node_fs31.default.statSync(w2.filePath).size;
53323
53423
  } catch {
53324
53424
  if (w2.sawFile) this.maybeRelocate(w2);
53325
53425
  return;
@@ -53330,11 +53430,11 @@ var SessionObserver = class {
53330
53430
  w2.buf = "";
53331
53431
  }
53332
53432
  if (size === w2.lastSize) return;
53333
- const fd = import_node_fs30.default.openSync(w2.filePath, "r");
53433
+ const fd = import_node_fs31.default.openSync(w2.filePath, "r");
53334
53434
  try {
53335
53435
  const len = size - w2.lastSize;
53336
53436
  const buf = Buffer.alloc(len);
53337
- import_node_fs30.default.readSync(fd, buf, 0, len, w2.lastSize);
53437
+ import_node_fs31.default.readSync(fd, buf, 0, len, w2.lastSize);
53338
53438
  w2.lastSize = size;
53339
53439
  w2.buf += buf.toString("utf8");
53340
53440
  let newlineIndex;
@@ -53357,7 +53457,7 @@ var SessionObserver = class {
53357
53457
  }
53358
53458
  }
53359
53459
  } finally {
53360
- import_node_fs30.default.closeSync(fd);
53460
+ import_node_fs31.default.closeSync(fd);
53361
53461
  }
53362
53462
  if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
53363
53463
  }
@@ -53369,7 +53469,7 @@ var SessionObserver = class {
53369
53469
  const now = Date.now();
53370
53470
  if (now - w2.lastRelocateScanMs < 1e3) return;
53371
53471
  w2.lastRelocateScanMs = now;
53372
- const projectsRoot = import_node_path32.default.join(this.home, ".claude", "projects");
53472
+ const projectsRoot = import_node_path33.default.join(this.home, ".claude", "projects");
53373
53473
  const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
53374
53474
  if (!found || found === w2.filePath) return;
53375
53475
  try {
@@ -53378,7 +53478,7 @@ var SessionObserver = class {
53378
53478
  }
53379
53479
  w2.filePath = found;
53380
53480
  try {
53381
- w2.watcher = import_node_fs30.default.watch(import_node_path32.default.dirname(found), { persistent: false }, (_event, changedName) => {
53481
+ w2.watcher = import_node_fs31.default.watch(import_node_path33.default.dirname(found), { persistent: false }, (_event, changedName) => {
53382
53482
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
53383
53483
  this.poll(w2);
53384
53484
  });
@@ -54173,8 +54273,8 @@ async function authenticate(token, deps) {
54173
54273
  }
54174
54274
 
54175
54275
  // src/legacy-cleanup.ts
54176
- var fs35 = __toESM(require("fs/promises"), 1);
54177
- var path37 = __toESM(require("path"), 1);
54276
+ var fs36 = __toESM(require("fs/promises"), 1);
54277
+ var path38 = __toESM(require("path"), 1);
54178
54278
  var LEGACY_FILES = [
54179
54279
  "personal-capability.json",
54180
54280
  "received-capabilities.json",
@@ -54183,9 +54283,9 @@ var LEGACY_FILES = [
54183
54283
  async function cleanupLegacyCapabilityFiles(dataDir, logger) {
54184
54284
  const removed = [];
54185
54285
  for (const name of LEGACY_FILES) {
54186
- const p2 = path37.join(dataDir, name);
54286
+ const p2 = path38.join(dataDir, name);
54187
54287
  try {
54188
- await fs35.unlink(p2);
54288
+ await fs36.unlink(p2);
54189
54289
  removed.push(name);
54190
54290
  logger.debug("legacy capability file removed", { file: name });
54191
54291
  } catch (err) {
@@ -54197,13 +54297,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
54197
54297
  }
54198
54298
 
54199
54299
  // src/inbox/inbox-store.ts
54200
- var fs36 = __toESM(require("fs"), 1);
54201
- var path38 = __toESM(require("path"), 1);
54300
+ var fs37 = __toESM(require("fs"), 1);
54301
+ var path39 = __toESM(require("path"), 1);
54202
54302
  var INBOX_SUBDIR = "inbox";
54203
54303
  var InboxStore = class {
54204
54304
  constructor(dataDir) {
54205
54305
  this.dataDir = dataDir;
54206
- fs36.mkdirSync(this.dirPath(), { recursive: true });
54306
+ fs37.mkdirSync(this.dirPath(), { recursive: true });
54207
54307
  }
54208
54308
  dataDir;
54209
54309
  /**
@@ -54215,7 +54315,7 @@ var InboxStore = class {
54215
54315
  const file = this.filePath(peerDeviceId);
54216
54316
  let raw;
54217
54317
  try {
54218
- raw = fs36.readFileSync(file, "utf8");
54318
+ raw = fs37.readFileSync(file, "utf8");
54219
54319
  } catch (err) {
54220
54320
  if (err?.code === "ENOENT") return [];
54221
54321
  return [];
@@ -54231,7 +54331,7 @@ var InboxStore = class {
54231
54331
  const dir = this.dirPath();
54232
54332
  let entries;
54233
54333
  try {
54234
- entries = fs36.readdirSync(dir);
54334
+ entries = fs37.readdirSync(dir);
54235
54335
  } catch (err) {
54236
54336
  if (err?.code === "ENOENT") return [];
54237
54337
  return [];
@@ -54247,9 +54347,9 @@ var InboxStore = class {
54247
54347
  if (existing.some((m2) => m2.id === message.id)) return;
54248
54348
  const file = this.filePath(message.peerDeviceId);
54249
54349
  const line = JSON.stringify(message) + "\n";
54250
- fs36.appendFileSync(file, line, { mode: 384 });
54350
+ fs37.appendFileSync(file, line, { mode: 384 });
54251
54351
  try {
54252
- fs36.chmodSync(file, 384);
54352
+ fs37.chmodSync(file, 384);
54253
54353
  } catch {
54254
54354
  }
54255
54355
  }
@@ -54279,7 +54379,7 @@ var InboxStore = class {
54279
54379
  removeByPeerDeviceId(peerDeviceId) {
54280
54380
  const file = this.filePath(peerDeviceId);
54281
54381
  try {
54282
- fs36.unlinkSync(file);
54382
+ fs37.unlinkSync(file);
54283
54383
  } catch (err) {
54284
54384
  if (err?.code === "ENOENT") return;
54285
54385
  }
@@ -54288,18 +54388,18 @@ var InboxStore = class {
54288
54388
  const file = this.filePath(peerDeviceId);
54289
54389
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
54290
54390
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
54291
- fs36.writeFileSync(tmp, content, { mode: 384 });
54292
- fs36.renameSync(tmp, file);
54391
+ fs37.writeFileSync(tmp, content, { mode: 384 });
54392
+ fs37.renameSync(tmp, file);
54293
54393
  try {
54294
- fs36.chmodSync(file, 384);
54394
+ fs37.chmodSync(file, 384);
54295
54395
  } catch {
54296
54396
  }
54297
54397
  }
54298
54398
  dirPath() {
54299
- return path38.join(this.dataDir, INBOX_SUBDIR);
54399
+ return path39.join(this.dataDir, INBOX_SUBDIR);
54300
54400
  }
54301
54401
  filePath(peerDeviceId) {
54302
- return path38.join(this.dirPath(), `${peerDeviceId}.jsonl`);
54402
+ return path39.join(this.dirPath(), `${peerDeviceId}.jsonl`);
54303
54403
  }
54304
54404
  };
54305
54405
  function parseAllLines(raw) {
@@ -54387,8 +54487,8 @@ var InboxManager = class {
54387
54487
  };
54388
54488
 
54389
54489
  // src/state/contact-store.ts
54390
- var fs37 = __toESM(require("fs"), 1);
54391
- var path39 = __toESM(require("path"), 1);
54490
+ var fs38 = __toESM(require("fs"), 1);
54491
+ var path40 = __toESM(require("path"), 1);
54392
54492
  var FILE_NAME = "contacts.json";
54393
54493
  var ContactStore = class {
54394
54494
  constructor(dataDir) {
@@ -54398,10 +54498,10 @@ var ContactStore = class {
54398
54498
  contacts = /* @__PURE__ */ new Map();
54399
54499
  load() {
54400
54500
  this.contacts.clear();
54401
- const file = path39.join(this.dataDir, FILE_NAME);
54501
+ const file = path40.join(this.dataDir, FILE_NAME);
54402
54502
  let raw;
54403
54503
  try {
54404
- raw = fs37.readFileSync(file, "utf8");
54504
+ raw = fs38.readFileSync(file, "utf8");
54405
54505
  } catch (err) {
54406
54506
  if (err?.code !== "ENOENT") this.renameBak(file);
54407
54507
  return;
@@ -54470,20 +54570,20 @@ var ContactStore = class {
54470
54570
  return true;
54471
54571
  }
54472
54572
  flush() {
54473
- const file = path39.join(this.dataDir, FILE_NAME);
54573
+ const file = path40.join(this.dataDir, FILE_NAME);
54474
54574
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
54475
54575
  const content = JSON.stringify(
54476
54576
  { contacts: Array.from(this.contacts.values()) },
54477
54577
  null,
54478
54578
  2
54479
54579
  );
54480
- fs37.mkdirSync(this.dataDir, { recursive: true });
54481
- fs37.writeFileSync(tmp, content, { mode: 384 });
54482
- fs37.renameSync(tmp, file);
54580
+ fs38.mkdirSync(this.dataDir, { recursive: true });
54581
+ fs38.writeFileSync(tmp, content, { mode: 384 });
54582
+ fs38.renameSync(tmp, file);
54483
54583
  }
54484
54584
  renameBak(file) {
54485
54585
  try {
54486
- fs37.renameSync(file, `${file}.bak`);
54586
+ fs38.renameSync(file, `${file}.bak`);
54487
54587
  } catch {
54488
54588
  }
54489
54589
  }
@@ -54591,61 +54691,61 @@ async function connectRemote(args) {
54591
54691
  }
54592
54692
 
54593
54693
  // src/migrations/2026-05-20-flatten-sessions.ts
54594
- var fs38 = __toESM(require("fs"), 1);
54595
- var path40 = __toESM(require("path"), 1);
54694
+ var fs39 = __toESM(require("fs"), 1);
54695
+ var path41 = __toESM(require("path"), 1);
54596
54696
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
54597
54697
  function migrateFlattenSessions(opts) {
54598
54698
  const dataDir = opts.dataDir;
54599
54699
  const now = opts.now ?? Date.now;
54600
- const sessionsDir = path40.join(dataDir, "sessions");
54601
- const flagPath = path40.join(sessionsDir, MIGRATION_FLAG_NAME);
54700
+ const sessionsDir = path41.join(dataDir, "sessions");
54701
+ const flagPath = path41.join(sessionsDir, MIGRATION_FLAG_NAME);
54602
54702
  if (existsSync3(flagPath)) {
54603
54703
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
54604
54704
  }
54605
54705
  let movedBare = 0;
54606
54706
  let movedVmOwner = 0;
54607
54707
  let archivedListener = 0;
54608
- const defaultDir = path40.join(sessionsDir, "default");
54708
+ const defaultDir = path41.join(sessionsDir, "default");
54609
54709
  if (existsSync3(defaultDir)) {
54610
54710
  for (const entry of readdirSafe(defaultDir)) {
54611
54711
  if (!entry.endsWith(".json")) continue;
54612
- const src = path40.join(defaultDir, entry);
54613
- const dst = path40.join(sessionsDir, entry);
54614
- fs38.renameSync(src, dst);
54712
+ const src = path41.join(defaultDir, entry);
54713
+ const dst = path41.join(sessionsDir, entry);
54714
+ fs39.renameSync(src, dst);
54615
54715
  movedBare += 1;
54616
54716
  }
54617
54717
  rmdirIfEmpty(defaultDir);
54618
54718
  }
54619
54719
  for (const pid of readdirSafe(sessionsDir)) {
54620
- const personaDir = path40.join(sessionsDir, pid);
54720
+ const personaDir = path41.join(sessionsDir, pid);
54621
54721
  if (!isDir(personaDir)) continue;
54622
54722
  if (pid === "default") continue;
54623
- const ownerSrc = path40.join(personaDir, "owner");
54723
+ const ownerSrc = path41.join(personaDir, "owner");
54624
54724
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
54625
- const ownerDst = path40.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
54626
- fs38.mkdirSync(ownerDst, { recursive: true });
54725
+ const ownerDst = path41.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
54726
+ fs39.mkdirSync(ownerDst, { recursive: true });
54627
54727
  for (const file of readdirSafe(ownerSrc)) {
54628
54728
  if (!file.endsWith(".json")) continue;
54629
- fs38.renameSync(path40.join(ownerSrc, file), path40.join(ownerDst, file));
54729
+ fs39.renameSync(path41.join(ownerSrc, file), path41.join(ownerDst, file));
54630
54730
  movedVmOwner += 1;
54631
54731
  }
54632
54732
  rmdirIfEmpty(ownerSrc);
54633
54733
  }
54634
- const listenerSrc = path40.join(personaDir, "listener");
54734
+ const listenerSrc = path41.join(personaDir, "listener");
54635
54735
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
54636
- const archiveDst = path40.join(dataDir, ".legacy", `listener-${pid}`);
54637
- fs38.mkdirSync(archiveDst, { recursive: true });
54736
+ const archiveDst = path41.join(dataDir, ".legacy", `listener-${pid}`);
54737
+ fs39.mkdirSync(archiveDst, { recursive: true });
54638
54738
  for (const file of readdirSafe(listenerSrc)) {
54639
54739
  if (!file.endsWith(".json")) continue;
54640
- fs38.renameSync(path40.join(listenerSrc, file), path40.join(archiveDst, file));
54740
+ fs39.renameSync(path41.join(listenerSrc, file), path41.join(archiveDst, file));
54641
54741
  archivedListener += 1;
54642
54742
  }
54643
54743
  rmdirIfEmpty(listenerSrc);
54644
54744
  }
54645
54745
  rmdirIfEmpty(personaDir);
54646
54746
  }
54647
- fs38.mkdirSync(sessionsDir, { recursive: true });
54648
- fs38.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
54747
+ fs39.mkdirSync(sessionsDir, { recursive: true });
54748
+ fs39.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
54649
54749
  return {
54650
54750
  skipped: false,
54651
54751
  flagWritten: true,
@@ -54656,7 +54756,7 @@ function migrateFlattenSessions(opts) {
54656
54756
  }
54657
54757
  function existsSync3(p2) {
54658
54758
  try {
54659
- fs38.statSync(p2);
54759
+ fs39.statSync(p2);
54660
54760
  return true;
54661
54761
  } catch {
54662
54762
  return false;
@@ -54664,31 +54764,31 @@ function existsSync3(p2) {
54664
54764
  }
54665
54765
  function isDir(p2) {
54666
54766
  try {
54667
- return fs38.statSync(p2).isDirectory();
54767
+ return fs39.statSync(p2).isDirectory();
54668
54768
  } catch {
54669
54769
  return false;
54670
54770
  }
54671
54771
  }
54672
54772
  function readdirSafe(p2) {
54673
54773
  try {
54674
- return fs38.readdirSync(p2);
54774
+ return fs39.readdirSync(p2);
54675
54775
  } catch {
54676
54776
  return [];
54677
54777
  }
54678
54778
  }
54679
54779
  function rmdirIfEmpty(p2) {
54680
54780
  try {
54681
- fs38.rmdirSync(p2);
54781
+ fs39.rmdirSync(p2);
54682
54782
  } catch {
54683
54783
  }
54684
54784
  }
54685
54785
 
54686
54786
  // src/transport/http-router.ts
54687
- var import_node_fs32 = __toESM(require("fs"), 1);
54688
- var import_node_path36 = __toESM(require("path"), 1);
54787
+ var import_node_fs33 = __toESM(require("fs"), 1);
54788
+ var import_node_path37 = __toESM(require("path"), 1);
54689
54789
 
54690
54790
  // src/attachment/mime.ts
54691
- var import_node_path33 = __toESM(require("path"), 1);
54791
+ var import_node_path34 = __toESM(require("path"), 1);
54692
54792
  var TEXT_PLAIN = "text/plain; charset=utf-8";
54693
54793
  var EXT_TO_NATIVE_MIME = {
54694
54794
  // 图片
@@ -54795,7 +54895,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
54795
54895
  ".mk"
54796
54896
  ]);
54797
54897
  function lookupMime(filePathOrName) {
54798
- const ext = import_node_path33.default.extname(filePathOrName).toLowerCase();
54898
+ const ext = import_node_path34.default.extname(filePathOrName).toLowerCase();
54799
54899
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
54800
54900
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
54801
54901
  return "application/octet-stream";
@@ -54865,8 +54965,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
54865
54965
  }
54866
54966
 
54867
54967
  // src/attachment/upload.ts
54868
- var import_node_fs31 = __toESM(require("fs"), 1);
54869
- var import_node_path34 = __toESM(require("path"), 1);
54968
+ var import_node_fs32 = __toESM(require("fs"), 1);
54969
+ var import_node_path35 = __toESM(require("path"), 1);
54870
54970
  var import_node_crypto8 = __toESM(require("crypto"), 1);
54871
54971
  var import_promises3 = require("stream/promises");
54872
54972
  var UploadError = class extends Error {
@@ -54878,22 +54978,22 @@ var UploadError = class extends Error {
54878
54978
  code;
54879
54979
  };
54880
54980
  function assertValidFileName(fileName) {
54881
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path34.default.basename(fileName)) {
54981
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path35.default.basename(fileName)) {
54882
54982
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
54883
54983
  }
54884
54984
  }
54885
54985
  var HASH_PREFIX_LEN = 16;
54886
54986
  async function writeUploadedAttachment(args) {
54887
54987
  assertValidFileName(args.fileName);
54888
- const attachmentsRoot = import_node_path34.default.join(args.baseDir, ".attachments");
54988
+ const attachmentsRoot = import_node_path35.default.join(args.baseDir, ".attachments");
54889
54989
  try {
54890
- import_node_fs31.default.mkdirSync(attachmentsRoot, { recursive: true });
54990
+ import_node_fs32.default.mkdirSync(attachmentsRoot, { recursive: true });
54891
54991
  } catch (err) {
54892
54992
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
54893
54993
  }
54894
54994
  const hasher = import_node_crypto8.default.createHash("sha256");
54895
54995
  let actualSize = 0;
54896
- const tmpPath = import_node_path34.default.join(
54996
+ const tmpPath = import_node_path35.default.join(
54897
54997
  attachmentsRoot,
54898
54998
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto8.default.randomBytes(4).toString("hex")}`
54899
54999
  );
@@ -54908,18 +55008,18 @@ async function writeUploadedAttachment(args) {
54908
55008
  yield buf;
54909
55009
  }
54910
55010
  },
54911
- import_node_fs31.default.createWriteStream(tmpPath, { mode: 384 })
55011
+ import_node_fs32.default.createWriteStream(tmpPath, { mode: 384 })
54912
55012
  );
54913
55013
  } catch (err) {
54914
55014
  try {
54915
- import_node_fs31.default.unlinkSync(tmpPath);
55015
+ import_node_fs32.default.unlinkSync(tmpPath);
54916
55016
  } catch {
54917
55017
  }
54918
55018
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
54919
55019
  }
54920
55020
  if (actualSize !== args.contentLength) {
54921
55021
  try {
54922
- import_node_fs31.default.unlinkSync(tmpPath);
55022
+ import_node_fs32.default.unlinkSync(tmpPath);
54923
55023
  } catch {
54924
55024
  }
54925
55025
  throw new UploadError(
@@ -54928,34 +55028,34 @@ async function writeUploadedAttachment(args) {
54928
55028
  );
54929
55029
  }
54930
55030
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
54931
- const hashDir = import_node_path34.default.join(attachmentsRoot, attachmentId);
55031
+ const hashDir = import_node_path35.default.join(attachmentsRoot, attachmentId);
54932
55032
  let finalFileName;
54933
55033
  let hashDirExists = false;
54934
55034
  try {
54935
- hashDirExists = import_node_fs31.default.statSync(hashDir).isDirectory();
55035
+ hashDirExists = import_node_fs32.default.statSync(hashDir).isDirectory();
54936
55036
  } catch {
54937
55037
  }
54938
55038
  if (hashDirExists) {
54939
- const existing = import_node_fs31.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
55039
+ const existing = import_node_fs32.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
54940
55040
  finalFileName = existing[0] ?? args.fileName;
54941
55041
  try {
54942
- import_node_fs31.default.unlinkSync(tmpPath);
55042
+ import_node_fs32.default.unlinkSync(tmpPath);
54943
55043
  } catch {
54944
55044
  }
54945
55045
  } else {
54946
55046
  try {
54947
- import_node_fs31.default.mkdirSync(hashDir, { recursive: true });
55047
+ import_node_fs32.default.mkdirSync(hashDir, { recursive: true });
54948
55048
  finalFileName = args.fileName;
54949
- import_node_fs31.default.renameSync(tmpPath, import_node_path34.default.join(hashDir, finalFileName));
55049
+ import_node_fs32.default.renameSync(tmpPath, import_node_path35.default.join(hashDir, finalFileName));
54950
55050
  } catch (err) {
54951
55051
  try {
54952
- import_node_fs31.default.unlinkSync(tmpPath);
55052
+ import_node_fs32.default.unlinkSync(tmpPath);
54953
55053
  } catch {
54954
55054
  }
54955
55055
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
54956
55056
  }
54957
55057
  }
54958
- const absPath = import_node_path34.default.join(hashDir, finalFileName);
55058
+ const absPath = import_node_path35.default.join(hashDir, finalFileName);
54959
55059
  const relPath = absPath;
54960
55060
  args.groupFileStore.upsert(args.scope, args.sessionId, {
54961
55061
  relPath: absPath,
@@ -54970,7 +55070,7 @@ async function writeUploadedAttachment(args) {
54970
55070
 
54971
55071
  // src/extension/import.ts
54972
55072
  var import_promises4 = __toESM(require("fs/promises"), 1);
54973
- var import_node_path35 = __toESM(require("path"), 1);
55073
+ var import_node_path36 = __toESM(require("path"), 1);
54974
55074
  var import_node_os12 = __toESM(require("os"), 1);
54975
55075
  var import_jszip = __toESM(require_lib3(), 1);
54976
55076
  var ImportError = class extends Error {
@@ -54988,7 +55088,7 @@ async function importZip(buf, root) {
54988
55088
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
54989
55089
  }
54990
55090
  for (const name of Object.keys(zip.files)) {
54991
- if (name.includes("..") || name.startsWith("/") || import_node_path35.default.isAbsolute(name)) {
55091
+ if (name.includes("..") || name.startsWith("/") || import_node_path36.default.isAbsolute(name)) {
54992
55092
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
54993
55093
  }
54994
55094
  }
@@ -55021,7 +55121,7 @@ async function importZip(buf, root) {
55021
55121
  );
55022
55122
  }
55023
55123
  }
55024
- const destDir = import_node_path35.default.join(root, manifest.id);
55124
+ const destDir = import_node_path36.default.join(root, manifest.id);
55025
55125
  let destExists = false;
55026
55126
  try {
55027
55127
  await import_promises4.default.access(destDir);
@@ -55031,15 +55131,15 @@ async function importZip(buf, root) {
55031
55131
  if (destExists) {
55032
55132
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
55033
55133
  }
55034
- const stage = await import_promises4.default.mkdtemp(import_node_path35.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
55134
+ const stage = await import_promises4.default.mkdtemp(import_node_path36.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
55035
55135
  try {
55036
55136
  for (const [name, entry] of Object.entries(zip.files)) {
55037
- const dest = import_node_path35.default.join(stage, name);
55137
+ const dest = import_node_path36.default.join(stage, name);
55038
55138
  if (entry.dir) {
55039
55139
  await import_promises4.default.mkdir(dest, { recursive: true });
55040
55140
  continue;
55041
55141
  }
55042
- await import_promises4.default.mkdir(import_node_path35.default.dirname(dest), { recursive: true });
55142
+ await import_promises4.default.mkdir(import_node_path36.default.dirname(dest), { recursive: true });
55043
55143
  const content = await entry.async("nodebuffer");
55044
55144
  await import_promises4.default.writeFile(dest, content);
55045
55145
  }
@@ -55069,7 +55169,7 @@ var SHARE_UI_ASSET_MIME = {
55069
55169
  ".wasm": "application/wasm"
55070
55170
  };
55071
55171
  function shareUiAssetMime(filePath) {
55072
- const ext = import_node_path36.default.extname(filePath).toLowerCase();
55172
+ const ext = import_node_path37.default.extname(filePath).toLowerCase();
55073
55173
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
55074
55174
  }
55075
55175
  var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
@@ -55168,7 +55268,7 @@ function isValidUploadFileName(fileName) {
55168
55268
  if (fileName === "." || fileName === "..") return false;
55169
55269
  if (fileName.startsWith(".")) return false;
55170
55270
  if (fileName.includes("/") || fileName.includes("\\")) return false;
55171
- return fileName === import_node_path36.default.basename(fileName);
55271
+ return fileName === import_node_path37.default.basename(fileName);
55172
55272
  }
55173
55273
  function createHttpRouter(deps) {
55174
55274
  return async (req, res) => {
@@ -55256,7 +55356,7 @@ function createHttpRouter(deps) {
55256
55356
  }
55257
55357
  let buf;
55258
55358
  try {
55259
- buf = await import_node_fs32.default.promises.readFile(abs);
55359
+ buf = await import_node_fs33.default.promises.readFile(abs);
55260
55360
  } catch {
55261
55361
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
55262
55362
  return true;
@@ -55404,7 +55504,7 @@ function createHttpRouter(deps) {
55404
55504
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
55405
55505
  return true;
55406
55506
  }
55407
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path36.default.basename(r.absPath)));
55507
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path37.default.basename(r.absPath)));
55408
55508
  return true;
55409
55509
  }
55410
55510
  const ctx = deps.authResolver.resolveFromHeader(
@@ -55525,7 +55625,7 @@ function createHttpRouter(deps) {
55525
55625
  return true;
55526
55626
  }
55527
55627
  let absPath;
55528
- if (import_node_path36.default.isAbsolute(pathParam)) {
55628
+ if (import_node_path37.default.isAbsolute(pathParam)) {
55529
55629
  absPath = pathParam;
55530
55630
  } else if (deps.sessionStore) {
55531
55631
  const file = deps.sessionStore.read(sid);
@@ -55533,7 +55633,7 @@ function createHttpRouter(deps) {
55533
55633
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
55534
55634
  return true;
55535
55635
  }
55536
- absPath = import_node_path36.default.join(file.cwd, pathParam);
55636
+ absPath = import_node_path37.default.join(file.cwd, pathParam);
55537
55637
  } else {
55538
55638
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
55539
55639
  return true;
@@ -55620,7 +55720,7 @@ function withCtx(ctx, body) {
55620
55720
  function streamFile(res, absPath, logger) {
55621
55721
  let stat;
55622
55722
  try {
55623
- stat = import_node_fs32.default.statSync(absPath);
55723
+ stat = import_node_fs33.default.statSync(absPath);
55624
55724
  } catch (err) {
55625
55725
  const code = err?.code;
55626
55726
  if (code === "ENOENT") {
@@ -55635,7 +55735,7 @@ function streamFile(res, absPath, logger) {
55635
55735
  return;
55636
55736
  }
55637
55737
  const mime = lookupMime(absPath);
55638
- const basename = import_node_path36.default.basename(absPath);
55738
+ const basename = import_node_path37.default.basename(absPath);
55639
55739
  res.writeHead(200, {
55640
55740
  "Content-Type": mime,
55641
55741
  "Content-Length": String(stat.size),
@@ -55643,7 +55743,7 @@ function streamFile(res, absPath, logger) {
55643
55743
  // 防止浏览器把任意 mime 当 html 渲染
55644
55744
  "X-Content-Type-Options": "nosniff"
55645
55745
  });
55646
- const stream = import_node_fs32.default.createReadStream(absPath);
55746
+ const stream = import_node_fs33.default.createReadStream(absPath);
55647
55747
  stream.on("error", (err) => {
55648
55748
  logger?.warn("streamFile read error", { absPath, err: err.message });
55649
55749
  res.destroy();
@@ -55652,8 +55752,8 @@ function streamFile(res, absPath, logger) {
55652
55752
  }
55653
55753
 
55654
55754
  // src/attachment/gc.ts
55655
- var import_node_fs33 = __toESM(require("fs"), 1);
55656
- var import_node_path37 = __toESM(require("path"), 1);
55755
+ var import_node_fs34 = __toESM(require("fs"), 1);
55756
+ var import_node_path38 = __toESM(require("path"), 1);
55657
55757
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
55658
55758
  function runAttachmentGc(args) {
55659
55759
  const now = (args.now ?? Date.now)();
@@ -55662,12 +55762,12 @@ function runAttachmentGc(args) {
55662
55762
  for (const { scope, sessionId } of args.sessionScopes) {
55663
55763
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
55664
55764
  if (entry.stale) continue;
55665
- if (import_node_path37.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
55765
+ if (import_node_path38.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
55666
55766
  }
55667
55767
  }
55668
55768
  const visited = /* @__PURE__ */ new Set();
55669
55769
  for (const { scope, sessionId } of args.sessionScopes) {
55670
- const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path37.default.join(
55770
+ const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path38.default.join(
55671
55771
  args.dataDir,
55672
55772
  "sessions",
55673
55773
  ...scopeSubPath(scope).map(safeFileName),
@@ -55680,28 +55780,28 @@ function runAttachmentGc(args) {
55680
55780
  return true;
55681
55781
  });
55682
55782
  for (const rootDir of roots) {
55683
- const attRoot = import_node_path37.default.join(rootDir, ".attachments");
55783
+ const attRoot = import_node_path38.default.join(rootDir, ".attachments");
55684
55784
  let hashDirs;
55685
55785
  try {
55686
- hashDirs = import_node_fs33.default.readdirSync(attRoot);
55786
+ hashDirs = import_node_fs34.default.readdirSync(attRoot);
55687
55787
  } catch (err) {
55688
55788
  if (err.code === "ENOENT") continue;
55689
55789
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
55690
55790
  continue;
55691
55791
  }
55692
55792
  for (const hashDir of hashDirs) {
55693
- const hashDirAbs = import_node_path37.default.join(attRoot, hashDir);
55793
+ const hashDirAbs = import_node_path38.default.join(attRoot, hashDir);
55694
55794
  let files;
55695
55795
  try {
55696
- files = import_node_fs33.default.readdirSync(hashDirAbs);
55796
+ files = import_node_fs34.default.readdirSync(hashDirAbs);
55697
55797
  } catch {
55698
55798
  continue;
55699
55799
  }
55700
55800
  for (const name of files) {
55701
- const file = import_node_path37.default.join(hashDirAbs, name);
55801
+ const file = import_node_path38.default.join(hashDirAbs, name);
55702
55802
  let stat;
55703
55803
  try {
55704
- stat = import_node_fs33.default.statSync(file);
55804
+ stat = import_node_fs34.default.statSync(file);
55705
55805
  } catch {
55706
55806
  continue;
55707
55807
  }
@@ -55710,18 +55810,18 @@ function runAttachmentGc(args) {
55710
55810
  if (age < ttlMs) continue;
55711
55811
  if (liveAbs.has(file)) continue;
55712
55812
  try {
55713
- import_node_fs33.default.unlinkSync(file);
55813
+ import_node_fs34.default.unlinkSync(file);
55714
55814
  } catch (err) {
55715
55815
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
55716
55816
  }
55717
55817
  }
55718
55818
  try {
55719
- if (import_node_fs33.default.readdirSync(hashDirAbs).length === 0) import_node_fs33.default.rmdirSync(hashDirAbs);
55819
+ if (import_node_fs34.default.readdirSync(hashDirAbs).length === 0) import_node_fs34.default.rmdirSync(hashDirAbs);
55720
55820
  } catch {
55721
55821
  }
55722
55822
  }
55723
55823
  try {
55724
- if (import_node_fs33.default.readdirSync(attRoot).length === 0) import_node_fs33.default.rmdirSync(attRoot);
55824
+ if (import_node_fs34.default.readdirSync(attRoot).length === 0) import_node_fs34.default.rmdirSync(attRoot);
55725
55825
  } catch {
55726
55826
  }
55727
55827
  }
@@ -55729,8 +55829,8 @@ function runAttachmentGc(args) {
55729
55829
  }
55730
55830
 
55731
55831
  // src/attachment/group.ts
55732
- var import_node_fs34 = __toESM(require("fs"), 1);
55733
- var import_node_path38 = __toESM(require("path"), 1);
55832
+ var import_node_fs35 = __toESM(require("fs"), 1);
55833
+ var import_node_path39 = __toESM(require("path"), 1);
55734
55834
  var import_node_crypto9 = __toESM(require("crypto"), 1);
55735
55835
  init_protocol();
55736
55836
  var GroupFileStore = class {
@@ -55742,11 +55842,11 @@ var GroupFileStore = class {
55742
55842
  this.logger = opts.logger;
55743
55843
  }
55744
55844
  rootForScope(scope) {
55745
- return import_node_path38.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
55845
+ return import_node_path39.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
55746
55846
  }
55747
55847
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
55748
55848
  filePath(scope, sessionId) {
55749
- return import_node_path38.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
55849
+ return import_node_path39.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
55750
55850
  }
55751
55851
  cacheKey(scope, sessionId) {
55752
55852
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -55755,7 +55855,7 @@ var GroupFileStore = class {
55755
55855
  readFile(scope, sessionId) {
55756
55856
  const file = this.filePath(scope, sessionId);
55757
55857
  try {
55758
- const raw = import_node_fs34.default.readFileSync(file, "utf8");
55858
+ const raw = import_node_fs35.default.readFileSync(file, "utf8");
55759
55859
  const parsed = JSON.parse(raw);
55760
55860
  if (!Array.isArray(parsed)) {
55761
55861
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -55781,10 +55881,10 @@ var GroupFileStore = class {
55781
55881
  }
55782
55882
  writeFile(scope, sessionId, entries) {
55783
55883
  const file = this.filePath(scope, sessionId);
55784
- import_node_fs34.default.mkdirSync(import_node_path38.default.dirname(file), { recursive: true });
55884
+ import_node_fs35.default.mkdirSync(import_node_path39.default.dirname(file), { recursive: true });
55785
55885
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
55786
- import_node_fs34.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
55787
- import_node_fs34.default.renameSync(tmp, file);
55886
+ import_node_fs35.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
55887
+ import_node_fs35.default.renameSync(tmp, file);
55788
55888
  }
55789
55889
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
55790
55890
  list(scope, sessionId) {
@@ -55870,10 +55970,10 @@ var GroupFileStore = class {
55870
55970
  };
55871
55971
 
55872
55972
  // src/discovery/state-file.ts
55873
- var import_node_fs35 = __toESM(require("fs"), 1);
55874
- var import_node_path39 = __toESM(require("path"), 1);
55973
+ var import_node_fs36 = __toESM(require("fs"), 1);
55974
+ var import_node_path40 = __toESM(require("path"), 1);
55875
55975
  function defaultStateFilePath(dataDir) {
55876
- return import_node_path39.default.join(dataDir, "state.json");
55976
+ return import_node_path40.default.join(dataDir, "state.json");
55877
55977
  }
55878
55978
  function isPidAlive(pid) {
55879
55979
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -55895,7 +55995,7 @@ var StateFileManager = class {
55895
55995
  }
55896
55996
  read() {
55897
55997
  try {
55898
- const raw = import_node_fs35.default.readFileSync(this.file, "utf8");
55998
+ const raw = import_node_fs36.default.readFileSync(this.file, "utf8");
55899
55999
  const parsed = JSON.parse(raw);
55900
56000
  return parsed;
55901
56001
  } catch {
@@ -55909,20 +56009,20 @@ var StateFileManager = class {
55909
56009
  return { status: "stale", existing };
55910
56010
  }
55911
56011
  write(state) {
55912
- import_node_fs35.default.mkdirSync(import_node_path39.default.dirname(this.file), { recursive: true });
56012
+ import_node_fs36.default.mkdirSync(import_node_path40.default.dirname(this.file), { recursive: true });
55913
56013
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
55914
- import_node_fs35.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
55915
- import_node_fs35.default.renameSync(tmp, this.file);
56014
+ import_node_fs36.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
56015
+ import_node_fs36.default.renameSync(tmp, this.file);
55916
56016
  if (process.platform !== "win32") {
55917
56017
  try {
55918
- import_node_fs35.default.chmodSync(this.file, 384);
56018
+ import_node_fs36.default.chmodSync(this.file, 384);
55919
56019
  } catch {
55920
56020
  }
55921
56021
  }
55922
56022
  }
55923
56023
  delete() {
55924
56024
  try {
55925
- import_node_fs35.default.unlinkSync(this.file);
56025
+ import_node_fs36.default.unlinkSync(this.file);
55926
56026
  } catch {
55927
56027
  }
55928
56028
  }
@@ -55936,14 +56036,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
55936
56036
  }
55937
56037
 
55938
56038
  // src/tunnel/tunnel-manager.ts
55939
- var import_node_fs39 = __toESM(require("fs"), 1);
55940
- var import_node_path43 = __toESM(require("path"), 1);
56039
+ var import_node_fs40 = __toESM(require("fs"), 1);
56040
+ var import_node_path44 = __toESM(require("path"), 1);
55941
56041
  var import_node_crypto10 = __toESM(require("crypto"), 1);
55942
56042
  var import_node_child_process9 = require("child_process");
55943
56043
 
55944
56044
  // src/tunnel/tunnel-store.ts
55945
- var import_node_fs36 = __toESM(require("fs"), 1);
55946
- var import_node_path40 = __toESM(require("path"), 1);
56045
+ var import_node_fs37 = __toESM(require("fs"), 1);
56046
+ var import_node_path41 = __toESM(require("path"), 1);
55947
56047
  var TunnelStore = class {
55948
56048
  constructor(filePath) {
55949
56049
  this.filePath = filePath;
@@ -55951,7 +56051,7 @@ var TunnelStore = class {
55951
56051
  filePath;
55952
56052
  async get() {
55953
56053
  try {
55954
- const raw = await import_node_fs36.default.promises.readFile(this.filePath, "utf8");
56054
+ const raw = await import_node_fs37.default.promises.readFile(this.filePath, "utf8");
55955
56055
  const obj = JSON.parse(raw);
55956
56056
  if (!isPersistedTunnel(obj)) return null;
55957
56057
  return obj;
@@ -55962,22 +56062,22 @@ var TunnelStore = class {
55962
56062
  }
55963
56063
  }
55964
56064
  async set(v2) {
55965
- const dir = import_node_path40.default.dirname(this.filePath);
55966
- await import_node_fs36.default.promises.mkdir(dir, { recursive: true });
56065
+ const dir = import_node_path41.default.dirname(this.filePath);
56066
+ await import_node_fs37.default.promises.mkdir(dir, { recursive: true });
55967
56067
  const data = JSON.stringify(v2, null, 2);
55968
56068
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
55969
- await import_node_fs36.default.promises.writeFile(tmp, data, { mode: 384 });
56069
+ await import_node_fs37.default.promises.writeFile(tmp, data, { mode: 384 });
55970
56070
  if (process.platform !== "win32") {
55971
56071
  try {
55972
- await import_node_fs36.default.promises.chmod(tmp, 384);
56072
+ await import_node_fs37.default.promises.chmod(tmp, 384);
55973
56073
  } catch {
55974
56074
  }
55975
56075
  }
55976
- await import_node_fs36.default.promises.rename(tmp, this.filePath);
56076
+ await import_node_fs37.default.promises.rename(tmp, this.filePath);
55977
56077
  }
55978
56078
  async clear() {
55979
56079
  try {
55980
- await import_node_fs36.default.promises.unlink(this.filePath);
56080
+ await import_node_fs37.default.promises.unlink(this.filePath);
55981
56081
  } catch (err) {
55982
56082
  const code = err?.code;
55983
56083
  if (code !== "ENOENT") throw err;
@@ -56072,9 +56172,9 @@ function escape(v2) {
56072
56172
  }
56073
56173
 
56074
56174
  // src/tunnel/frpc-binary.ts
56075
- var import_node_fs37 = __toESM(require("fs"), 1);
56175
+ var import_node_fs38 = __toESM(require("fs"), 1);
56076
56176
  var import_node_os13 = __toESM(require("os"), 1);
56077
- var import_node_path41 = __toESM(require("path"), 1);
56177
+ var import_node_path42 = __toESM(require("path"), 1);
56078
56178
  var import_node_child_process7 = require("child_process");
56079
56179
  var import_node_stream3 = require("stream");
56080
56180
  var import_promises5 = require("stream/promises");
@@ -56106,20 +56206,20 @@ function frpcDownloadUrl(version2, p2) {
56106
56206
  }
56107
56207
  async function ensureFrpcBinary(opts) {
56108
56208
  if (opts.override) {
56109
- if (!import_node_fs37.default.existsSync(opts.override)) {
56209
+ if (!import_node_fs38.default.existsSync(opts.override)) {
56110
56210
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
56111
56211
  }
56112
56212
  return opts.override;
56113
56213
  }
56114
56214
  const version2 = opts.version ?? FRPC_VERSION;
56115
56215
  const platform = opts.platform ?? detectPlatform();
56116
- const binDir = import_node_path41.default.join(opts.dataDir, "bin");
56117
- import_node_fs37.default.mkdirSync(binDir, { recursive: true });
56216
+ const binDir = import_node_path42.default.join(opts.dataDir, "bin");
56217
+ import_node_fs38.default.mkdirSync(binDir, { recursive: true });
56118
56218
  cleanupStaleArtifacts(binDir);
56119
- const stableBin = import_node_path41.default.join(binDir, "frpc");
56120
- if (import_node_fs37.default.existsSync(stableBin)) return stableBin;
56219
+ const stableBin = import_node_path42.default.join(binDir, "frpc");
56220
+ if (import_node_fs38.default.existsSync(stableBin)) return stableBin;
56121
56221
  const partialBin = `${stableBin}.partial`;
56122
- const tarballPath = import_node_path41.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
56222
+ const tarballPath = import_node_path42.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
56123
56223
  try {
56124
56224
  const url = frpcDownloadUrl(version2, platform);
56125
56225
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -56128,8 +56228,8 @@ async function ensureFrpcBinary(opts) {
56128
56228
  } else {
56129
56229
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
56130
56230
  }
56131
- import_node_fs37.default.chmodSync(partialBin, 493);
56132
- import_node_fs37.default.renameSync(partialBin, stableBin);
56231
+ import_node_fs38.default.chmodSync(partialBin, 493);
56232
+ import_node_fs38.default.renameSync(partialBin, stableBin);
56133
56233
  } finally {
56134
56234
  safeUnlink(tarballPath);
56135
56235
  safeUnlink(partialBin);
@@ -56139,15 +56239,15 @@ async function ensureFrpcBinary(opts) {
56139
56239
  function cleanupStaleArtifacts(binDir) {
56140
56240
  let entries;
56141
56241
  try {
56142
- entries = import_node_fs37.default.readdirSync(binDir);
56242
+ entries = import_node_fs38.default.readdirSync(binDir);
56143
56243
  } catch {
56144
56244
  return;
56145
56245
  }
56146
56246
  for (const name of entries) {
56147
56247
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
56148
- const full = import_node_path41.default.join(binDir, name);
56248
+ const full = import_node_path42.default.join(binDir, name);
56149
56249
  try {
56150
- import_node_fs37.default.rmSync(full, { recursive: true, force: true });
56250
+ import_node_fs38.default.rmSync(full, { recursive: true, force: true });
56151
56251
  } catch {
56152
56252
  }
56153
56253
  }
@@ -56155,7 +56255,7 @@ function cleanupStaleArtifacts(binDir) {
56155
56255
  }
56156
56256
  function safeUnlink(p2) {
56157
56257
  try {
56158
- import_node_fs37.default.unlinkSync(p2);
56258
+ import_node_fs38.default.unlinkSync(p2);
56159
56259
  } catch {
56160
56260
  }
56161
56261
  }
@@ -56166,13 +56266,13 @@ async function downloadToFile(url, dest, fetchImpl) {
56166
56266
  if (!res.ok || !res.body) {
56167
56267
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
56168
56268
  }
56169
- const out = import_node_fs37.default.createWriteStream(dest);
56269
+ const out = import_node_fs38.default.createWriteStream(dest);
56170
56270
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
56171
56271
  await (0, import_promises5.pipeline)(nodeStream, out);
56172
56272
  }
56173
56273
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
56174
- const work = import_node_path41.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
56175
- import_node_fs37.default.mkdirSync(work, { recursive: true });
56274
+ const work = import_node_path42.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
56275
+ import_node_fs38.default.mkdirSync(work, { recursive: true });
56176
56276
  try {
56177
56277
  await new Promise((resolve6, reject) => {
56178
56278
  const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -56180,32 +56280,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
56180
56280
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
56181
56281
  });
56182
56282
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
56183
- const src = import_node_path41.default.join(work, dirName, "frpc");
56184
- if (!import_node_fs37.default.existsSync(src)) {
56283
+ const src = import_node_path42.default.join(work, dirName, "frpc");
56284
+ if (!import_node_fs38.default.existsSync(src)) {
56185
56285
  throw new Error(`frpc not found inside tarball at ${src}`);
56186
56286
  }
56187
- import_node_fs37.default.copyFileSync(src, destBin);
56287
+ import_node_fs38.default.copyFileSync(src, destBin);
56188
56288
  } finally {
56189
- import_node_fs37.default.rmSync(work, { recursive: true, force: true });
56289
+ import_node_fs38.default.rmSync(work, { recursive: true, force: true });
56190
56290
  }
56191
56291
  }
56192
56292
 
56193
56293
  // src/tunnel/frpc-process.ts
56194
- var import_node_fs38 = __toESM(require("fs"), 1);
56195
- var import_node_path42 = __toESM(require("path"), 1);
56294
+ var import_node_fs39 = __toESM(require("fs"), 1);
56295
+ var import_node_path43 = __toESM(require("path"), 1);
56196
56296
  var import_node_child_process8 = require("child_process");
56197
56297
  function frpcPidFilePath(dataDir) {
56198
- return import_node_path42.default.join(dataDir, "frpc.pid");
56298
+ return import_node_path43.default.join(dataDir, "frpc.pid");
56199
56299
  }
56200
56300
  function writeFrpcPid(dataDir, pid) {
56201
56301
  try {
56202
- import_node_fs38.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
56302
+ import_node_fs39.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
56203
56303
  } catch {
56204
56304
  }
56205
56305
  }
56206
56306
  function clearFrpcPid(dataDir) {
56207
56307
  try {
56208
- import_node_fs38.default.unlinkSync(frpcPidFilePath(dataDir));
56308
+ import_node_fs39.default.unlinkSync(frpcPidFilePath(dataDir));
56209
56309
  } catch {
56210
56310
  }
56211
56311
  }
@@ -56221,7 +56321,7 @@ function defaultIsPidAlive(pid) {
56221
56321
  }
56222
56322
  function defaultReadPidFile(file) {
56223
56323
  try {
56224
- return import_node_fs38.default.readFileSync(file, "utf8");
56324
+ return import_node_fs39.default.readFileSync(file, "utf8");
56225
56325
  } catch {
56226
56326
  return null;
56227
56327
  }
@@ -56237,7 +56337,7 @@ function defaultSleep2(ms) {
56237
56337
  }
56238
56338
  async function killStaleFrpc(deps) {
56239
56339
  const pidFile = frpcPidFilePath(deps.dataDir);
56240
- const tomlPath = import_node_path42.default.join(deps.dataDir, "frpc.toml");
56340
+ const tomlPath = import_node_path43.default.join(deps.dataDir, "frpc.toml");
56241
56341
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
56242
56342
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
56243
56343
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -56261,7 +56361,7 @@ async function killStaleFrpc(deps) {
56261
56361
  }
56262
56362
  if (victims.size === 0) {
56263
56363
  try {
56264
- import_node_fs38.default.unlinkSync(pidFile);
56364
+ import_node_fs39.default.unlinkSync(pidFile);
56265
56365
  } catch {
56266
56366
  }
56267
56367
  return;
@@ -56272,7 +56372,7 @@ async function killStaleFrpc(deps) {
56272
56372
  }
56273
56373
  await sleep2(deps.reapWaitMs ?? 300);
56274
56374
  try {
56275
- import_node_fs38.default.unlinkSync(pidFile);
56375
+ import_node_fs39.default.unlinkSync(pidFile);
56276
56376
  } catch {
56277
56377
  }
56278
56378
  }
@@ -56309,7 +56409,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
56309
56409
  var TunnelManager = class {
56310
56410
  constructor(deps) {
56311
56411
  this.deps = deps;
56312
- this.store = deps.store ?? new TunnelStore(import_node_path43.default.join(deps.dataDir, "tunnel.json"));
56412
+ this.store = deps.store ?? new TunnelStore(import_node_path44.default.join(deps.dataDir, "tunnel.json"));
56313
56413
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
56314
56414
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
56315
56415
  }
@@ -56436,7 +56536,7 @@ var TunnelManager = class {
56436
56536
  dataDir: this.deps.dataDir,
56437
56537
  override: this.deps.frpcBinaryOverride ?? void 0
56438
56538
  });
56439
- const tomlPath = import_node_path43.default.join(this.deps.dataDir, "frpc.toml");
56539
+ const tomlPath = import_node_path44.default.join(this.deps.dataDir, "frpc.toml");
56440
56540
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto10.default.randomBytes(3).toString("hex")}`;
56441
56541
  const toml = buildFrpcToml({
56442
56542
  serverAddr: t.frpsHost,
@@ -56447,14 +56547,14 @@ var TunnelManager = class {
56447
56547
  localPort,
56448
56548
  logLevel: "info"
56449
56549
  });
56450
- await import_node_fs39.default.promises.writeFile(tomlPath, toml, { mode: 384 });
56550
+ await import_node_fs40.default.promises.writeFile(tomlPath, toml, { mode: 384 });
56451
56551
  const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
56452
56552
  stdio: ["ignore", "pipe", "pipe"]
56453
56553
  });
56454
- const logDir = import_node_path43.default.join(this.deps.dataDir, "log");
56455
- import_node_fs39.default.mkdirSync(logDir, { recursive: true });
56456
- const logFilePath = import_node_path43.default.join(logDir, "frpc.log");
56457
- const logStream = import_node_fs39.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
56554
+ const logDir = import_node_path44.default.join(this.deps.dataDir, "log");
56555
+ import_node_fs40.default.mkdirSync(logDir, { recursive: true });
56556
+ const logFilePath = import_node_path44.default.join(logDir, "frpc.log");
56557
+ const logStream = import_node_fs40.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
56458
56558
  logStream.on("error", () => {
56459
56559
  });
56460
56560
  const tee = (chunk) => {
@@ -56537,27 +56637,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
56537
56637
 
56538
56638
  // src/tunnel/device-key.ts
56539
56639
  var import_node_os14 = __toESM(require("os"), 1);
56540
- var import_node_path44 = __toESM(require("path"), 1);
56640
+ var import_node_path45 = __toESM(require("path"), 1);
56541
56641
  var import_node_crypto11 = __toESM(require("crypto"), 1);
56542
56642
  var DERIVE_SALT = "clawd-tunnel-device-v1";
56543
56643
  function deriveStableDeviceKey(opts = {}) {
56544
56644
  const hostname = opts.hostname ?? import_node_os14.default.hostname();
56545
56645
  const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
56546
56646
  const home = opts.home ?? import_node_os14.default.homedir();
56547
- const defaultDataDir = import_node_path44.default.resolve(import_node_path44.default.join(home, ".clawd"));
56548
- const normalizedDataDir = opts.dataDir ? import_node_path44.default.resolve(opts.dataDir) : null;
56647
+ const defaultDataDir = import_node_path45.default.resolve(import_node_path45.default.join(home, ".clawd"));
56648
+ const normalizedDataDir = opts.dataDir ? import_node_path45.default.resolve(opts.dataDir) : null;
56549
56649
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
56550
56650
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
56551
56651
  return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
56552
56652
  }
56553
56653
 
56554
56654
  // src/auth-store.ts
56555
- var import_node_fs40 = __toESM(require("fs"), 1);
56556
- var import_node_path45 = __toESM(require("path"), 1);
56655
+ var import_node_fs41 = __toESM(require("fs"), 1);
56656
+ var import_node_path46 = __toESM(require("path"), 1);
56557
56657
  var import_node_crypto12 = __toESM(require("crypto"), 1);
56558
56658
  var AUTH_FILE_NAME = "auth.json";
56559
56659
  function authFilePath(dataDir) {
56560
- return import_node_path45.default.join(dataDir, AUTH_FILE_NAME);
56660
+ return import_node_path46.default.join(dataDir, AUTH_FILE_NAME);
56561
56661
  }
56562
56662
  function loadOrCreateAuthFile(opts) {
56563
56663
  const file = authFilePath(opts.dataDir);
@@ -56589,7 +56689,7 @@ function defaultGenerateOwnerPrincipalId() {
56589
56689
  }
56590
56690
  function readAuthFile(file) {
56591
56691
  try {
56592
- const raw = import_node_fs40.default.readFileSync(file, "utf8");
56692
+ const raw = import_node_fs41.default.readFileSync(file, "utf8");
56593
56693
  const parsed = JSON.parse(raw);
56594
56694
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
56595
56695
  return null;
@@ -56609,25 +56709,25 @@ function readAuthFile(file) {
56609
56709
  }
56610
56710
  }
56611
56711
  function writeAuthFile(file, content) {
56612
- import_node_fs40.default.mkdirSync(import_node_path45.default.dirname(file), { recursive: true });
56613
- import_node_fs40.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
56712
+ import_node_fs41.default.mkdirSync(import_node_path46.default.dirname(file), { recursive: true });
56713
+ import_node_fs41.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
56614
56714
  try {
56615
- import_node_fs40.default.chmodSync(file, 384);
56715
+ import_node_fs41.default.chmodSync(file, 384);
56616
56716
  } catch {
56617
56717
  }
56618
56718
  }
56619
56719
 
56620
56720
  // src/owner-profile.ts
56621
- var import_node_fs41 = __toESM(require("fs"), 1);
56721
+ var import_node_fs42 = __toESM(require("fs"), 1);
56622
56722
  var import_node_os15 = __toESM(require("os"), 1);
56623
- var import_node_path46 = __toESM(require("path"), 1);
56723
+ var import_node_path47 = __toESM(require("path"), 1);
56624
56724
  var PROFILE_FILENAME = "profile.json";
56625
56725
  function loadOwnerDisplayName(dataDir) {
56626
56726
  const fallback = import_node_os15.default.userInfo().username;
56627
- const profilePath = import_node_path46.default.join(dataDir, PROFILE_FILENAME);
56727
+ const profilePath = import_node_path47.default.join(dataDir, PROFILE_FILENAME);
56628
56728
  let raw;
56629
56729
  try {
56630
- raw = import_node_fs41.default.readFileSync(profilePath, "utf8");
56730
+ raw = import_node_fs42.default.readFileSync(profilePath, "utf8");
56631
56731
  } catch {
56632
56732
  return fallback;
56633
56733
  }
@@ -56650,18 +56750,18 @@ function loadOwnerDisplayName(dataDir) {
56650
56750
  }
56651
56751
 
56652
56752
  // src/feishu-auth/owner-identity-store.ts
56653
- var import_node_fs42 = __toESM(require("fs"), 1);
56654
- var import_node_path47 = __toESM(require("path"), 1);
56753
+ var import_node_fs43 = __toESM(require("fs"), 1);
56754
+ var import_node_path48 = __toESM(require("path"), 1);
56655
56755
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
56656
56756
  var OwnerIdentityStore = class {
56657
56757
  file;
56658
56758
  constructor(dataDir) {
56659
- this.file = import_node_path47.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
56759
+ this.file = import_node_path48.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
56660
56760
  }
56661
56761
  read() {
56662
56762
  let raw;
56663
56763
  try {
56664
- raw = import_node_fs42.default.readFileSync(this.file, "utf8");
56764
+ raw = import_node_fs43.default.readFileSync(this.file, "utf8");
56665
56765
  } catch {
56666
56766
  return null;
56667
56767
  }
@@ -56689,16 +56789,16 @@ var OwnerIdentityStore = class {
56689
56789
  };
56690
56790
  }
56691
56791
  write(record) {
56692
- import_node_fs42.default.mkdirSync(import_node_path47.default.dirname(this.file), { recursive: true });
56693
- import_node_fs42.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
56792
+ import_node_fs43.default.mkdirSync(import_node_path48.default.dirname(this.file), { recursive: true });
56793
+ import_node_fs43.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
56694
56794
  try {
56695
- import_node_fs42.default.chmodSync(this.file, 384);
56795
+ import_node_fs43.default.chmodSync(this.file, 384);
56696
56796
  } catch {
56697
56797
  }
56698
56798
  }
56699
56799
  clear() {
56700
56800
  try {
56701
- import_node_fs42.default.unlinkSync(this.file);
56801
+ import_node_fs43.default.unlinkSync(this.file);
56702
56802
  } catch (err) {
56703
56803
  const code = err?.code;
56704
56804
  if (code !== "ENOENT") throw err;
@@ -56835,9 +56935,9 @@ var CentralClientError = class extends Error {
56835
56935
  code;
56836
56936
  cause;
56837
56937
  };
56838
- async function centralRequest(opts, path78, init) {
56938
+ async function centralRequest(opts, path79, init) {
56839
56939
  const f = opts.fetchImpl ?? globalThis.fetch;
56840
- const url = `${opts.api.replace(/\/+$/, "")}${path78}`;
56940
+ const url = `${opts.api.replace(/\/+$/, "")}${path79}`;
56841
56941
  const ctrl = new AbortController();
56842
56942
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
56843
56943
  let res;
@@ -57031,8 +57131,8 @@ function verifyConnectToken(args) {
57031
57131
  }
57032
57132
 
57033
57133
  // src/feishu-auth/server-key.ts
57034
- var fs52 = __toESM(require("fs"), 1);
57035
- var path56 = __toESM(require("path"), 1);
57134
+ var fs53 = __toESM(require("fs"), 1);
57135
+ var path57 = __toESM(require("path"), 1);
57036
57136
  var FILE_NAME2 = "server-signing-key.json";
57037
57137
  var ServerKeyStore = class {
57038
57138
  constructor(dataDir) {
@@ -57040,12 +57140,12 @@ var ServerKeyStore = class {
57040
57140
  }
57041
57141
  dataDir;
57042
57142
  filePath() {
57043
- return path56.join(this.dataDir, FILE_NAME2);
57143
+ return path57.join(this.dataDir, FILE_NAME2);
57044
57144
  }
57045
57145
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
57046
57146
  read() {
57047
57147
  try {
57048
- const raw = fs52.readFileSync(this.filePath(), "utf8");
57148
+ const raw = fs53.readFileSync(this.filePath(), "utf8");
57049
57149
  const parsed = JSON.parse(raw);
57050
57150
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
57051
57151
  return parsed.publicKeyPem;
@@ -57060,12 +57160,12 @@ var ServerKeyStore = class {
57060
57160
  publicKeyPem,
57061
57161
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
57062
57162
  };
57063
- fs52.mkdirSync(this.dataDir, { recursive: true });
57064
- fs52.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
57163
+ fs53.mkdirSync(this.dataDir, { recursive: true });
57164
+ fs53.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
57065
57165
  }
57066
57166
  clear() {
57067
57167
  try {
57068
- fs52.unlinkSync(this.filePath());
57168
+ fs53.unlinkSync(this.filePath());
57069
57169
  } catch {
57070
57170
  }
57071
57171
  }
@@ -57078,12 +57178,12 @@ init_protocol();
57078
57178
  init_protocol();
57079
57179
 
57080
57180
  // src/session/fork.ts
57081
- var import_node_fs43 = __toESM(require("fs"), 1);
57181
+ var import_node_fs44 = __toESM(require("fs"), 1);
57082
57182
  var import_node_os16 = __toESM(require("os"), 1);
57083
- var import_node_path48 = __toESM(require("path"), 1);
57183
+ var import_node_path49 = __toESM(require("path"), 1);
57084
57184
  init_claude_history();
57085
57185
  function readJsonlEntries(file) {
57086
- const raw = import_node_fs43.default.readFileSync(file, "utf8");
57186
+ const raw = import_node_fs44.default.readFileSync(file, "utf8");
57087
57187
  const out = [];
57088
57188
  for (const line of raw.split("\n")) {
57089
57189
  const t = line.trim();
@@ -57096,19 +57196,19 @@ function readJsonlEntries(file) {
57096
57196
  return out;
57097
57197
  }
57098
57198
  function forkSession(input) {
57099
- const baseDir = input.baseDir ?? import_node_path48.default.join(import_node_os16.default.homedir(), ".claude");
57100
- let projectDir = import_node_path48.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
57101
- let sourceFile = import_node_path48.default.join(projectDir, `${input.toolSessionId}.jsonl`);
57102
- if (!import_node_fs43.default.existsSync(sourceFile)) {
57199
+ const baseDir = input.baseDir ?? import_node_path49.default.join(import_node_os16.default.homedir(), ".claude");
57200
+ let projectDir = import_node_path49.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
57201
+ let sourceFile = import_node_path49.default.join(projectDir, `${input.toolSessionId}.jsonl`);
57202
+ if (!import_node_fs44.default.existsSync(sourceFile)) {
57103
57203
  const found = findTranscriptByToolSessionId(
57104
- import_node_path48.default.join(baseDir, "projects"),
57204
+ import_node_path49.default.join(baseDir, "projects"),
57105
57205
  input.toolSessionId
57106
57206
  );
57107
57207
  if (!found) {
57108
57208
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
57109
57209
  }
57110
57210
  sourceFile = found;
57111
- projectDir = import_node_path48.default.dirname(found);
57211
+ projectDir = import_node_path49.default.dirname(found);
57112
57212
  }
57113
57213
  const entries = readJsonlEntries(sourceFile);
57114
57214
  const mainEntries = entries.filter((e) => e.isSidechain !== true);
@@ -57137,10 +57237,10 @@ function forkSession(input) {
57137
57237
  }
57138
57238
  forkedLines.push(JSON.stringify(forked));
57139
57239
  }
57140
- const outDir = input.targetCwd ? import_node_path48.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
57141
- const forkedFilePath = import_node_path48.default.join(outDir, `${forkedToolSessionId}.jsonl`);
57142
- import_node_fs43.default.mkdirSync(outDir, { recursive: true });
57143
- import_node_fs43.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
57240
+ const outDir = input.targetCwd ? import_node_path49.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
57241
+ const forkedFilePath = import_node_path49.default.join(outDir, `${forkedToolSessionId}.jsonl`);
57242
+ import_node_fs44.default.mkdirSync(outDir, { recursive: true });
57243
+ import_node_fs44.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
57144
57244
  return { forkedToolSessionId, forkedFilePath };
57145
57245
  }
57146
57246
 
@@ -57599,7 +57699,7 @@ function buildPermissionHandlers(deps) {
57599
57699
  }
57600
57700
 
57601
57701
  // src/handlers/history.ts
57602
- var path59 = __toESM(require("path"), 1);
57702
+ var path60 = __toESM(require("path"), 1);
57603
57703
  init_protocol();
57604
57704
 
57605
57705
  // src/session/recent-dirs.ts
@@ -57617,7 +57717,7 @@ function listRecentDirs(store, limit = 50) {
57617
57717
  }
57618
57718
 
57619
57719
  // src/permission/persona-paths.ts
57620
- var path58 = __toESM(require("path"), 1);
57720
+ var path59 = __toESM(require("path"), 1);
57621
57721
  function getAllowedPersonaIds(grants, action) {
57622
57722
  const ids = /* @__PURE__ */ new Set();
57623
57723
  for (const g2 of grants) {
@@ -57630,42 +57730,42 @@ function getAllowedPersonaIds(grants, action) {
57630
57730
  return ids;
57631
57731
  }
57632
57732
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
57633
- const target = path58.resolve(absPath);
57733
+ const target = path59.resolve(absPath);
57634
57734
  if (userWorkDir) {
57635
- const u = path58.resolve(userWorkDir);
57636
- const usep = u.endsWith(path58.sep) ? "" : path58.sep;
57735
+ const u = path59.resolve(userWorkDir);
57736
+ const usep = u.endsWith(path59.sep) ? "" : path59.sep;
57637
57737
  if (target === u || target.startsWith(u + usep)) return true;
57638
57738
  }
57639
- const root = path58.resolve(personaRoot);
57640
- const sep3 = root.endsWith(path58.sep) ? "" : path58.sep;
57739
+ const root = path59.resolve(personaRoot);
57740
+ const sep3 = root.endsWith(path59.sep) ? "" : path59.sep;
57641
57741
  if (!target.startsWith(root + sep3)) return false;
57642
- const rel = path58.relative(root, target);
57742
+ const rel = path59.relative(root, target);
57643
57743
  if (!rel || rel.startsWith("..")) return false;
57644
- const personaId2 = rel.split(path58.sep)[0];
57744
+ const personaId2 = rel.split(path59.sep)[0];
57645
57745
  if (!personaId2) return false;
57646
57746
  const allowed = getAllowedPersonaIds(grants, action);
57647
57747
  if (allowed === "*") return true;
57648
57748
  return allowed.has(personaId2);
57649
57749
  }
57650
57750
  function personaIdFromPath(absPath, personaRoot) {
57651
- const root = path58.resolve(personaRoot);
57652
- const target = path58.resolve(absPath);
57653
- const sep3 = root.endsWith(path58.sep) ? "" : path58.sep;
57751
+ const root = path59.resolve(personaRoot);
57752
+ const target = path59.resolve(absPath);
57753
+ const sep3 = root.endsWith(path59.sep) ? "" : path59.sep;
57654
57754
  if (!target.startsWith(root + sep3)) return null;
57655
- const rel = path58.relative(root, target);
57755
+ const rel = path59.relative(root, target);
57656
57756
  if (!rel || rel.startsWith("..")) return null;
57657
- const id = rel.split(path58.sep)[0];
57757
+ const id = rel.split(path59.sep)[0];
57658
57758
  return id || null;
57659
57759
  }
57660
57760
  function isPathWithin(dir, absPath) {
57661
- const d = path58.resolve(dir);
57662
- const t = path58.resolve(absPath);
57663
- const sep3 = d.endsWith(path58.sep) ? "" : path58.sep;
57761
+ const d = path59.resolve(dir);
57762
+ const t = path59.resolve(absPath);
57763
+ const sep3 = d.endsWith(path59.sep) ? "" : path59.sep;
57664
57764
  return t === d || t.startsWith(d + sep3);
57665
57765
  }
57666
57766
  function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
57667
57767
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
57668
- return personaIdFromPath(path58.resolve(absPath), personaRoot) === personaId2;
57768
+ return personaIdFromPath(path59.resolve(absPath), personaRoot) === personaId2;
57669
57769
  }
57670
57770
 
57671
57771
  // src/handlers/history.ts
@@ -57717,7 +57817,7 @@ function buildHistoryHandlers(deps) {
57717
57817
  if (!pid) return false;
57718
57818
  return isGuestPathAllowed(
57719
57819
  ctx.grants,
57720
- path59.join(personaRoot, pid),
57820
+ path60.join(personaRoot, pid),
57721
57821
  personaRoot,
57722
57822
  "read",
57723
57823
  userWorkDir
@@ -57729,7 +57829,7 @@ function buildHistoryHandlers(deps) {
57729
57829
  };
57730
57830
  const list = async (frame, _client, ctx) => {
57731
57831
  const args = HistoryListArgs.parse(frame);
57732
- assertGuestPath(ctx, path59.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
57832
+ assertGuestPath(ctx, path60.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
57733
57833
  const sessions = await history.listSessions(args);
57734
57834
  return { response: { type: "history:list", sessions } };
57735
57835
  };
@@ -57773,14 +57873,14 @@ function buildHistoryHandlers(deps) {
57773
57873
  };
57774
57874
  const subagents = async (frame, _client, ctx) => {
57775
57875
  const args = HistorySubagentsArgs.parse(frame);
57776
- assertGuestPath(ctx, path59.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
57876
+ assertGuestPath(ctx, path60.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
57777
57877
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
57778
57878
  const subs = await history.listSubagents(args);
57779
57879
  return { response: { type: "history:subagents", subagents: subs } };
57780
57880
  };
57781
57881
  const subagentRead = async (frame, _client, ctx) => {
57782
57882
  const args = HistorySubagentReadArgs.parse(frame);
57783
- assertGuestPath(ctx, path59.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
57883
+ assertGuestPath(ctx, path60.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
57784
57884
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
57785
57885
  const res = await history.readSubagent(args);
57786
57886
  return { response: { type: "history:subagent-read", ...res } };
@@ -57790,7 +57890,7 @@ function buildHistoryHandlers(deps) {
57790
57890
  if (ctx?.principal.kind === "guest" && personaRoot) {
57791
57891
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
57792
57892
  const filtered = dirs.filter(
57793
- (d) => isGuestPathAllowed(ctx.grants, path59.resolve(d.cwd), personaRoot, "read", userWorkDir)
57893
+ (d) => isGuestPathAllowed(ctx.grants, path60.resolve(d.cwd), personaRoot, "read", userWorkDir)
57794
57894
  );
57795
57895
  return { response: { type: "history:recentDirs", dirs: filtered } };
57796
57896
  }
@@ -57807,7 +57907,7 @@ function buildHistoryHandlers(deps) {
57807
57907
  }
57808
57908
 
57809
57909
  // src/handlers/workspace.ts
57810
- var path60 = __toESM(require("path"), 1);
57910
+ var path61 = __toESM(require("path"), 1);
57811
57911
  var os16 = __toESM(require("os"), 1);
57812
57912
  init_protocol();
57813
57913
  init_protocol();
@@ -57849,22 +57949,22 @@ function buildWorkspaceHandlers(deps) {
57849
57949
  const args = WorkspaceListArgs.parse(frame);
57850
57950
  const isGuest = ctx?.principal.kind === "guest";
57851
57951
  const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
57852
- const resolvedCwd = path60.resolve(args.cwd ?? fallbackCwd);
57853
- const target = args.path ? path60.resolve(resolvedCwd, args.path) : resolvedCwd;
57952
+ const resolvedCwd = path61.resolve(args.cwd ?? fallbackCwd);
57953
+ const target = args.path ? path61.resolve(resolvedCwd, args.path) : resolvedCwd;
57854
57954
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
57855
57955
  const res = workspace.list({ ...args, cwd: resolvedCwd });
57856
57956
  return { response: { type: "workspace:list", ...res } };
57857
57957
  };
57858
57958
  const read = async (frame, _client, ctx) => {
57859
57959
  const args = WorkspaceReadArgs.parse(frame);
57860
- const target = path60.isAbsolute(args.path) ? path60.resolve(args.path) : path60.resolve(args.cwd, args.path);
57960
+ const target = path61.isAbsolute(args.path) ? path61.resolve(args.path) : path61.resolve(args.cwd, args.path);
57861
57961
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
57862
57962
  const res = workspace.read(args);
57863
57963
  return { response: { type: "workspace:read", ...res } };
57864
57964
  };
57865
57965
  const skillsList = async (frame, _client, ctx) => {
57866
57966
  const args = SkillsListArgs.parse(frame);
57867
- const cwdAbs = path60.resolve(args.cwd);
57967
+ const cwdAbs = path61.resolve(args.cwd);
57868
57968
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
57869
57969
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
57870
57970
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -57876,7 +57976,7 @@ function buildWorkspaceHandlers(deps) {
57876
57976
  };
57877
57977
  const agentsList = async (frame, _client, ctx) => {
57878
57978
  const args = AgentsListArgs.parse(frame);
57879
- const cwdAbs = path60.resolve(args.cwd);
57979
+ const cwdAbs = path61.resolve(args.cwd);
57880
57980
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
57881
57981
  if (args.tool === "codex") {
57882
57982
  return { response: { type: "agents:list", agents: [] } };
@@ -57898,20 +57998,20 @@ function buildWorkspaceHandlers(deps) {
57898
57998
  }
57899
57999
 
57900
58000
  // src/handlers/git.ts
57901
- var path62 = __toESM(require("path"), 1);
58001
+ var path63 = __toESM(require("path"), 1);
57902
58002
  init_protocol();
57903
58003
  init_protocol();
57904
58004
 
57905
58005
  // src/workspace/git.ts
57906
58006
  var import_node_child_process10 = require("child_process");
57907
- var import_node_fs44 = __toESM(require("fs"), 1);
57908
- var import_node_path49 = __toESM(require("path"), 1);
58007
+ var import_node_fs45 = __toESM(require("fs"), 1);
58008
+ var import_node_path50 = __toESM(require("path"), 1);
57909
58009
  var import_node_util = require("util");
57910
58010
  var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
57911
58011
  function normalizePath(p2) {
57912
- const resolved = import_node_path49.default.resolve(p2);
58012
+ const resolved = import_node_path50.default.resolve(p2);
57913
58013
  try {
57914
- return import_node_fs44.default.realpathSync(resolved);
58014
+ return import_node_fs45.default.realpathSync(resolved);
57915
58015
  } catch {
57916
58016
  return resolved;
57917
58017
  }
@@ -57985,7 +58085,7 @@ async function listGitBranches(cwd) {
57985
58085
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
57986
58086
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
57987
58087
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
57988
- if (!isGuestPathAllowed(ctx.grants, path62.resolve(cwd), personaRoot, "read", userWorkDir)) {
58088
+ if (!isGuestPathAllowed(ctx.grants, path63.resolve(cwd), personaRoot, "read", userWorkDir)) {
57989
58089
  throw new ClawdError(
57990
58090
  ERROR_CODES.UNAUTHORIZED,
57991
58091
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -58850,21 +58950,21 @@ function computeMethodAccess(args) {
58850
58950
  }
58851
58951
 
58852
58952
  // src/version.ts
58853
- var version = "0.2.293".length > 0 ? "0.2.293" : "dev";
58953
+ var version = "0.2.295".length > 0 ? "0.2.295" : "dev";
58854
58954
 
58855
58955
  // src/cli-probe/probe.ts
58856
- var fs55 = __toESM(require("fs"), 1);
58857
- var path63 = __toESM(require("path"), 1);
58956
+ var fs56 = __toESM(require("fs"), 1);
58957
+ var path64 = __toESM(require("path"), 1);
58858
58958
  var PKG_NAME = "@clawos-dev/clawd";
58859
58959
  var BIN_NAME = "clawd";
58860
58960
  var MAX_PARENT_HOPS = 5;
58861
58961
  function probeGlobalCli(pathEnv) {
58862
58962
  if (!pathEnv) return null;
58863
- for (const dir of pathEnv.split(path63.delimiter)) {
58963
+ for (const dir of pathEnv.split(path64.delimiter)) {
58864
58964
  if (!dir) continue;
58865
58965
  let real;
58866
58966
  try {
58867
- real = fs55.realpathSync(path63.join(dir, BIN_NAME));
58967
+ real = fs56.realpathSync(path64.join(dir, BIN_NAME));
58868
58968
  } catch {
58869
58969
  continue;
58870
58970
  }
@@ -58874,15 +58974,15 @@ function probeGlobalCli(pathEnv) {
58874
58974
  return null;
58875
58975
  }
58876
58976
  function readOwnPackageVersion(entryPath) {
58877
- let dir = path63.dirname(entryPath);
58977
+ let dir = path64.dirname(entryPath);
58878
58978
  for (let i = 0; i < MAX_PARENT_HOPS; i++) {
58879
58979
  try {
58880
- const raw = fs55.readFileSync(path63.join(dir, "package.json"), "utf8");
58980
+ const raw = fs56.readFileSync(path64.join(dir, "package.json"), "utf8");
58881
58981
  const pkg = JSON.parse(raw);
58882
58982
  if (pkg.name !== PKG_NAME) return null;
58883
58983
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
58884
58984
  } catch {
58885
- const parent = path63.dirname(dir);
58985
+ const parent = path64.dirname(dir);
58886
58986
  if (parent === dir) return null;
58887
58987
  dir = parent;
58888
58988
  }
@@ -59040,7 +59140,7 @@ function buildPersonaHandlers(deps) {
59040
59140
  }
59041
59141
 
59042
59142
  // src/handlers/attachment.ts
59043
- var import_node_path50 = __toESM(require("path"), 1);
59143
+ var import_node_path51 = __toESM(require("path"), 1);
59044
59144
  init_protocol();
59045
59145
  init_protocol();
59046
59146
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -59120,12 +59220,12 @@ function buildAttachmentHandlers(deps) {
59120
59220
  `session ${args.sessionId} scope unresolved`
59121
59221
  );
59122
59222
  }
59123
- const cwdAbs = import_node_path50.default.resolve(sessionFile.cwd);
59124
- const candidateAbs = import_node_path50.default.isAbsolute(args.relPath) ? import_node_path50.default.resolve(args.relPath) : import_node_path50.default.resolve(cwdAbs, args.relPath);
59223
+ const cwdAbs = import_node_path51.default.resolve(sessionFile.cwd);
59224
+ const candidateAbs = import_node_path51.default.isAbsolute(args.relPath) ? import_node_path51.default.resolve(args.relPath) : import_node_path51.default.resolve(cwdAbs, args.relPath);
59125
59225
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
59126
59226
  const entries = deps.groupFileStore.list(scope, args.sessionId);
59127
59227
  const entry = entries.find((e) => {
59128
- const storedAbs = import_node_path50.default.isAbsolute(e.relPath) ? import_node_path50.default.resolve(e.relPath) : import_node_path50.default.resolve(cwdAbs, e.relPath);
59228
+ const storedAbs = import_node_path51.default.isAbsolute(e.relPath) ? import_node_path51.default.resolve(e.relPath) : import_node_path51.default.resolve(cwdAbs, e.relPath);
59129
59229
  return storedAbs === candidateAbs && !e.stale;
59130
59230
  });
59131
59231
  if (!entry) {
@@ -59150,7 +59250,7 @@ function buildAttachmentHandlers(deps) {
59150
59250
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
59151
59251
  const f = deps.sessionStore.read(sessionId);
59152
59252
  if (!f) return;
59153
- assertGuestAttachmentPath(ctx, import_node_path50.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
59253
+ assertGuestAttachmentPath(ctx, import_node_path51.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
59154
59254
  }
59155
59255
  const groupAdd = async (frame, _client, ctx) => {
59156
59256
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -59165,8 +59265,8 @@ function buildAttachmentHandlers(deps) {
59165
59265
  if (!scope) {
59166
59266
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
59167
59267
  }
59168
- const cwdAbs = import_node_path50.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
59169
- const candidateAbs = import_node_path50.default.isAbsolute(args.relPath) ? import_node_path50.default.resolve(args.relPath) : import_node_path50.default.resolve(cwdAbs, args.relPath);
59268
+ const cwdAbs = import_node_path51.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
59269
+ const candidateAbs = import_node_path51.default.isAbsolute(args.relPath) ? import_node_path51.default.resolve(args.relPath) : import_node_path51.default.resolve(cwdAbs, args.relPath);
59170
59270
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
59171
59271
  const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
59172
59272
  const size = 0;
@@ -59225,19 +59325,19 @@ function buildAttachmentHandlers(deps) {
59225
59325
 
59226
59326
  // src/handlers/extension.ts
59227
59327
  var import_promises9 = __toESM(require("fs/promises"), 1);
59228
- var import_node_path55 = __toESM(require("path"), 1);
59328
+ var import_node_path56 = __toESM(require("path"), 1);
59229
59329
  init_protocol();
59230
59330
 
59231
59331
  // src/extension/bundle-zip.ts
59232
59332
  var import_promises6 = __toESM(require("fs/promises"), 1);
59233
- var import_node_path51 = __toESM(require("path"), 1);
59333
+ var import_node_path52 = __toESM(require("path"), 1);
59234
59334
  var import_node_crypto14 = __toESM(require("crypto"), 1);
59235
59335
  var import_jszip2 = __toESM(require_lib3(), 1);
59236
59336
  async function bundleExtensionDir(dir) {
59237
59337
  const entries = await listFilesSorted(dir);
59238
59338
  const zip = new import_jszip2.default();
59239
59339
  for (const rel of entries) {
59240
- const abs = import_node_path51.default.join(dir, rel);
59340
+ const abs = import_node_path52.default.join(dir, rel);
59241
59341
  const content = await import_promises6.default.readFile(abs);
59242
59342
  zip.file(rel, content, { date: FIXED_DATE });
59243
59343
  }
@@ -59258,7 +59358,7 @@ async function listFilesSorted(rootDir) {
59258
59358
  return out;
59259
59359
  }
59260
59360
  async function walk(absRoot, relPrefix, out) {
59261
- const dirAbs = import_node_path51.default.join(absRoot, relPrefix);
59361
+ const dirAbs = import_node_path52.default.join(absRoot, relPrefix);
59262
59362
  const entries = await import_promises6.default.readdir(dirAbs, { withFileTypes: true });
59263
59363
  for (const e of entries) {
59264
59364
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -59312,25 +59412,25 @@ function computePublishCheck(args) {
59312
59412
 
59313
59413
  // src/extension/install-flow.ts
59314
59414
  var import_promises7 = __toESM(require("fs/promises"), 1);
59315
- var import_node_path53 = __toESM(require("path"), 1);
59415
+ var import_node_path54 = __toESM(require("path"), 1);
59316
59416
  var import_node_os19 = __toESM(require("os"), 1);
59317
59417
  var import_node_crypto15 = __toESM(require("crypto"), 1);
59318
59418
  var import_jszip3 = __toESM(require_lib3(), 1);
59319
59419
 
59320
59420
  // src/extension/paths.ts
59321
59421
  var import_node_os18 = __toESM(require("os"), 1);
59322
- var import_node_path52 = __toESM(require("path"), 1);
59422
+ var import_node_path53 = __toESM(require("path"), 1);
59323
59423
  function clawdHomeRoot(override) {
59324
- return override ?? process.env.CLAWD_HOME ?? import_node_path52.default.join(import_node_os18.default.homedir(), ".clawd");
59424
+ return override ?? process.env.CLAWD_HOME ?? import_node_path53.default.join(import_node_os18.default.homedir(), ".clawd");
59325
59425
  }
59326
59426
  function extensionsRoot(override) {
59327
- return import_node_path52.default.join(clawdHomeRoot(override), "extensions");
59427
+ return import_node_path53.default.join(clawdHomeRoot(override), "extensions");
59328
59428
  }
59329
59429
  function publishedChannelsFile(override) {
59330
- return import_node_path52.default.join(clawdHomeRoot(override), "extensions-published.json");
59430
+ return import_node_path53.default.join(clawdHomeRoot(override), "extensions-published.json");
59331
59431
  }
59332
59432
  function bundleCacheRoot(override) {
59333
- return import_node_path52.default.join(clawdHomeRoot(override), "extension-bundles");
59433
+ return import_node_path53.default.join(clawdHomeRoot(override), "extension-bundles");
59334
59434
  }
59335
59435
 
59336
59436
  // src/extension/install-flow.ts
@@ -59357,7 +59457,7 @@ async function installFromChannel(args, deps) {
59357
59457
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
59358
59458
  }
59359
59459
  for (const name of Object.keys(zip.files)) {
59360
- if (name.includes("..") || name.startsWith("/") || import_node_path53.default.isAbsolute(name)) {
59460
+ if (name.includes("..") || name.startsWith("/") || import_node_path54.default.isAbsolute(name)) {
59361
59461
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
59362
59462
  }
59363
59463
  }
@@ -59389,7 +59489,7 @@ async function installFromChannel(args, deps) {
59389
59489
  );
59390
59490
  }
59391
59491
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
59392
- const destDir = import_node_path53.default.join(deps.extensionsRoot, localExtId);
59492
+ const destDir = import_node_path54.default.join(deps.extensionsRoot, localExtId);
59393
59493
  let destExists = false;
59394
59494
  try {
59395
59495
  await import_promises7.default.access(destDir);
@@ -59403,16 +59503,16 @@ async function installFromChannel(args, deps) {
59403
59503
  );
59404
59504
  }
59405
59505
  const stage = await import_promises7.default.mkdtemp(
59406
- import_node_path53.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
59506
+ import_node_path54.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
59407
59507
  );
59408
59508
  try {
59409
59509
  for (const [name, entry] of Object.entries(zip.files)) {
59410
- const dest = import_node_path53.default.join(stage, name);
59510
+ const dest = import_node_path54.default.join(stage, name);
59411
59511
  if (entry.dir) {
59412
59512
  await import_promises7.default.mkdir(dest, { recursive: true });
59413
59513
  continue;
59414
59514
  }
59415
- await import_promises7.default.mkdir(import_node_path53.default.dirname(dest), { recursive: true });
59515
+ await import_promises7.default.mkdir(import_node_path54.default.dirname(dest), { recursive: true });
59416
59516
  if (name === "manifest.json") {
59417
59517
  const rewritten = { ...parsed.data, id: localExtId };
59418
59518
  await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -59433,7 +59533,7 @@ async function installFromChannel(args, deps) {
59433
59533
 
59434
59534
  // src/extension/update-flow.ts
59435
59535
  var import_promises8 = __toESM(require("fs/promises"), 1);
59436
- var import_node_path54 = __toESM(require("path"), 1);
59536
+ var import_node_path55 = __toESM(require("path"), 1);
59437
59537
  var import_node_os20 = __toESM(require("os"), 1);
59438
59538
  var import_node_crypto16 = __toESM(require("crypto"), 1);
59439
59539
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -59450,11 +59550,11 @@ async function updateFromChannel(args, deps) {
59450
59550
  channelRef.extId,
59451
59551
  channelRef.ownerPrincipalId
59452
59552
  );
59453
- const liveDir = import_node_path54.default.join(deps.extensionsRoot, localExtId);
59553
+ const liveDir = import_node_path55.default.join(deps.extensionsRoot, localExtId);
59454
59554
  const prevDir = `${liveDir}.prev`;
59455
59555
  let existingVersion;
59456
59556
  try {
59457
- const raw = await import_promises8.default.readFile(import_node_path54.default.join(liveDir, "manifest.json"), "utf8");
59557
+ const raw = await import_promises8.default.readFile(import_node_path55.default.join(liveDir, "manifest.json"), "utf8");
59458
59558
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
59459
59559
  if (!parsed2.success) {
59460
59560
  throw new UpdateError(
@@ -59487,7 +59587,7 @@ async function updateFromChannel(args, deps) {
59487
59587
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
59488
59588
  }
59489
59589
  for (const name of Object.keys(zip.files)) {
59490
- if (name.includes("..") || name.startsWith("/") || import_node_path54.default.isAbsolute(name)) {
59590
+ if (name.includes("..") || name.startsWith("/") || import_node_path55.default.isAbsolute(name)) {
59491
59591
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
59492
59592
  }
59493
59593
  }
@@ -59522,16 +59622,16 @@ async function updateFromChannel(args, deps) {
59522
59622
  await import_promises8.default.rm(prevDir, { recursive: true, force: true });
59523
59623
  await import_promises8.default.rename(liveDir, prevDir);
59524
59624
  const stage = await import_promises8.default.mkdtemp(
59525
- import_node_path54.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
59625
+ import_node_path55.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
59526
59626
  );
59527
59627
  try {
59528
59628
  for (const [name, entry] of Object.entries(zip.files)) {
59529
- const dest = import_node_path54.default.join(stage, name);
59629
+ const dest = import_node_path55.default.join(stage, name);
59530
59630
  if (entry.dir) {
59531
59631
  await import_promises8.default.mkdir(dest, { recursive: true });
59532
59632
  continue;
59533
59633
  }
59534
- await import_promises8.default.mkdir(import_node_path54.default.dirname(dest), { recursive: true });
59634
+ await import_promises8.default.mkdir(import_node_path55.default.dirname(dest), { recursive: true });
59535
59635
  if (name === "manifest.json") {
59536
59636
  const rewritten = { ...parsed.data, id: localExtId };
59537
59637
  await import_promises8.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -59598,7 +59698,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
59598
59698
  );
59599
59699
  }
59600
59700
  }
59601
- const manifestPath = import_node_path55.default.join(root, extId, "manifest.json");
59701
+ const manifestPath = import_node_path56.default.join(root, extId, "manifest.json");
59602
59702
  const manifest = await readManifest(root, extId);
59603
59703
  const next = { ...manifest, version: newVersion };
59604
59704
  const tmp = `${manifestPath}.tmp`;
@@ -59606,7 +59706,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
59606
59706
  await import_promises9.default.rename(tmp, manifestPath);
59607
59707
  }
59608
59708
  async function readManifest(root, extId) {
59609
- const file = import_node_path55.default.join(root, extId, "manifest.json");
59709
+ const file = import_node_path56.default.join(root, extId, "manifest.json");
59610
59710
  let raw;
59611
59711
  try {
59612
59712
  raw = await import_promises9.default.readFile(file, "utf8");
@@ -59690,7 +59790,7 @@ function buildExtensionHandlers(deps) {
59690
59790
  };
59691
59791
  async function buildSnapshotMeta(extId) {
59692
59792
  const manifest = await readManifest(deps.root, extId);
59693
- const { sha256, buffer } = await bundleExtensionDir(import_node_path55.default.join(deps.root, extId));
59793
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path56.default.join(deps.root, extId));
59694
59794
  return { manifest, contentHash: sha256, buffer };
59695
59795
  }
59696
59796
  const publish = async (frame, _client, ctx) => {
@@ -59865,9 +59965,9 @@ function buildExtensionHandlers(deps) {
59865
59965
  }
59866
59966
 
59867
59967
  // src/app-builder/project-store.ts
59868
- var import_node_fs45 = require("fs");
59968
+ var import_node_fs46 = require("fs");
59869
59969
  var import_node_child_process11 = require("child_process");
59870
- var import_node_path56 = require("path");
59970
+ var import_node_path57 = require("path");
59871
59971
  init_protocol();
59872
59972
  var PROJECTS_DIR = "projects";
59873
59973
  var META_FILE = ".clawd-project.json";
@@ -59881,19 +59981,19 @@ var ProjectStore = class {
59881
59981
  root;
59882
59982
  /** projects/<name>/.clawd-project.json 路径 */
59883
59983
  metaPath(name) {
59884
- return (0, import_node_path56.join)(this.projectsRoot(), name, META_FILE);
59984
+ return (0, import_node_path57.join)(this.projectsRoot(), name, META_FILE);
59885
59985
  }
59886
59986
  /** projects/<name>/ 目录路径(cwd 用) */
59887
59987
  projectDir(name) {
59888
- return (0, import_node_path56.join)(this.projectsRoot(), name);
59988
+ return (0, import_node_path57.join)(this.projectsRoot(), name);
59889
59989
  }
59890
59990
  projectsRoot() {
59891
- return (0, import_node_path56.join)(this.root, PROJECTS_DIR);
59991
+ return (0, import_node_path57.join)(this.root, PROJECTS_DIR);
59892
59992
  }
59893
59993
  async list() {
59894
59994
  let entries;
59895
59995
  try {
59896
- entries = await import_node_fs45.promises.readdir(this.projectsRoot());
59996
+ entries = await import_node_fs46.promises.readdir(this.projectsRoot());
59897
59997
  } catch (err) {
59898
59998
  if (err.code === "ENOENT") return [];
59899
59999
  throw err;
@@ -59901,7 +60001,7 @@ var ProjectStore = class {
59901
60001
  const out = [];
59902
60002
  for (const name of entries) {
59903
60003
  try {
59904
- const raw = await import_node_fs45.promises.readFile(this.metaPath(name), "utf8");
60004
+ const raw = await import_node_fs46.promises.readFile(this.metaPath(name), "utf8");
59905
60005
  const json = JSON.parse(raw);
59906
60006
  let migrated = false;
59907
60007
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -59912,7 +60012,7 @@ var ProjectStore = class {
59912
60012
  if (parsed.success) {
59913
60013
  out.push(parsed.data);
59914
60014
  if (migrated) {
59915
- void import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
60015
+ void import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
59916
60016
  });
59917
60017
  }
59918
60018
  }
@@ -59956,8 +60056,8 @@ var ProjectStore = class {
59956
60056
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
59957
60057
  }
59958
60058
  const dir = this.projectDir(name);
59959
- await import_node_fs45.promises.mkdir(dir, { recursive: true });
59960
- await import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
60059
+ await import_node_fs46.promises.mkdir(dir, { recursive: true });
60060
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
59961
60061
  return meta;
59962
60062
  }
59963
60063
  /**
@@ -60000,7 +60100,7 @@ var ProjectStore = class {
60000
60100
  }
60001
60101
  async delete(name) {
60002
60102
  const dir = this.projectDir(name);
60003
- await import_node_fs45.promises.rm(dir, { recursive: true, force: true });
60103
+ await import_node_fs46.promises.rm(dir, { recursive: true, force: true });
60004
60104
  }
60005
60105
  async updatePort(name, newPort) {
60006
60106
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -60016,7 +60116,7 @@ var ProjectStore = class {
60016
60116
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
60017
60117
  }
60018
60118
  const updated = { ...target, port: newPort };
60019
- await import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
60119
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
60020
60120
  return updated;
60021
60121
  }
60022
60122
  /**
@@ -60033,7 +60133,7 @@ var ProjectStore = class {
60033
60133
  if (!validated.success) {
60034
60134
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
60035
60135
  }
60036
- await import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60136
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60037
60137
  return validated.data;
60038
60138
  }
60039
60139
  /**
@@ -60054,7 +60154,7 @@ var ProjectStore = class {
60054
60154
  if (!validated.success) {
60055
60155
  throw new Error(`invalid publishJob: ${validated.error.message}`);
60056
60156
  }
60057
- await import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60157
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60058
60158
  return validated.data;
60059
60159
  }
60060
60160
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -60069,7 +60169,7 @@ var ProjectStore = class {
60069
60169
  if (!validated.success) {
60070
60170
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
60071
60171
  }
60072
- await import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60172
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60073
60173
  return validated.data;
60074
60174
  }
60075
60175
  };
@@ -60190,8 +60290,8 @@ var PublishJobRegistry = class {
60190
60290
 
60191
60291
  // src/app-builder/publish-job-runner.ts
60192
60292
  var import_node_child_process13 = require("child_process");
60193
- var import_node_fs46 = require("fs");
60194
- var import_node_path57 = require("path");
60293
+ var import_node_fs47 = require("fs");
60294
+ var import_node_path58 = require("path");
60195
60295
 
60196
60296
  // src/app-builder/publish-stage-parser.ts
60197
60297
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -60223,10 +60323,10 @@ async function startPublishJob(deps, args) {
60223
60323
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
60224
60324
  }
60225
60325
  const projDir = projectDir(args.name);
60226
- const logPath = (0, import_node_path57.join)(projDir, ".publish.log");
60326
+ const logPath = (0, import_node_path58.join)(projDir, ".publish.log");
60227
60327
  let logStream = null;
60228
60328
  try {
60229
- logStream = (0, import_node_fs46.createWriteStream)(logPath, { flags: "w" });
60329
+ logStream = (0, import_node_fs47.createWriteStream)(logPath, { flags: "w" });
60230
60330
  } catch {
60231
60331
  logStream = null;
60232
60332
  }
@@ -60483,8 +60583,8 @@ async function recoverInterruptedJobs(deps) {
60483
60583
 
60484
60584
  // src/handlers/app-builder.ts
60485
60585
  init_protocol();
60486
- var import_node_path58 = require("path");
60487
- var import_node_fs47 = require("fs");
60586
+ var import_node_path59 = require("path");
60587
+ var import_node_fs48 = require("fs");
60488
60588
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
60489
60589
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
60490
60590
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -60565,7 +60665,7 @@ function buildAppBuilderHandlers(deps) {
60565
60665
  async function listAllUsersProjects() {
60566
60666
  if (!deps.usersRoot || !deps.getStore) return [];
60567
60667
  const getStore = deps.getStore;
60568
- const userIds = await import_node_fs47.promises.readdir(deps.usersRoot).catch(() => []);
60668
+ const userIds = await import_node_fs48.promises.readdir(deps.usersRoot).catch(() => []);
60569
60669
  const perUser = await Promise.all(
60570
60670
  userIds.map((uid) => getStore(uid).list().catch(() => []))
60571
60671
  );
@@ -60634,8 +60734,8 @@ function buildAppBuilderHandlers(deps) {
60634
60734
  const project = await userStore.create(f.name, reservedPorts);
60635
60735
  try {
60636
60736
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
60637
- const templateSrcDir = (0, import_node_path58.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
60638
- const scaffoldScript = (0, import_node_path58.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
60737
+ const templateSrcDir = (0, import_node_path59.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
60738
+ const scaffoldScript = (0, import_node_path59.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
60639
60739
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
60640
60740
  deps.logger?.info("app-builder.scaffold.done", {
60641
60741
  name: project.name,
@@ -60839,7 +60939,7 @@ function buildAppBuilderHandlers(deps) {
60839
60939
  await userStore.clearPublishJob(args.name);
60840
60940
  }
60841
60941
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
60842
- const scriptPath = (0, import_node_path58.join)(deps.deployKitRoot, "scripts", "publish.sh");
60942
+ const scriptPath = (0, import_node_path59.join)(deps.deployKitRoot, "scripts", "publish.sh");
60843
60943
  deps.logger?.info("app-builder.publish.start", {
60844
60944
  name: args.name,
60845
60945
  sessionId: boundSession.sessionId,
@@ -61015,7 +61115,7 @@ function buildVisitorHandlers(deps) {
61015
61115
 
61016
61116
  // src/extension/registry.ts
61017
61117
  var import_promises10 = __toESM(require("fs/promises"), 1);
61018
- var import_node_path59 = __toESM(require("path"), 1);
61118
+ var import_node_path60 = __toESM(require("path"), 1);
61019
61119
  async function loadAll(root) {
61020
61120
  let entries;
61021
61121
  try {
@@ -61028,13 +61128,13 @@ async function loadAll(root) {
61028
61128
  for (const ent of entries) {
61029
61129
  if (!ent.isDirectory()) continue;
61030
61130
  if (ent.name.startsWith(".")) continue;
61031
- records.push(await loadOne(import_node_path59.default.join(root, ent.name), ent.name));
61131
+ records.push(await loadOne(import_node_path60.default.join(root, ent.name), ent.name));
61032
61132
  }
61033
61133
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
61034
61134
  return records;
61035
61135
  }
61036
61136
  async function loadOne(dir, dirName) {
61037
- const manifestPath = import_node_path59.default.join(dir, "manifest.json");
61137
+ const manifestPath = import_node_path60.default.join(dir, "manifest.json");
61038
61138
  let raw;
61039
61139
  try {
61040
61140
  raw = await import_promises10.default.readFile(manifestPath, "utf8");
@@ -61079,7 +61179,7 @@ async function loadOne(dir, dirName) {
61079
61179
 
61080
61180
  // src/extension/uninstall.ts
61081
61181
  var import_promises11 = __toESM(require("fs/promises"), 1);
61082
- var import_node_path60 = __toESM(require("path"), 1);
61182
+ var import_node_path61 = __toESM(require("path"), 1);
61083
61183
  var UninstallError = class extends Error {
61084
61184
  constructor(code, message) {
61085
61185
  super(message);
@@ -61088,7 +61188,7 @@ var UninstallError = class extends Error {
61088
61188
  code;
61089
61189
  };
61090
61190
  async function uninstall(deps) {
61091
- const dir = import_node_path60.default.join(deps.root, deps.extId);
61191
+ const dir = import_node_path61.default.join(deps.root, deps.extId);
61092
61192
  try {
61093
61193
  await import_promises11.default.access(dir);
61094
61194
  } catch {
@@ -61618,7 +61718,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
61618
61718
 
61619
61719
  // src/extension/runtime.ts
61620
61720
  var import_node_child_process16 = require("child_process");
61621
- var import_node_path61 = __toESM(require("path"), 1);
61721
+ var import_node_path62 = __toESM(require("path"), 1);
61622
61722
  var import_promises12 = require("timers/promises");
61623
61723
 
61624
61724
  // src/extension/port-allocator.ts
@@ -61719,7 +61819,7 @@ var Runtime = class {
61719
61819
  /\$CLAWOS_EXT_PORT/g,
61720
61820
  String(port)
61721
61821
  );
61722
- const dir = import_node_path61.default.join(this.root, extId);
61822
+ const dir = import_node_path62.default.join(this.root, extId);
61723
61823
  const env = {
61724
61824
  ...process.env,
61725
61825
  CLAWOS_EXT_PORT: String(port),
@@ -61831,7 +61931,7 @@ ${handle.stderrTail}`
61831
61931
 
61832
61932
  // src/extension/published-channels.ts
61833
61933
  var import_promises13 = __toESM(require("fs/promises"), 1);
61834
- var import_node_path62 = __toESM(require("path"), 1);
61934
+ var import_node_path63 = __toESM(require("path"), 1);
61835
61935
  init_zod();
61836
61936
  var PublishedChannelsError = class extends Error {
61837
61937
  constructor(code, message) {
@@ -61930,7 +62030,7 @@ var PublishedChannelStore = class {
61930
62030
  )
61931
62031
  };
61932
62032
  const tmp = `${this.filePath}.tmp`;
61933
- await import_promises13.default.mkdir(import_node_path62.default.dirname(this.filePath), { recursive: true });
62033
+ await import_promises13.default.mkdir(import_node_path63.default.dirname(this.filePath), { recursive: true });
61934
62034
  await import_promises13.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
61935
62035
  await import_promises13.default.rename(tmp, this.filePath);
61936
62036
  }
@@ -61938,7 +62038,7 @@ var PublishedChannelStore = class {
61938
62038
 
61939
62039
  // src/extension/bundle-cache.ts
61940
62040
  var import_promises14 = __toESM(require("fs/promises"), 1);
61941
- var import_node_path63 = __toESM(require("path"), 1);
62041
+ var import_node_path64 = __toESM(require("path"), 1);
61942
62042
  var BundleCache = class {
61943
62043
  constructor(rootDir) {
61944
62044
  this.rootDir = rootDir;
@@ -61947,14 +62047,14 @@ var BundleCache = class {
61947
62047
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
61948
62048
  async write(snapshotHash, buffer) {
61949
62049
  await import_promises14.default.mkdir(this.rootDir, { recursive: true });
61950
- const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
62050
+ const file = import_node_path64.default.join(this.rootDir, `${snapshotHash}.zip`);
61951
62051
  const tmp = `${file}.tmp`;
61952
62052
  await import_promises14.default.writeFile(tmp, buffer, { mode: 384 });
61953
62053
  await import_promises14.default.rename(tmp, file);
61954
62054
  }
61955
62055
  /** Returns the bundle bytes, or null when the file doesn't exist. */
61956
62056
  async read(snapshotHash) {
61957
- const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
62057
+ const file = import_node_path64.default.join(this.rootDir, `${snapshotHash}.zip`);
61958
62058
  try {
61959
62059
  return await import_promises14.default.readFile(file);
61960
62060
  } catch (e) {
@@ -61964,7 +62064,7 @@ var BundleCache = class {
61964
62064
  }
61965
62065
  /** Idempotent — missing file is not an error. */
61966
62066
  async delete(snapshotHash) {
61967
- const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
62067
+ const file = import_node_path64.default.join(this.rootDir, `${snapshotHash}.zip`);
61968
62068
  await import_promises14.default.rm(file, { force: true });
61969
62069
  }
61970
62070
  };
@@ -61987,24 +62087,24 @@ async function startDaemon(config) {
61987
62087
  sampling: logShippingCfg.sampling,
61988
62088
  homeDir: import_node_os22.default.homedir()
61989
62089
  });
61990
- const logDir = import_node_path64.default.join(config.dataDir, "log");
61991
- import_node_fs48.default.mkdirSync(logDir, { recursive: true });
62090
+ const logDir = import_node_path65.default.join(config.dataDir, "log");
62091
+ import_node_fs49.default.mkdirSync(logDir, { recursive: true });
61992
62092
  const logger = createLogger({
61993
62093
  level: config.logLevel,
61994
- file: import_node_path64.default.join(logDir, "clawd.log"),
62094
+ file: import_node_path65.default.join(logDir, "clawd.log"),
61995
62095
  logClient
61996
62096
  });
61997
62097
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
61998
62098
  const screenIdleProbeLogger = createFileOnlyLogger({
61999
- file: import_node_path64.default.join(logDir, "screen-idle-probe.log"),
62099
+ file: import_node_path65.default.join(logDir, "screen-idle-probe.log"),
62000
62100
  level: "debug"
62001
62101
  });
62002
62102
  logger.info("screen-idle probe logger enabled", {
62003
- file: import_node_path64.default.join(logDir, "screen-idle-probe.log")
62103
+ file: import_node_path65.default.join(logDir, "screen-idle-probe.log")
62004
62104
  });
62005
62105
  const CAP_TARGETS = [
62006
- import_node_path64.default.join(logDir, "clawd.log"),
62007
- import_node_path64.default.join(logDir, "screen-idle-probe.log")
62106
+ import_node_path65.default.join(logDir, "clawd.log"),
62107
+ import_node_path65.default.join(logDir, "screen-idle-probe.log")
62008
62108
  ];
62009
62109
  const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
62010
62110
  const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
@@ -62100,8 +62200,8 @@ async function startDaemon(config) {
62100
62200
  const agents = new AgentsScanner();
62101
62201
  const history = new ClaudeHistoryReader();
62102
62202
  let transport = null;
62103
- const personaStore = new PersonaStore(import_node_path64.default.join(config.dataDir, "personas"));
62104
- const usersRoot = import_node_path64.default.join(config.dataDir, "users");
62203
+ const personaStore = new PersonaStore(import_node_path65.default.join(config.dataDir, "personas"));
62204
+ const usersRoot = import_node_path65.default.join(config.dataDir, "users");
62105
62205
  const defaultsRoot = findDefaultsRoot(logger);
62106
62206
  if (defaultsRoot) {
62107
62207
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -62123,7 +62223,7 @@ async function startDaemon(config) {
62123
62223
  retirePersonaBuilder({ store: personaStore, logger });
62124
62224
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
62125
62225
  const dispatchStore = createDispatchStore({
62126
- filePath: import_node_path64.default.join(config.dataDir, "dispatch.json"),
62226
+ filePath: import_node_path65.default.join(config.dataDir, "dispatch.json"),
62127
62227
  now: () => Date.now(),
62128
62228
  onFlushError: (err) => logger.error("dispatch store flush failed", {
62129
62229
  reason: err instanceof Error ? err.message : String(err)
@@ -62138,18 +62238,18 @@ async function startDaemon(config) {
62138
62238
  now: () => Date.now(),
62139
62239
  onCompleted: (sid) => deliverPendingRef?.(sid)
62140
62240
  });
62141
- const here = typeof __dirname === "string" ? __dirname : import_node_path64.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
62241
+ const here = typeof __dirname === "string" ? __dirname : import_node_path65.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
62142
62242
  const mcpConfigs = [];
62143
62243
  const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
62144
62244
  const dispatchServerCandidates = [
62145
- import_node_path64.default.join(here, "dispatch", "mcp-server.cjs"),
62245
+ import_node_path65.default.join(here, "dispatch", "mcp-server.cjs"),
62146
62246
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
62147
- import_node_path64.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
62247
+ import_node_path65.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
62148
62248
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
62149
62249
  ];
62150
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62250
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62151
62251
  if (dispatchServerScriptPath) {
62152
- const dispatchLogPath = import_node_path64.default.join(logDir, "dispatch-mcp-server.log");
62252
+ const dispatchLogPath = import_node_path65.default.join(logDir, "dispatch-mcp-server.log");
62153
62253
  const dispatchCfgPath = writeDispatchMcpConfig({
62154
62254
  dataDir: config.dataDir,
62155
62255
  serverScriptPath: dispatchServerScriptPath,
@@ -62169,12 +62269,12 @@ async function startDaemon(config) {
62169
62269
  });
62170
62270
  }
62171
62271
  const ticketServerCandidates = [
62172
- import_node_path64.default.join(here, "ticket", "mcp-server.cjs"),
62173
- import_node_path64.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
62272
+ import_node_path65.default.join(here, "ticket", "mcp-server.cjs"),
62273
+ import_node_path65.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
62174
62274
  ];
62175
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62275
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62176
62276
  if (ticketServerScriptPath) {
62177
- const ticketLogPath = import_node_path64.default.join(logDir, "ticket-mcp-server.log");
62277
+ const ticketLogPath = import_node_path65.default.join(logDir, "ticket-mcp-server.log");
62178
62278
  const ticketCfgPath = writeTicketMcpConfig({
62179
62279
  dataDir: config.dataDir,
62180
62280
  serverScriptPath: ticketServerScriptPath,
@@ -62196,12 +62296,12 @@ async function startDaemon(config) {
62196
62296
  });
62197
62297
  }
62198
62298
  const shiftServerCandidates = [
62199
- import_node_path64.default.join(here, "shift", "mcp-server.cjs"),
62200
- import_node_path64.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
62299
+ import_node_path65.default.join(here, "shift", "mcp-server.cjs"),
62300
+ import_node_path65.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
62201
62301
  ];
62202
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62302
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62203
62303
  if (shiftServerScriptPath) {
62204
- const shiftLogPath = import_node_path64.default.join(logDir, "shift-mcp-server.log");
62304
+ const shiftLogPath = import_node_path65.default.join(logDir, "shift-mcp-server.log");
62205
62305
  const shiftCfgPath = await writeShiftMcpConfig({
62206
62306
  dataDir: config.dataDir,
62207
62307
  serverScriptPath: shiftServerScriptPath,
@@ -62222,12 +62322,12 @@ async function startDaemon(config) {
62222
62322
  );
62223
62323
  }
62224
62324
  const inboxServerCandidates = [
62225
- import_node_path64.default.join(here, "inbox", "mcp-server.cjs"),
62226
- import_node_path64.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
62325
+ import_node_path65.default.join(here, "inbox", "mcp-server.cjs"),
62326
+ import_node_path65.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
62227
62327
  ];
62228
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62328
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62229
62329
  if (inboxServerScriptPath) {
62230
- const inboxLogPath = import_node_path64.default.join(logDir, "inbox-mcp-server.log");
62330
+ const inboxLogPath = import_node_path65.default.join(logDir, "inbox-mcp-server.log");
62231
62331
  const inboxCfgPath = await writeInboxMcpConfig({
62232
62332
  dataDir: config.dataDir,
62233
62333
  serverScriptPath: inboxServerScriptPath,
@@ -62248,10 +62348,10 @@ async function startDaemon(config) {
62248
62348
  );
62249
62349
  }
62250
62350
  const peerOpsServerCandidates = [
62251
- import_node_path64.default.join(here, "peer-ops", "mcp-server.cjs"),
62252
- import_node_path64.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
62351
+ import_node_path65.default.join(here, "peer-ops", "mcp-server.cjs"),
62352
+ import_node_path65.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
62253
62353
  ];
62254
- const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62354
+ const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62255
62355
  if (peerOpsServerScriptPath) {
62256
62356
  const peerOpsCfgPath = writePeerOpsMcpConfig({
62257
62357
  dataDir: config.dataDir,
@@ -62271,12 +62371,12 @@ async function startDaemon(config) {
62271
62371
  );
62272
62372
  }
62273
62373
  const rpcToolServerCandidates = [
62274
- import_node_path64.default.join(here, "rpc-tool", "mcp-server.cjs"),
62275
- import_node_path64.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
62374
+ import_node_path65.default.join(here, "rpc-tool", "mcp-server.cjs"),
62375
+ import_node_path65.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
62276
62376
  ];
62277
- const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62377
+ const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62278
62378
  if (rpcToolServerScriptPath) {
62279
- const rpcToolLogPath = import_node_path64.default.join(logDir, "rpc-tool-mcp-server.log");
62379
+ const rpcToolLogPath = import_node_path65.default.join(logDir, "rpc-tool-mcp-server.log");
62280
62380
  const rpcToolCfgPath = writeRpcToolMcpConfig({
62281
62381
  dataDir: config.dataDir,
62282
62382
  serverScriptPath: rpcToolServerScriptPath,
@@ -62297,7 +62397,7 @@ async function startDaemon(config) {
62297
62397
  );
62298
62398
  }
62299
62399
  const shiftStore = createShiftStore({
62300
- filePath: import_node_path64.default.join(config.dataDir, "shift.json"),
62400
+ filePath: import_node_path65.default.join(config.dataDir, "shift.json"),
62301
62401
  ownerIdProvider: () => ownerPrincipalId,
62302
62402
  now: () => Date.now()
62303
62403
  });
@@ -62319,7 +62419,7 @@ async function startDaemon(config) {
62319
62419
  getAdapter,
62320
62420
  historyReader: history,
62321
62421
  dataDir: config.dataDir,
62322
- personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
62422
+ personaRoot: import_node_path65.default.join(config.dataDir, "personas"),
62323
62423
  // dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
62324
62424
  // personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
62325
62425
  getPersonaTool: (personaId2) => personaRegistry.get(personaId2)?.tool,
@@ -62370,10 +62470,10 @@ async function startDaemon(config) {
62370
62470
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
62371
62471
  attachmentGroup: {
62372
62472
  onFileEdit: (input) => {
62373
- const absPath = import_node_path64.default.isAbsolute(input.relPath) ? input.relPath : import_node_path64.default.join(input.cwd, input.relPath);
62473
+ const absPath = import_node_path65.default.isAbsolute(input.relPath) ? input.relPath : import_node_path65.default.join(input.cwd, input.relPath);
62374
62474
  let size = 0;
62375
62475
  try {
62376
- size = import_node_fs48.default.statSync(absPath).size;
62476
+ size = import_node_fs49.default.statSync(absPath).size;
62377
62477
  } catch (err) {
62378
62478
  logger.warn("attachment.onFileEdit stat failed", {
62379
62479
  sessionId: input.sessionId,
@@ -62620,11 +62720,11 @@ async function startDaemon(config) {
62620
62720
  // 'persona/<pid>/owner',default 走 'default'。
62621
62721
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
62622
62722
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
62623
- personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
62723
+ personaRoot: import_node_path65.default.join(config.dataDir, "personas"),
62624
62724
  usersRoot
62625
62725
  },
62626
62726
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
62627
- personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
62727
+ personaRoot: import_node_path65.default.join(config.dataDir, "personas"),
62628
62728
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
62629
62729
  usersRoot,
62630
62730
  // v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
@@ -62750,11 +62850,11 @@ async function startDaemon(config) {
62750
62850
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
62751
62851
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
62752
62852
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
62753
- appBuilderPersonaRoot: import_node_path64.default.join(config.dataDir, "personas", "persona-app-builder"),
62853
+ appBuilderPersonaRoot: import_node_path65.default.join(config.dataDir, "personas", "persona-app-builder"),
62754
62854
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
62755
- deployKitRoot: import_node_path64.default.join(config.dataDir, "deploy-kit"),
62855
+ deployKitRoot: import_node_path65.default.join(config.dataDir, "deploy-kit"),
62756
62856
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
62757
- resolvePersonaRoot: (personaId2) => import_node_path64.default.join(config.dataDir, "personas", personaId2),
62857
+ resolvePersonaRoot: (personaId2) => import_node_path65.default.join(config.dataDir, "personas", personaId2),
62758
62858
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
62759
62859
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
62760
62860
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -62857,7 +62957,7 @@ async function startDaemon(config) {
62857
62957
  });
62858
62958
  shiftScheduler.start();
62859
62959
  logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
62860
- const larkBotStore = createLarkBotBindingStore(import_node_path64.default.join(config.dataDir, "personas"));
62960
+ const larkBotStore = createLarkBotBindingStore(import_node_path65.default.join(config.dataDir, "personas"));
62861
62961
  const larkBotCloud = createLarkBotCloudClient({
62862
62962
  api: config.clawosApi ?? DEFAULT_CLAWOS_API,
62863
62963
  apiKey: resolveClawdTicketsApiKey(),
@@ -62868,6 +62968,9 @@ async function startDaemon(config) {
62868
62968
  manager,
62869
62969
  cloud: larkBotCloud,
62870
62970
  store: larkBotStore,
62971
+ fetchResource: (appId, messageId, fileKey, maxBytes) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes),
62972
+ // 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
62973
+ mediaRootFor: (chatId) => import_node_path65.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
62871
62974
  logger: {
62872
62975
  warn: (msg) => logger.warn(msg),
62873
62976
  info: (msg) => logger.info(msg)
@@ -63150,8 +63253,8 @@ async function startDaemon(config) {
63150
63253
  const lines = [
63151
63254
  `Tunnel: ${r.url}`,
63152
63255
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
63153
- `Frpc config: ${import_node_path64.default.join(config.dataDir, "frpc.toml")}`,
63154
- `Frpc log: ${import_node_path64.default.join(logDir, "frpc.log")}`
63256
+ `Frpc config: ${import_node_path65.default.join(config.dataDir, "frpc.toml")}`,
63257
+ `Frpc log: ${import_node_path65.default.join(logDir, "frpc.log")}`
63155
63258
  ];
63156
63259
  const width = Math.max(...lines.map((l) => l.length));
63157
63260
  const bar = "\u2550".repeat(width + 4);
@@ -63164,8 +63267,8 @@ ${bar}
63164
63267
 
63165
63268
  `);
63166
63269
  try {
63167
- const connectPath = import_node_path64.default.join(config.dataDir, "connect.txt");
63168
- import_node_fs48.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
63270
+ const connectPath = import_node_path65.default.join(config.dataDir, "connect.txt");
63271
+ import_node_fs49.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
63169
63272
  } catch {
63170
63273
  }
63171
63274
  } catch (err) {
@@ -63239,9 +63342,9 @@ ${bar}
63239
63342
  };
63240
63343
  }
63241
63344
  function migrateDropPersonsDir(dataDir) {
63242
- const dir = import_node_path64.default.join(dataDir, "persons");
63345
+ const dir = import_node_path65.default.join(dataDir, "persons");
63243
63346
  try {
63244
- import_node_fs48.default.rmSync(dir, { recursive: true, force: true });
63347
+ import_node_fs49.default.rmSync(dir, { recursive: true, force: true });
63245
63348
  } catch {
63246
63349
  }
63247
63350
  }