@clawos-dev/clawd 0.2.293 → 0.2.294

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
 
@@ -47181,8 +47187,9 @@ var SessionManager = class {
47181
47187
  // guest 三件套:creatorPrincipalId=capId(scopeForFile 回落防线)、
47182
47188
  // creatorDisplayName(reducer guest 分支硬性要求,缺则 spawn 抛)
47183
47189
  creatorPrincipalId: capId,
47184
- creatorDisplayName: `\u98DE\u4E66\u7FA4\xB7${args.chatName ?? args.chatId}`,
47190
+ creatorDisplayName: `${(args.chatType ?? "group") === "p2p" ? "\u98DE\u4E66\u79C1\u804A" : "\u98DE\u4E66\u7FA4"}\xB7${args.chatName ?? args.chatId}`,
47185
47191
  larkChatId: args.chatId,
47192
+ larkChatType: args.chatType ?? "group",
47186
47193
  ...args.chatName ? { larkChatName: args.chatName } : {},
47187
47194
  createdAt: now,
47188
47195
  updatedAt: now
@@ -47752,7 +47759,10 @@ var PersonaStore = class {
47752
47759
  /**
47753
47760
  * persona 基线注入:Edit-deny(绝对 '~/<persona>/**')并进 permissions.deny + 剥掉历史相对
47754
47761
  * 'Edit(./**)';persona 目录 '~/' 路径 union 进 sandbox.filesystem.allowRead(guest 读权
47755
- * 落盘即真源,compose 不再运行时注入——spec 2026-08-06-persona-workdir-discipline §1-§2)。
47762
+ * 落盘即真源,compose 不再运行时注入——spec 2026-08-06-persona-workdir-discipline §1-§2);
47763
+ * `Read(~/<persona>/**)` union 进 permissions.allow——OS 沙箱层可读只放行了 Bash,CC 自带
47764
+ * Read 工具在最严格 base(dontAsk + 无 allow)下仍被拒,工具层与 OS 层必须同构放行
47765
+ * (guest「自由读 persona 目录、只写自己 userWorkDir」,spec 2026-08-06-lark-dm §P10 通用化)。
47756
47766
  */
47757
47767
  injectPersonaBaseline(personaId2, settings) {
47758
47768
  const dir = this.personaDir(personaId2);
@@ -47760,6 +47770,9 @@ var PersonaStore = class {
47760
47770
  const rule = personaEditDeny(dir);
47761
47771
  const rawDeny = s.permissions && typeof s.permissions === "object" ? s.permissions.deny : void 0;
47762
47772
  const prevDeny = (Array.isArray(rawDeny) ? rawDeny : []).filter((r) => r !== "Edit(./**)" && r !== rule);
47773
+ const readRule = personaReadAllow(dir);
47774
+ const rawAllow = s.permissions && typeof s.permissions === "object" ? s.permissions.allow : void 0;
47775
+ const prevAllow = (Array.isArray(rawAllow) ? rawAllow : []).filter((r) => r !== readRule);
47763
47776
  const readPath = tildePath(dir);
47764
47777
  const sandbox = s.sandbox && typeof s.sandbox === "object" && !Array.isArray(s.sandbox) ? s.sandbox : {};
47765
47778
  const rawFs = sandbox.filesystem;
@@ -47770,6 +47783,7 @@ var PersonaStore = class {
47770
47783
  ...s,
47771
47784
  permissions: {
47772
47785
  ...s.permissions && typeof s.permissions === "object" ? s.permissions : {},
47786
+ allow: [...prevAllow, readRule],
47773
47787
  deny: [...prevDeny, rule]
47774
47788
  },
47775
47789
  sandbox: { ...sandbox, filesystem: { ...filesystem, allowRead: [...prevRead, readPath] } }
@@ -48654,7 +48668,10 @@ function migrateSandboxAllowRead(args) {
48654
48668
  continue;
48655
48669
  }
48656
48670
  const allowRead = raw.sandbox?.filesystem?.allowRead;
48657
- if (Array.isArray(allowRead) && allowRead.includes(readPath)) continue;
48671
+ const permAllow = raw.permissions?.allow;
48672
+ const readRule = personaReadAllow(args.store.personaDirPath(personaId2));
48673
+ if (Array.isArray(allowRead) && allowRead.includes(readPath) && Array.isArray(permAllow) && permAllow.includes(readRule))
48674
+ continue;
48658
48675
  args.store.writeSandboxSettings(personaId2, raw);
48659
48676
  n++;
48660
48677
  args.logger.info("persona.sandbox.allow-read.migrated", { personaId: personaId2 });
@@ -49301,8 +49318,8 @@ function turnStartInput(text) {
49301
49318
  const items = [];
49302
49319
  let leftover = text;
49303
49320
  for (const m2 of text.matchAll(SKILL_RE)) {
49304
- const [marker, name, path78] = m2;
49305
- items.push({ type: "skill", name, path: path78 });
49321
+ const [marker, name, path79] = m2;
49322
+ items.push({ type: "skill", name, path: path79 });
49306
49323
  leftover = leftover.replace(marker, "");
49307
49324
  }
49308
49325
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -51996,14 +52013,62 @@ function createLarkBotCloudClient(opts) {
51996
52013
  async claimEvents() {
51997
52014
  const json = await request("POST", "/api/lark-bot/events/claim");
51998
52015
  return json.items ?? [];
52016
+ },
52017
+ async fetchResource(appId, messageId, fileKey, maxBytes) {
52018
+ const ac = new AbortController();
52019
+ const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? 15e3);
52020
+ const qs = new URLSearchParams({
52021
+ appId,
52022
+ messageId,
52023
+ fileKey,
52024
+ ...maxBytes ? { maxBytes: String(maxBytes) } : {}
52025
+ }).toString();
52026
+ let res;
52027
+ try {
52028
+ res = await f(`${base}/api/lark-bot/resource?${qs}`, {
52029
+ method: "GET",
52030
+ signal: ac.signal,
52031
+ headers: {
52032
+ authorization: `Bearer ${opts.apiKey}`,
52033
+ "x-did": encodeURIComponent(opts.deviceId),
52034
+ "x-name": encodeURIComponent(opts.displayName),
52035
+ "x-scene": "daemon"
52036
+ }
52037
+ });
52038
+ } catch (err) {
52039
+ throw new LarkBotCloudError(`lark-bot cloud resource fetch failed: ${err.message}`);
52040
+ } finally {
52041
+ clearTimeout(timer);
52042
+ }
52043
+ if (!res.ok) {
52044
+ throw new LarkBotCloudError(`lark-bot cloud resource: HTTP ${res.status}`, res.status);
52045
+ }
52046
+ const data = Buffer.from(await res.arrayBuffer());
52047
+ const contentType = res.headers.get("content-type") ?? "application/octet-stream";
52048
+ return { data, contentType };
51999
52049
  }
52000
52050
  };
52001
52051
  }
52002
52052
 
52003
52053
  // src/lark-bot-connector/chat-router.ts
52054
+ var import_node_fs27 = __toESM(require("fs"), 1);
52055
+ var import_node_path28 = __toESM(require("path"), 1);
52004
52056
  init_protocol();
52005
52057
  var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
52006
52058
  var DEFAULT_TURN_TIMEOUT_MS = 10 * 60 * 1e3;
52059
+ var MAX_IMAGE_BYTES = 8 * 1024 * 1024;
52060
+ var EXT_BY_MIME = {
52061
+ "image/png": "png",
52062
+ "image/jpeg": "jpg",
52063
+ "image/gif": "gif",
52064
+ "image/webp": "webp"
52065
+ };
52066
+ var IMAGE_OVERSIZE_TEXT = "[\u56FE\u7247\u6D88\u606F\uFF0C\u8D85\u51FA\u5927\u5C0F\u9650\u5236]";
52067
+ var IMAGE_UNAVAILABLE_TEXT = "[\u56FE\u7247\u6D88\u606F\uFF0C\u6682\u4E0D\u652F\u6301\u67E5\u770B]";
52068
+ function safeMediaName(raw) {
52069
+ const cleaned = raw.replace(/[^a-zA-Z0-9_\-.]/g, "_").replace(/^\.+/, (d) => "_".repeat(d.length));
52070
+ return (cleaned || "msg").replace(/\.\./g, "__");
52071
+ }
52007
52072
  function createLarkChatRouter(deps) {
52008
52073
  const timeoutMs = deps.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;
52009
52074
  const replyDelays = deps.replyRetryDelaysMs ?? [2e3, 8e3, 3e4];
@@ -52016,7 +52081,34 @@ function createLarkChatRouter(deps) {
52016
52081
  return;
52017
52082
  }
52018
52083
  const speaker = env.senderName || env.senderOpenId || "\u672A\u77E5\u6210\u5458";
52019
- const body = env.text?.trim() ? env.text : "[\u975E\u6587\u672C\u6D88\u606F]";
52084
+ const imageLines = [];
52085
+ for (const [i, key] of (env.imageKeys ?? []).entries()) {
52086
+ try {
52087
+ if (!deps.fetchResource || !deps.mediaRootFor) throw new Error("resource pipeline not wired");
52088
+ const r = await deps.fetchResource(env.appId, env.messageId, key, MAX_IMAGE_BYTES);
52089
+ if (r.data.byteLength > MAX_IMAGE_BYTES) {
52090
+ deps.logger?.warn(`larkBot image oversize ${key}: ${r.data.byteLength}B`);
52091
+ imageLines.push(IMAGE_OVERSIZE_TEXT);
52092
+ continue;
52093
+ }
52094
+ const ext = EXT_BY_MIME[r.contentType];
52095
+ if (!ext) {
52096
+ deps.logger?.warn(`larkBot image unsupported mime ${key}: ${r.contentType}`);
52097
+ imageLines.push(IMAGE_UNAVAILABLE_TEXT);
52098
+ continue;
52099
+ }
52100
+ const dir = deps.mediaRootFor(env.chatId);
52101
+ import_node_fs27.default.mkdirSync(dir, { recursive: true });
52102
+ const p2 = import_node_path28.default.join(dir, `${safeMediaName(env.messageId)}-${i}.${ext}`);
52103
+ import_node_fs27.default.writeFileSync(p2, r.data);
52104
+ imageLines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
52105
+ } catch (err) {
52106
+ deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
52107
+ imageLines.push(IMAGE_UNAVAILABLE_TEXT);
52108
+ }
52109
+ }
52110
+ const rawBody = [env.text?.trim(), ...imageLines].filter(Boolean).join("\n");
52111
+ const body = rawBody || "[\u975E\u6587\u672C\u6D88\u606F]";
52020
52112
  const text = `${body}
52021
52113
 
52022
52114
  ${formatLarkSpeakerReminder(speaker)}`;
@@ -52024,6 +52116,7 @@ ${formatLarkSpeakerReminder(speaker)}`;
52024
52116
  personaId: env.personaId,
52025
52117
  chatId: env.chatId,
52026
52118
  chatName: env.chatName,
52119
+ chatType: env.chatType ?? "group",
52027
52120
  senderOpenId: env.senderOpenId ?? "",
52028
52121
  senderName: env.senderName ?? env.senderOpenId ?? "\u672A\u77E5\u6210\u5458",
52029
52122
  text
@@ -52786,7 +52879,7 @@ var CodexHistoryReader = class {
52786
52879
  };
52787
52880
 
52788
52881
  // src/tools/codex-skills.ts
52789
- var import_node_path28 = __toESM(require("path"), 1);
52882
+ var import_node_path29 = __toESM(require("path"), 1);
52790
52883
  function str3(v2) {
52791
52884
  return typeof v2 === "string" ? v2 : void 0;
52792
52885
  }
@@ -52801,13 +52894,13 @@ function mapSkillsListResponse(res) {
52801
52894
  const r = s ?? {};
52802
52895
  const name = str3(r.name);
52803
52896
  if (!name) continue;
52804
- const path78 = str3(r.path);
52897
+ const path79 = str3(r.path);
52805
52898
  const description = str3(r.description);
52806
52899
  const isPlugin = name.includes(":");
52807
52900
  out.push({
52808
52901
  name,
52809
52902
  source: isPlugin ? "plugin" : "project",
52810
- ...path78 ? { path: path78 } : {},
52903
+ ...path79 ? { path: path79 } : {},
52811
52904
  ...description ? { description } : {},
52812
52905
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
52813
52906
  });
@@ -52823,30 +52916,30 @@ async function listCodexSkills(cwd, deps = {}) {
52823
52916
  // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
52824
52917
  // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
52825
52918
  beforeRequest: (client) => {
52826
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path28.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
52919
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path29.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
52827
52920
  }
52828
52921
  });
52829
52922
  return mapSkillsListResponse(res);
52830
52923
  }
52831
52924
 
52832
52925
  // src/workspace/browser.ts
52833
- var import_node_fs27 = __toESM(require("fs"), 1);
52926
+ var import_node_fs28 = __toESM(require("fs"), 1);
52834
52927
  var import_node_os8 = __toESM(require("os"), 1);
52835
- var import_node_path29 = __toESM(require("path"), 1);
52928
+ var import_node_path30 = __toESM(require("path"), 1);
52836
52929
  init_protocol();
52837
52930
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
52838
52931
  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)) {
52932
+ const absCwd = import_node_path30.default.resolve(cwd);
52933
+ const joined = import_node_path30.default.resolve(absCwd, subpath ?? ".");
52934
+ const rel = import_node_path30.default.relative(absCwd, joined);
52935
+ if (rel.startsWith("..") || import_node_path30.default.isAbsolute(rel)) {
52843
52936
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
52844
52937
  }
52845
52938
  return joined;
52846
52939
  }
52847
52940
  function ensureCwd(cwd) {
52848
52941
  try {
52849
- const stat = import_node_fs27.default.statSync(cwd);
52942
+ const stat = import_node_fs28.default.statSync(cwd);
52850
52943
  if (!stat.isDirectory()) {
52851
52944
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
52852
52945
  }
@@ -52860,7 +52953,7 @@ var WorkspaceBrowser = class {
52860
52953
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
52861
52954
  ensureCwd(cwd);
52862
52955
  const full = resolveInsideCwd(cwd, args.path);
52863
- const dirents = import_node_fs27.default.readdirSync(full, { withFileTypes: true });
52956
+ const dirents = import_node_fs28.default.readdirSync(full, { withFileTypes: true });
52864
52957
  const entries = [];
52865
52958
  for (const d of dirents) {
52866
52959
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -52870,7 +52963,7 @@ var WorkspaceBrowser = class {
52870
52963
  mtime: ""
52871
52964
  };
52872
52965
  try {
52873
- const st = import_node_fs27.default.statSync(import_node_path29.default.join(full, d.name));
52966
+ const st = import_node_fs28.default.statSync(import_node_path30.default.join(full, d.name));
52874
52967
  entry.mtime = new Date(st.mtimeMs).toISOString();
52875
52968
  if (d.isFile()) entry.size = st.size;
52876
52969
  } catch {
@@ -52886,14 +52979,14 @@ var WorkspaceBrowser = class {
52886
52979
  read(args) {
52887
52980
  ensureCwd(args.cwd);
52888
52981
  const full = resolveInsideCwd(args.cwd, args.path);
52889
- const st = import_node_fs27.default.statSync(full);
52982
+ const st = import_node_fs28.default.statSync(full);
52890
52983
  if (!st.isFile()) {
52891
52984
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
52892
52985
  }
52893
52986
  if (st.size > MAX_FILE_BYTES) {
52894
52987
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
52895
52988
  }
52896
- const buf = import_node_fs27.default.readFileSync(full);
52989
+ const buf = import_node_fs28.default.readFileSync(full);
52897
52990
  const isBinary = buf.includes(0);
52898
52991
  if (isBinary) {
52899
52992
  return {
@@ -52915,20 +53008,20 @@ var WorkspaceBrowser = class {
52915
53008
  };
52916
53009
 
52917
53010
  // src/skills/agents-scanner.ts
52918
- var import_node_fs28 = __toESM(require("fs"), 1);
53011
+ var import_node_fs29 = __toESM(require("fs"), 1);
52919
53012
  var import_node_os9 = __toESM(require("os"), 1);
52920
- var import_node_path30 = __toESM(require("path"), 1);
53013
+ var import_node_path31 = __toESM(require("path"), 1);
52921
53014
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
52922
53015
  function isDirLikeSync2(p2) {
52923
53016
  try {
52924
- return import_node_fs28.default.statSync(p2).isDirectory();
53017
+ return import_node_fs29.default.statSync(p2).isDirectory();
52925
53018
  } catch {
52926
53019
  return false;
52927
53020
  }
52928
53021
  }
52929
53022
  function fileExistsSync(p2) {
52930
53023
  try {
52931
- return import_node_fs28.default.statSync(p2).isFile();
53024
+ return import_node_fs29.default.statSync(p2).isFile();
52932
53025
  } catch {
52933
53026
  return false;
52934
53027
  }
@@ -52936,7 +53029,7 @@ function fileExistsSync(p2) {
52936
53029
  function parseAgentFile(filePath) {
52937
53030
  let content;
52938
53031
  try {
52939
- content = import_node_fs28.default.readFileSync(filePath, "utf8");
53032
+ content = import_node_fs29.default.readFileSync(filePath, "utf8");
52940
53033
  } catch {
52941
53034
  return {};
52942
53035
  }
@@ -52949,16 +53042,16 @@ function parseAgentFile(filePath) {
52949
53042
  function scanAgentsDir(dir, source, seen, out) {
52950
53043
  let entries;
52951
53044
  try {
52952
- entries = import_node_fs28.default.readdirSync(dir, { withFileTypes: true });
53045
+ entries = import_node_fs29.default.readdirSync(dir, { withFileTypes: true });
52953
53046
  } catch {
52954
53047
  return;
52955
53048
  }
52956
53049
  for (const ent of entries) {
52957
53050
  if (!ent.name.endsWith(".md")) continue;
52958
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path30.default.join(dir, ent.name)))) {
53051
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path31.default.join(dir, ent.name)))) {
52959
53052
  continue;
52960
53053
  }
52961
- const filePath = import_node_path30.default.join(dir, ent.name);
53054
+ const filePath = import_node_path31.default.join(dir, ent.name);
52962
53055
  const baseName = ent.name.replace(/\.md$/, "");
52963
53056
  if (seen.has(baseName)) continue;
52964
53057
  seen.add(baseName);
@@ -52976,12 +53069,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
52976
53069
  function walk2(dir, namespaces) {
52977
53070
  let entries;
52978
53071
  try {
52979
- entries = import_node_fs28.default.readdirSync(dir, { withFileTypes: true });
53072
+ entries = import_node_fs29.default.readdirSync(dir, { withFileTypes: true });
52980
53073
  } catch {
52981
53074
  return;
52982
53075
  }
52983
53076
  for (const ent of entries) {
52984
- const childPath = import_node_path30.default.join(dir, ent.name);
53077
+ const childPath = import_node_path31.default.join(dir, ent.name);
52985
53078
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
52986
53079
  walk2(childPath, [...namespaces, ent.name]);
52987
53080
  continue;
@@ -53006,13 +53099,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
53006
53099
  walk2(root, []);
53007
53100
  }
53008
53101
  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");
53102
+ const pluginsDir = import_node_path31.default.join(home, ".claude", "plugins");
53103
+ const v2 = import_node_path31.default.join(pluginsDir, "installed_plugins_v2.json");
53104
+ const v1 = import_node_path31.default.join(pluginsDir, "installed_plugins.json");
53012
53105
  let raw = null;
53013
53106
  for (const candidate of [v2, v1]) {
53014
53107
  try {
53015
- raw = import_node_fs28.default.readFileSync(candidate, "utf8");
53108
+ raw = import_node_fs29.default.readFileSync(candidate, "utf8");
53016
53109
  break;
53017
53110
  } catch {
53018
53111
  }
@@ -53037,19 +53130,19 @@ function readInstalledPlugins2(home) {
53037
53130
  return out;
53038
53131
  }
53039
53132
  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;
53133
+ let cur = import_node_path31.default.resolve(startCwd);
53134
+ const fsRoot = import_node_path31.default.parse(cur).root;
53042
53135
  while (true) {
53043
- scanAgentsDir(import_node_path30.default.join(cur, ".claude", "agents"), "project", seen, out);
53136
+ scanAgentsDir(import_node_path31.default.join(cur, ".claude", "agents"), "project", seen, out);
53044
53137
  let hasGit = false;
53045
53138
  try {
53046
- hasGit = import_node_fs28.default.existsSync(import_node_path30.default.join(cur, ".git"));
53139
+ hasGit = import_node_fs29.default.existsSync(import_node_path31.default.join(cur, ".git"));
53047
53140
  } catch {
53048
53141
  }
53049
53142
  if (hasGit) return;
53050
53143
  if (cur === home) return;
53051
53144
  if (cur === fsRoot) return;
53052
- const parent = import_node_path30.default.dirname(cur);
53145
+ const parent = import_node_path31.default.dirname(cur);
53053
53146
  if (parent === cur) return;
53054
53147
  cur = parent;
53055
53148
  }
@@ -53084,7 +53177,7 @@ var AgentsScanner = class {
53084
53177
  }
53085
53178
  const fsBlock = [];
53086
53179
  scanAgentsDir(
53087
- import_node_path30.default.join(this.home, ".claude", "agents"),
53180
+ import_node_path31.default.join(this.home, ".claude", "agents"),
53088
53181
  "global",
53089
53182
  seen,
53090
53183
  fsBlock
@@ -53098,7 +53191,7 @@ var AgentsScanner = class {
53098
53191
  ...this.extraPluginRoots
53099
53192
  ];
53100
53193
  for (const { name, root } of plugins) {
53101
- const agentsRoot = import_node_path30.default.join(root, "agents");
53194
+ const agentsRoot = import_node_path31.default.join(root, "agents");
53102
53195
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
53103
53196
  }
53104
53197
  return [...builtinBlock, ...fsBlock];
@@ -53106,15 +53199,15 @@ var AgentsScanner = class {
53106
53199
  };
53107
53200
 
53108
53201
  // src/observer/session-observer.ts
53109
- var import_node_fs30 = __toESM(require("fs"), 1);
53202
+ var import_node_fs31 = __toESM(require("fs"), 1);
53110
53203
  var import_node_os11 = __toESM(require("os"), 1);
53111
- var import_node_path32 = __toESM(require("path"), 1);
53204
+ var import_node_path33 = __toESM(require("path"), 1);
53112
53205
  init_claude_history();
53113
53206
 
53114
53207
  // src/observer/subagent-meta-observer.ts
53115
- var import_node_fs29 = __toESM(require("fs"), 1);
53208
+ var import_node_fs30 = __toESM(require("fs"), 1);
53116
53209
  var import_node_os10 = __toESM(require("os"), 1);
53117
- var import_node_path31 = __toESM(require("path"), 1);
53210
+ var import_node_path32 = __toESM(require("path"), 1);
53118
53211
  init_claude_history();
53119
53212
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
53120
53213
  var SubagentMetaObserver = class {
@@ -53127,7 +53220,7 @@ var SubagentMetaObserver = class {
53127
53220
  watches = /* @__PURE__ */ new Map();
53128
53221
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
53129
53222
  resolveSubagentDir(cwd, toolSessionId) {
53130
- return import_node_path31.default.join(
53223
+ return import_node_path32.default.join(
53131
53224
  this.home,
53132
53225
  ".claude",
53133
53226
  "projects",
@@ -53157,7 +53250,7 @@ var SubagentMetaObserver = class {
53157
53250
  attachWatcher(w2) {
53158
53251
  if (w2.watcher) return;
53159
53252
  try {
53160
- w2.watcher = import_node_fs29.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
53253
+ w2.watcher = import_node_fs30.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
53161
53254
  if (!name) return;
53162
53255
  const m2 = META_RE.exec(String(name));
53163
53256
  if (!m2) return;
@@ -53169,7 +53262,7 @@ var SubagentMetaObserver = class {
53169
53262
  scan(w2) {
53170
53263
  let entries;
53171
53264
  try {
53172
- entries = import_node_fs29.default.readdirSync(w2.dirPath);
53265
+ entries = import_node_fs30.default.readdirSync(w2.dirPath);
53173
53266
  } catch {
53174
53267
  return;
53175
53268
  }
@@ -53183,10 +53276,10 @@ var SubagentMetaObserver = class {
53183
53276
  if (!m2) return;
53184
53277
  const agentId = m2[1];
53185
53278
  if (w2.emitted.has(agentId)) return;
53186
- const file = import_node_path31.default.join(w2.dirPath, name);
53279
+ const file = import_node_path32.default.join(w2.dirPath, name);
53187
53280
  let raw;
53188
53281
  try {
53189
- raw = import_node_fs29.default.readFileSync(file, "utf8");
53282
+ raw = import_node_fs30.default.readFileSync(file, "utf8");
53190
53283
  } catch {
53191
53284
  return;
53192
53285
  }
@@ -53243,14 +53336,14 @@ var SessionObserver = class {
53243
53336
  metaObserver;
53244
53337
  resolveJsonlPath(cwd, toolSessionId, override) {
53245
53338
  if (override) return override;
53246
- return import_node_path32.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
53339
+ return import_node_path33.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
53247
53340
  }
53248
53341
  start(args) {
53249
53342
  this.stop(args.sessionId);
53250
53343
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
53251
53344
  let size = 0;
53252
53345
  try {
53253
- size = import_node_fs30.default.statSync(filePath).size;
53346
+ size = import_node_fs31.default.statSync(filePath).size;
53254
53347
  } catch {
53255
53348
  }
53256
53349
  const w2 = {
@@ -53263,16 +53356,16 @@ var SessionObserver = class {
53263
53356
  adapter: args.adapter,
53264
53357
  prevIsRejectSentinel: false,
53265
53358
  toolSessionId: args.toolSessionId,
53266
- sawFile: import_node_fs30.default.existsSync(filePath),
53359
+ sawFile: import_node_fs31.default.existsSync(filePath),
53267
53360
  lastRelocateScanMs: 0,
53268
53361
  pendingCwdDerive: false,
53269
53362
  lastDeriveMs: 0
53270
53363
  };
53271
53364
  try {
53272
- import_node_fs30.default.mkdirSync(import_node_path32.default.dirname(filePath), { recursive: true });
53365
+ import_node_fs31.default.mkdirSync(import_node_path33.default.dirname(filePath), { recursive: true });
53273
53366
  } catch {
53274
53367
  }
53275
- w2.watcher = import_node_fs30.default.watch(import_node_path32.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
53368
+ w2.watcher = import_node_fs31.default.watch(import_node_path33.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
53276
53369
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
53277
53370
  this.poll(w2);
53278
53371
  });
@@ -53295,7 +53388,7 @@ var SessionObserver = class {
53295
53388
  // 异常静默吞,不阻塞 watcher 启动
53296
53389
  hydrateMetaTail(w2, maxLines = 200) {
53297
53390
  try {
53298
- const raw = import_node_fs30.default.readFileSync(w2.filePath, "utf8");
53391
+ const raw = import_node_fs31.default.readFileSync(w2.filePath, "utf8");
53299
53392
  if (!raw) return;
53300
53393
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
53301
53394
  if (allLines.length === 0) return;
@@ -53319,7 +53412,7 @@ var SessionObserver = class {
53319
53412
  poll(w2) {
53320
53413
  let size = 0;
53321
53414
  try {
53322
- size = import_node_fs30.default.statSync(w2.filePath).size;
53415
+ size = import_node_fs31.default.statSync(w2.filePath).size;
53323
53416
  } catch {
53324
53417
  if (w2.sawFile) this.maybeRelocate(w2);
53325
53418
  return;
@@ -53330,11 +53423,11 @@ var SessionObserver = class {
53330
53423
  w2.buf = "";
53331
53424
  }
53332
53425
  if (size === w2.lastSize) return;
53333
- const fd = import_node_fs30.default.openSync(w2.filePath, "r");
53426
+ const fd = import_node_fs31.default.openSync(w2.filePath, "r");
53334
53427
  try {
53335
53428
  const len = size - w2.lastSize;
53336
53429
  const buf = Buffer.alloc(len);
53337
- import_node_fs30.default.readSync(fd, buf, 0, len, w2.lastSize);
53430
+ import_node_fs31.default.readSync(fd, buf, 0, len, w2.lastSize);
53338
53431
  w2.lastSize = size;
53339
53432
  w2.buf += buf.toString("utf8");
53340
53433
  let newlineIndex;
@@ -53357,7 +53450,7 @@ var SessionObserver = class {
53357
53450
  }
53358
53451
  }
53359
53452
  } finally {
53360
- import_node_fs30.default.closeSync(fd);
53453
+ import_node_fs31.default.closeSync(fd);
53361
53454
  }
53362
53455
  if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
53363
53456
  }
@@ -53369,7 +53462,7 @@ var SessionObserver = class {
53369
53462
  const now = Date.now();
53370
53463
  if (now - w2.lastRelocateScanMs < 1e3) return;
53371
53464
  w2.lastRelocateScanMs = now;
53372
- const projectsRoot = import_node_path32.default.join(this.home, ".claude", "projects");
53465
+ const projectsRoot = import_node_path33.default.join(this.home, ".claude", "projects");
53373
53466
  const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
53374
53467
  if (!found || found === w2.filePath) return;
53375
53468
  try {
@@ -53378,7 +53471,7 @@ var SessionObserver = class {
53378
53471
  }
53379
53472
  w2.filePath = found;
53380
53473
  try {
53381
- w2.watcher = import_node_fs30.default.watch(import_node_path32.default.dirname(found), { persistent: false }, (_event, changedName) => {
53474
+ w2.watcher = import_node_fs31.default.watch(import_node_path33.default.dirname(found), { persistent: false }, (_event, changedName) => {
53382
53475
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
53383
53476
  this.poll(w2);
53384
53477
  });
@@ -54173,8 +54266,8 @@ async function authenticate(token, deps) {
54173
54266
  }
54174
54267
 
54175
54268
  // src/legacy-cleanup.ts
54176
- var fs35 = __toESM(require("fs/promises"), 1);
54177
- var path37 = __toESM(require("path"), 1);
54269
+ var fs36 = __toESM(require("fs/promises"), 1);
54270
+ var path38 = __toESM(require("path"), 1);
54178
54271
  var LEGACY_FILES = [
54179
54272
  "personal-capability.json",
54180
54273
  "received-capabilities.json",
@@ -54183,9 +54276,9 @@ var LEGACY_FILES = [
54183
54276
  async function cleanupLegacyCapabilityFiles(dataDir, logger) {
54184
54277
  const removed = [];
54185
54278
  for (const name of LEGACY_FILES) {
54186
- const p2 = path37.join(dataDir, name);
54279
+ const p2 = path38.join(dataDir, name);
54187
54280
  try {
54188
- await fs35.unlink(p2);
54281
+ await fs36.unlink(p2);
54189
54282
  removed.push(name);
54190
54283
  logger.debug("legacy capability file removed", { file: name });
54191
54284
  } catch (err) {
@@ -54197,13 +54290,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
54197
54290
  }
54198
54291
 
54199
54292
  // src/inbox/inbox-store.ts
54200
- var fs36 = __toESM(require("fs"), 1);
54201
- var path38 = __toESM(require("path"), 1);
54293
+ var fs37 = __toESM(require("fs"), 1);
54294
+ var path39 = __toESM(require("path"), 1);
54202
54295
  var INBOX_SUBDIR = "inbox";
54203
54296
  var InboxStore = class {
54204
54297
  constructor(dataDir) {
54205
54298
  this.dataDir = dataDir;
54206
- fs36.mkdirSync(this.dirPath(), { recursive: true });
54299
+ fs37.mkdirSync(this.dirPath(), { recursive: true });
54207
54300
  }
54208
54301
  dataDir;
54209
54302
  /**
@@ -54215,7 +54308,7 @@ var InboxStore = class {
54215
54308
  const file = this.filePath(peerDeviceId);
54216
54309
  let raw;
54217
54310
  try {
54218
- raw = fs36.readFileSync(file, "utf8");
54311
+ raw = fs37.readFileSync(file, "utf8");
54219
54312
  } catch (err) {
54220
54313
  if (err?.code === "ENOENT") return [];
54221
54314
  return [];
@@ -54231,7 +54324,7 @@ var InboxStore = class {
54231
54324
  const dir = this.dirPath();
54232
54325
  let entries;
54233
54326
  try {
54234
- entries = fs36.readdirSync(dir);
54327
+ entries = fs37.readdirSync(dir);
54235
54328
  } catch (err) {
54236
54329
  if (err?.code === "ENOENT") return [];
54237
54330
  return [];
@@ -54247,9 +54340,9 @@ var InboxStore = class {
54247
54340
  if (existing.some((m2) => m2.id === message.id)) return;
54248
54341
  const file = this.filePath(message.peerDeviceId);
54249
54342
  const line = JSON.stringify(message) + "\n";
54250
- fs36.appendFileSync(file, line, { mode: 384 });
54343
+ fs37.appendFileSync(file, line, { mode: 384 });
54251
54344
  try {
54252
- fs36.chmodSync(file, 384);
54345
+ fs37.chmodSync(file, 384);
54253
54346
  } catch {
54254
54347
  }
54255
54348
  }
@@ -54279,7 +54372,7 @@ var InboxStore = class {
54279
54372
  removeByPeerDeviceId(peerDeviceId) {
54280
54373
  const file = this.filePath(peerDeviceId);
54281
54374
  try {
54282
- fs36.unlinkSync(file);
54375
+ fs37.unlinkSync(file);
54283
54376
  } catch (err) {
54284
54377
  if (err?.code === "ENOENT") return;
54285
54378
  }
@@ -54288,18 +54381,18 @@ var InboxStore = class {
54288
54381
  const file = this.filePath(peerDeviceId);
54289
54382
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
54290
54383
  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);
54384
+ fs37.writeFileSync(tmp, content, { mode: 384 });
54385
+ fs37.renameSync(tmp, file);
54293
54386
  try {
54294
- fs36.chmodSync(file, 384);
54387
+ fs37.chmodSync(file, 384);
54295
54388
  } catch {
54296
54389
  }
54297
54390
  }
54298
54391
  dirPath() {
54299
- return path38.join(this.dataDir, INBOX_SUBDIR);
54392
+ return path39.join(this.dataDir, INBOX_SUBDIR);
54300
54393
  }
54301
54394
  filePath(peerDeviceId) {
54302
- return path38.join(this.dirPath(), `${peerDeviceId}.jsonl`);
54395
+ return path39.join(this.dirPath(), `${peerDeviceId}.jsonl`);
54303
54396
  }
54304
54397
  };
54305
54398
  function parseAllLines(raw) {
@@ -54387,8 +54480,8 @@ var InboxManager = class {
54387
54480
  };
54388
54481
 
54389
54482
  // src/state/contact-store.ts
54390
- var fs37 = __toESM(require("fs"), 1);
54391
- var path39 = __toESM(require("path"), 1);
54483
+ var fs38 = __toESM(require("fs"), 1);
54484
+ var path40 = __toESM(require("path"), 1);
54392
54485
  var FILE_NAME = "contacts.json";
54393
54486
  var ContactStore = class {
54394
54487
  constructor(dataDir) {
@@ -54398,10 +54491,10 @@ var ContactStore = class {
54398
54491
  contacts = /* @__PURE__ */ new Map();
54399
54492
  load() {
54400
54493
  this.contacts.clear();
54401
- const file = path39.join(this.dataDir, FILE_NAME);
54494
+ const file = path40.join(this.dataDir, FILE_NAME);
54402
54495
  let raw;
54403
54496
  try {
54404
- raw = fs37.readFileSync(file, "utf8");
54497
+ raw = fs38.readFileSync(file, "utf8");
54405
54498
  } catch (err) {
54406
54499
  if (err?.code !== "ENOENT") this.renameBak(file);
54407
54500
  return;
@@ -54470,20 +54563,20 @@ var ContactStore = class {
54470
54563
  return true;
54471
54564
  }
54472
54565
  flush() {
54473
- const file = path39.join(this.dataDir, FILE_NAME);
54566
+ const file = path40.join(this.dataDir, FILE_NAME);
54474
54567
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
54475
54568
  const content = JSON.stringify(
54476
54569
  { contacts: Array.from(this.contacts.values()) },
54477
54570
  null,
54478
54571
  2
54479
54572
  );
54480
- fs37.mkdirSync(this.dataDir, { recursive: true });
54481
- fs37.writeFileSync(tmp, content, { mode: 384 });
54482
- fs37.renameSync(tmp, file);
54573
+ fs38.mkdirSync(this.dataDir, { recursive: true });
54574
+ fs38.writeFileSync(tmp, content, { mode: 384 });
54575
+ fs38.renameSync(tmp, file);
54483
54576
  }
54484
54577
  renameBak(file) {
54485
54578
  try {
54486
- fs37.renameSync(file, `${file}.bak`);
54579
+ fs38.renameSync(file, `${file}.bak`);
54487
54580
  } catch {
54488
54581
  }
54489
54582
  }
@@ -54591,61 +54684,61 @@ async function connectRemote(args) {
54591
54684
  }
54592
54685
 
54593
54686
  // src/migrations/2026-05-20-flatten-sessions.ts
54594
- var fs38 = __toESM(require("fs"), 1);
54595
- var path40 = __toESM(require("path"), 1);
54687
+ var fs39 = __toESM(require("fs"), 1);
54688
+ var path41 = __toESM(require("path"), 1);
54596
54689
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
54597
54690
  function migrateFlattenSessions(opts) {
54598
54691
  const dataDir = opts.dataDir;
54599
54692
  const now = opts.now ?? Date.now;
54600
- const sessionsDir = path40.join(dataDir, "sessions");
54601
- const flagPath = path40.join(sessionsDir, MIGRATION_FLAG_NAME);
54693
+ const sessionsDir = path41.join(dataDir, "sessions");
54694
+ const flagPath = path41.join(sessionsDir, MIGRATION_FLAG_NAME);
54602
54695
  if (existsSync3(flagPath)) {
54603
54696
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
54604
54697
  }
54605
54698
  let movedBare = 0;
54606
54699
  let movedVmOwner = 0;
54607
54700
  let archivedListener = 0;
54608
- const defaultDir = path40.join(sessionsDir, "default");
54701
+ const defaultDir = path41.join(sessionsDir, "default");
54609
54702
  if (existsSync3(defaultDir)) {
54610
54703
  for (const entry of readdirSafe(defaultDir)) {
54611
54704
  if (!entry.endsWith(".json")) continue;
54612
- const src = path40.join(defaultDir, entry);
54613
- const dst = path40.join(sessionsDir, entry);
54614
- fs38.renameSync(src, dst);
54705
+ const src = path41.join(defaultDir, entry);
54706
+ const dst = path41.join(sessionsDir, entry);
54707
+ fs39.renameSync(src, dst);
54615
54708
  movedBare += 1;
54616
54709
  }
54617
54710
  rmdirIfEmpty(defaultDir);
54618
54711
  }
54619
54712
  for (const pid of readdirSafe(sessionsDir)) {
54620
- const personaDir = path40.join(sessionsDir, pid);
54713
+ const personaDir = path41.join(sessionsDir, pid);
54621
54714
  if (!isDir(personaDir)) continue;
54622
54715
  if (pid === "default") continue;
54623
- const ownerSrc = path40.join(personaDir, "owner");
54716
+ const ownerSrc = path41.join(personaDir, "owner");
54624
54717
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
54625
- const ownerDst = path40.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
54626
- fs38.mkdirSync(ownerDst, { recursive: true });
54718
+ const ownerDst = path41.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
54719
+ fs39.mkdirSync(ownerDst, { recursive: true });
54627
54720
  for (const file of readdirSafe(ownerSrc)) {
54628
54721
  if (!file.endsWith(".json")) continue;
54629
- fs38.renameSync(path40.join(ownerSrc, file), path40.join(ownerDst, file));
54722
+ fs39.renameSync(path41.join(ownerSrc, file), path41.join(ownerDst, file));
54630
54723
  movedVmOwner += 1;
54631
54724
  }
54632
54725
  rmdirIfEmpty(ownerSrc);
54633
54726
  }
54634
- const listenerSrc = path40.join(personaDir, "listener");
54727
+ const listenerSrc = path41.join(personaDir, "listener");
54635
54728
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
54636
- const archiveDst = path40.join(dataDir, ".legacy", `listener-${pid}`);
54637
- fs38.mkdirSync(archiveDst, { recursive: true });
54729
+ const archiveDst = path41.join(dataDir, ".legacy", `listener-${pid}`);
54730
+ fs39.mkdirSync(archiveDst, { recursive: true });
54638
54731
  for (const file of readdirSafe(listenerSrc)) {
54639
54732
  if (!file.endsWith(".json")) continue;
54640
- fs38.renameSync(path40.join(listenerSrc, file), path40.join(archiveDst, file));
54733
+ fs39.renameSync(path41.join(listenerSrc, file), path41.join(archiveDst, file));
54641
54734
  archivedListener += 1;
54642
54735
  }
54643
54736
  rmdirIfEmpty(listenerSrc);
54644
54737
  }
54645
54738
  rmdirIfEmpty(personaDir);
54646
54739
  }
54647
- fs38.mkdirSync(sessionsDir, { recursive: true });
54648
- fs38.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
54740
+ fs39.mkdirSync(sessionsDir, { recursive: true });
54741
+ fs39.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
54649
54742
  return {
54650
54743
  skipped: false,
54651
54744
  flagWritten: true,
@@ -54656,7 +54749,7 @@ function migrateFlattenSessions(opts) {
54656
54749
  }
54657
54750
  function existsSync3(p2) {
54658
54751
  try {
54659
- fs38.statSync(p2);
54752
+ fs39.statSync(p2);
54660
54753
  return true;
54661
54754
  } catch {
54662
54755
  return false;
@@ -54664,31 +54757,31 @@ function existsSync3(p2) {
54664
54757
  }
54665
54758
  function isDir(p2) {
54666
54759
  try {
54667
- return fs38.statSync(p2).isDirectory();
54760
+ return fs39.statSync(p2).isDirectory();
54668
54761
  } catch {
54669
54762
  return false;
54670
54763
  }
54671
54764
  }
54672
54765
  function readdirSafe(p2) {
54673
54766
  try {
54674
- return fs38.readdirSync(p2);
54767
+ return fs39.readdirSync(p2);
54675
54768
  } catch {
54676
54769
  return [];
54677
54770
  }
54678
54771
  }
54679
54772
  function rmdirIfEmpty(p2) {
54680
54773
  try {
54681
- fs38.rmdirSync(p2);
54774
+ fs39.rmdirSync(p2);
54682
54775
  } catch {
54683
54776
  }
54684
54777
  }
54685
54778
 
54686
54779
  // src/transport/http-router.ts
54687
- var import_node_fs32 = __toESM(require("fs"), 1);
54688
- var import_node_path36 = __toESM(require("path"), 1);
54780
+ var import_node_fs33 = __toESM(require("fs"), 1);
54781
+ var import_node_path37 = __toESM(require("path"), 1);
54689
54782
 
54690
54783
  // src/attachment/mime.ts
54691
- var import_node_path33 = __toESM(require("path"), 1);
54784
+ var import_node_path34 = __toESM(require("path"), 1);
54692
54785
  var TEXT_PLAIN = "text/plain; charset=utf-8";
54693
54786
  var EXT_TO_NATIVE_MIME = {
54694
54787
  // 图片
@@ -54795,7 +54888,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
54795
54888
  ".mk"
54796
54889
  ]);
54797
54890
  function lookupMime(filePathOrName) {
54798
- const ext = import_node_path33.default.extname(filePathOrName).toLowerCase();
54891
+ const ext = import_node_path34.default.extname(filePathOrName).toLowerCase();
54799
54892
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
54800
54893
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
54801
54894
  return "application/octet-stream";
@@ -54865,8 +54958,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
54865
54958
  }
54866
54959
 
54867
54960
  // src/attachment/upload.ts
54868
- var import_node_fs31 = __toESM(require("fs"), 1);
54869
- var import_node_path34 = __toESM(require("path"), 1);
54961
+ var import_node_fs32 = __toESM(require("fs"), 1);
54962
+ var import_node_path35 = __toESM(require("path"), 1);
54870
54963
  var import_node_crypto8 = __toESM(require("crypto"), 1);
54871
54964
  var import_promises3 = require("stream/promises");
54872
54965
  var UploadError = class extends Error {
@@ -54878,22 +54971,22 @@ var UploadError = class extends Error {
54878
54971
  code;
54879
54972
  };
54880
54973
  function assertValidFileName(fileName) {
54881
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path34.default.basename(fileName)) {
54974
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path35.default.basename(fileName)) {
54882
54975
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
54883
54976
  }
54884
54977
  }
54885
54978
  var HASH_PREFIX_LEN = 16;
54886
54979
  async function writeUploadedAttachment(args) {
54887
54980
  assertValidFileName(args.fileName);
54888
- const attachmentsRoot = import_node_path34.default.join(args.baseDir, ".attachments");
54981
+ const attachmentsRoot = import_node_path35.default.join(args.baseDir, ".attachments");
54889
54982
  try {
54890
- import_node_fs31.default.mkdirSync(attachmentsRoot, { recursive: true });
54983
+ import_node_fs32.default.mkdirSync(attachmentsRoot, { recursive: true });
54891
54984
  } catch (err) {
54892
54985
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
54893
54986
  }
54894
54987
  const hasher = import_node_crypto8.default.createHash("sha256");
54895
54988
  let actualSize = 0;
54896
- const tmpPath = import_node_path34.default.join(
54989
+ const tmpPath = import_node_path35.default.join(
54897
54990
  attachmentsRoot,
54898
54991
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto8.default.randomBytes(4).toString("hex")}`
54899
54992
  );
@@ -54908,18 +55001,18 @@ async function writeUploadedAttachment(args) {
54908
55001
  yield buf;
54909
55002
  }
54910
55003
  },
54911
- import_node_fs31.default.createWriteStream(tmpPath, { mode: 384 })
55004
+ import_node_fs32.default.createWriteStream(tmpPath, { mode: 384 })
54912
55005
  );
54913
55006
  } catch (err) {
54914
55007
  try {
54915
- import_node_fs31.default.unlinkSync(tmpPath);
55008
+ import_node_fs32.default.unlinkSync(tmpPath);
54916
55009
  } catch {
54917
55010
  }
54918
55011
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
54919
55012
  }
54920
55013
  if (actualSize !== args.contentLength) {
54921
55014
  try {
54922
- import_node_fs31.default.unlinkSync(tmpPath);
55015
+ import_node_fs32.default.unlinkSync(tmpPath);
54923
55016
  } catch {
54924
55017
  }
54925
55018
  throw new UploadError(
@@ -54928,34 +55021,34 @@ async function writeUploadedAttachment(args) {
54928
55021
  );
54929
55022
  }
54930
55023
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
54931
- const hashDir = import_node_path34.default.join(attachmentsRoot, attachmentId);
55024
+ const hashDir = import_node_path35.default.join(attachmentsRoot, attachmentId);
54932
55025
  let finalFileName;
54933
55026
  let hashDirExists = false;
54934
55027
  try {
54935
- hashDirExists = import_node_fs31.default.statSync(hashDir).isDirectory();
55028
+ hashDirExists = import_node_fs32.default.statSync(hashDir).isDirectory();
54936
55029
  } catch {
54937
55030
  }
54938
55031
  if (hashDirExists) {
54939
- const existing = import_node_fs31.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
55032
+ const existing = import_node_fs32.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
54940
55033
  finalFileName = existing[0] ?? args.fileName;
54941
55034
  try {
54942
- import_node_fs31.default.unlinkSync(tmpPath);
55035
+ import_node_fs32.default.unlinkSync(tmpPath);
54943
55036
  } catch {
54944
55037
  }
54945
55038
  } else {
54946
55039
  try {
54947
- import_node_fs31.default.mkdirSync(hashDir, { recursive: true });
55040
+ import_node_fs32.default.mkdirSync(hashDir, { recursive: true });
54948
55041
  finalFileName = args.fileName;
54949
- import_node_fs31.default.renameSync(tmpPath, import_node_path34.default.join(hashDir, finalFileName));
55042
+ import_node_fs32.default.renameSync(tmpPath, import_node_path35.default.join(hashDir, finalFileName));
54950
55043
  } catch (err) {
54951
55044
  try {
54952
- import_node_fs31.default.unlinkSync(tmpPath);
55045
+ import_node_fs32.default.unlinkSync(tmpPath);
54953
55046
  } catch {
54954
55047
  }
54955
55048
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
54956
55049
  }
54957
55050
  }
54958
- const absPath = import_node_path34.default.join(hashDir, finalFileName);
55051
+ const absPath = import_node_path35.default.join(hashDir, finalFileName);
54959
55052
  const relPath = absPath;
54960
55053
  args.groupFileStore.upsert(args.scope, args.sessionId, {
54961
55054
  relPath: absPath,
@@ -54970,7 +55063,7 @@ async function writeUploadedAttachment(args) {
54970
55063
 
54971
55064
  // src/extension/import.ts
54972
55065
  var import_promises4 = __toESM(require("fs/promises"), 1);
54973
- var import_node_path35 = __toESM(require("path"), 1);
55066
+ var import_node_path36 = __toESM(require("path"), 1);
54974
55067
  var import_node_os12 = __toESM(require("os"), 1);
54975
55068
  var import_jszip = __toESM(require_lib3(), 1);
54976
55069
  var ImportError = class extends Error {
@@ -54988,7 +55081,7 @@ async function importZip(buf, root) {
54988
55081
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
54989
55082
  }
54990
55083
  for (const name of Object.keys(zip.files)) {
54991
- if (name.includes("..") || name.startsWith("/") || import_node_path35.default.isAbsolute(name)) {
55084
+ if (name.includes("..") || name.startsWith("/") || import_node_path36.default.isAbsolute(name)) {
54992
55085
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
54993
55086
  }
54994
55087
  }
@@ -55021,7 +55114,7 @@ async function importZip(buf, root) {
55021
55114
  );
55022
55115
  }
55023
55116
  }
55024
- const destDir = import_node_path35.default.join(root, manifest.id);
55117
+ const destDir = import_node_path36.default.join(root, manifest.id);
55025
55118
  let destExists = false;
55026
55119
  try {
55027
55120
  await import_promises4.default.access(destDir);
@@ -55031,15 +55124,15 @@ async function importZip(buf, root) {
55031
55124
  if (destExists) {
55032
55125
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
55033
55126
  }
55034
- const stage = await import_promises4.default.mkdtemp(import_node_path35.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
55127
+ const stage = await import_promises4.default.mkdtemp(import_node_path36.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
55035
55128
  try {
55036
55129
  for (const [name, entry] of Object.entries(zip.files)) {
55037
- const dest = import_node_path35.default.join(stage, name);
55130
+ const dest = import_node_path36.default.join(stage, name);
55038
55131
  if (entry.dir) {
55039
55132
  await import_promises4.default.mkdir(dest, { recursive: true });
55040
55133
  continue;
55041
55134
  }
55042
- await import_promises4.default.mkdir(import_node_path35.default.dirname(dest), { recursive: true });
55135
+ await import_promises4.default.mkdir(import_node_path36.default.dirname(dest), { recursive: true });
55043
55136
  const content = await entry.async("nodebuffer");
55044
55137
  await import_promises4.default.writeFile(dest, content);
55045
55138
  }
@@ -55069,7 +55162,7 @@ var SHARE_UI_ASSET_MIME = {
55069
55162
  ".wasm": "application/wasm"
55070
55163
  };
55071
55164
  function shareUiAssetMime(filePath) {
55072
- const ext = import_node_path36.default.extname(filePath).toLowerCase();
55165
+ const ext = import_node_path37.default.extname(filePath).toLowerCase();
55073
55166
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
55074
55167
  }
55075
55168
  var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
@@ -55168,7 +55261,7 @@ function isValidUploadFileName(fileName) {
55168
55261
  if (fileName === "." || fileName === "..") return false;
55169
55262
  if (fileName.startsWith(".")) return false;
55170
55263
  if (fileName.includes("/") || fileName.includes("\\")) return false;
55171
- return fileName === import_node_path36.default.basename(fileName);
55264
+ return fileName === import_node_path37.default.basename(fileName);
55172
55265
  }
55173
55266
  function createHttpRouter(deps) {
55174
55267
  return async (req, res) => {
@@ -55256,7 +55349,7 @@ function createHttpRouter(deps) {
55256
55349
  }
55257
55350
  let buf;
55258
55351
  try {
55259
- buf = await import_node_fs32.default.promises.readFile(abs);
55352
+ buf = await import_node_fs33.default.promises.readFile(abs);
55260
55353
  } catch {
55261
55354
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
55262
55355
  return true;
@@ -55404,7 +55497,7 @@ function createHttpRouter(deps) {
55404
55497
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
55405
55498
  return true;
55406
55499
  }
55407
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path36.default.basename(r.absPath)));
55500
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path37.default.basename(r.absPath)));
55408
55501
  return true;
55409
55502
  }
55410
55503
  const ctx = deps.authResolver.resolveFromHeader(
@@ -55525,7 +55618,7 @@ function createHttpRouter(deps) {
55525
55618
  return true;
55526
55619
  }
55527
55620
  let absPath;
55528
- if (import_node_path36.default.isAbsolute(pathParam)) {
55621
+ if (import_node_path37.default.isAbsolute(pathParam)) {
55529
55622
  absPath = pathParam;
55530
55623
  } else if (deps.sessionStore) {
55531
55624
  const file = deps.sessionStore.read(sid);
@@ -55533,7 +55626,7 @@ function createHttpRouter(deps) {
55533
55626
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
55534
55627
  return true;
55535
55628
  }
55536
- absPath = import_node_path36.default.join(file.cwd, pathParam);
55629
+ absPath = import_node_path37.default.join(file.cwd, pathParam);
55537
55630
  } else {
55538
55631
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
55539
55632
  return true;
@@ -55620,7 +55713,7 @@ function withCtx(ctx, body) {
55620
55713
  function streamFile(res, absPath, logger) {
55621
55714
  let stat;
55622
55715
  try {
55623
- stat = import_node_fs32.default.statSync(absPath);
55716
+ stat = import_node_fs33.default.statSync(absPath);
55624
55717
  } catch (err) {
55625
55718
  const code = err?.code;
55626
55719
  if (code === "ENOENT") {
@@ -55635,7 +55728,7 @@ function streamFile(res, absPath, logger) {
55635
55728
  return;
55636
55729
  }
55637
55730
  const mime = lookupMime(absPath);
55638
- const basename = import_node_path36.default.basename(absPath);
55731
+ const basename = import_node_path37.default.basename(absPath);
55639
55732
  res.writeHead(200, {
55640
55733
  "Content-Type": mime,
55641
55734
  "Content-Length": String(stat.size),
@@ -55643,7 +55736,7 @@ function streamFile(res, absPath, logger) {
55643
55736
  // 防止浏览器把任意 mime 当 html 渲染
55644
55737
  "X-Content-Type-Options": "nosniff"
55645
55738
  });
55646
- const stream = import_node_fs32.default.createReadStream(absPath);
55739
+ const stream = import_node_fs33.default.createReadStream(absPath);
55647
55740
  stream.on("error", (err) => {
55648
55741
  logger?.warn("streamFile read error", { absPath, err: err.message });
55649
55742
  res.destroy();
@@ -55652,8 +55745,8 @@ function streamFile(res, absPath, logger) {
55652
55745
  }
55653
55746
 
55654
55747
  // src/attachment/gc.ts
55655
- var import_node_fs33 = __toESM(require("fs"), 1);
55656
- var import_node_path37 = __toESM(require("path"), 1);
55748
+ var import_node_fs34 = __toESM(require("fs"), 1);
55749
+ var import_node_path38 = __toESM(require("path"), 1);
55657
55750
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
55658
55751
  function runAttachmentGc(args) {
55659
55752
  const now = (args.now ?? Date.now)();
@@ -55662,12 +55755,12 @@ function runAttachmentGc(args) {
55662
55755
  for (const { scope, sessionId } of args.sessionScopes) {
55663
55756
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
55664
55757
  if (entry.stale) continue;
55665
- if (import_node_path37.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
55758
+ if (import_node_path38.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
55666
55759
  }
55667
55760
  }
55668
55761
  const visited = /* @__PURE__ */ new Set();
55669
55762
  for (const { scope, sessionId } of args.sessionScopes) {
55670
- const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path37.default.join(
55763
+ const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path38.default.join(
55671
55764
  args.dataDir,
55672
55765
  "sessions",
55673
55766
  ...scopeSubPath(scope).map(safeFileName),
@@ -55680,28 +55773,28 @@ function runAttachmentGc(args) {
55680
55773
  return true;
55681
55774
  });
55682
55775
  for (const rootDir of roots) {
55683
- const attRoot = import_node_path37.default.join(rootDir, ".attachments");
55776
+ const attRoot = import_node_path38.default.join(rootDir, ".attachments");
55684
55777
  let hashDirs;
55685
55778
  try {
55686
- hashDirs = import_node_fs33.default.readdirSync(attRoot);
55779
+ hashDirs = import_node_fs34.default.readdirSync(attRoot);
55687
55780
  } catch (err) {
55688
55781
  if (err.code === "ENOENT") continue;
55689
55782
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
55690
55783
  continue;
55691
55784
  }
55692
55785
  for (const hashDir of hashDirs) {
55693
- const hashDirAbs = import_node_path37.default.join(attRoot, hashDir);
55786
+ const hashDirAbs = import_node_path38.default.join(attRoot, hashDir);
55694
55787
  let files;
55695
55788
  try {
55696
- files = import_node_fs33.default.readdirSync(hashDirAbs);
55789
+ files = import_node_fs34.default.readdirSync(hashDirAbs);
55697
55790
  } catch {
55698
55791
  continue;
55699
55792
  }
55700
55793
  for (const name of files) {
55701
- const file = import_node_path37.default.join(hashDirAbs, name);
55794
+ const file = import_node_path38.default.join(hashDirAbs, name);
55702
55795
  let stat;
55703
55796
  try {
55704
- stat = import_node_fs33.default.statSync(file);
55797
+ stat = import_node_fs34.default.statSync(file);
55705
55798
  } catch {
55706
55799
  continue;
55707
55800
  }
@@ -55710,18 +55803,18 @@ function runAttachmentGc(args) {
55710
55803
  if (age < ttlMs) continue;
55711
55804
  if (liveAbs.has(file)) continue;
55712
55805
  try {
55713
- import_node_fs33.default.unlinkSync(file);
55806
+ import_node_fs34.default.unlinkSync(file);
55714
55807
  } catch (err) {
55715
55808
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
55716
55809
  }
55717
55810
  }
55718
55811
  try {
55719
- if (import_node_fs33.default.readdirSync(hashDirAbs).length === 0) import_node_fs33.default.rmdirSync(hashDirAbs);
55812
+ if (import_node_fs34.default.readdirSync(hashDirAbs).length === 0) import_node_fs34.default.rmdirSync(hashDirAbs);
55720
55813
  } catch {
55721
55814
  }
55722
55815
  }
55723
55816
  try {
55724
- if (import_node_fs33.default.readdirSync(attRoot).length === 0) import_node_fs33.default.rmdirSync(attRoot);
55817
+ if (import_node_fs34.default.readdirSync(attRoot).length === 0) import_node_fs34.default.rmdirSync(attRoot);
55725
55818
  } catch {
55726
55819
  }
55727
55820
  }
@@ -55729,8 +55822,8 @@ function runAttachmentGc(args) {
55729
55822
  }
55730
55823
 
55731
55824
  // src/attachment/group.ts
55732
- var import_node_fs34 = __toESM(require("fs"), 1);
55733
- var import_node_path38 = __toESM(require("path"), 1);
55825
+ var import_node_fs35 = __toESM(require("fs"), 1);
55826
+ var import_node_path39 = __toESM(require("path"), 1);
55734
55827
  var import_node_crypto9 = __toESM(require("crypto"), 1);
55735
55828
  init_protocol();
55736
55829
  var GroupFileStore = class {
@@ -55742,11 +55835,11 @@ var GroupFileStore = class {
55742
55835
  this.logger = opts.logger;
55743
55836
  }
55744
55837
  rootForScope(scope) {
55745
- return import_node_path38.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
55838
+ return import_node_path39.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
55746
55839
  }
55747
55840
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
55748
55841
  filePath(scope, sessionId) {
55749
- return import_node_path38.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
55842
+ return import_node_path39.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
55750
55843
  }
55751
55844
  cacheKey(scope, sessionId) {
55752
55845
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -55755,7 +55848,7 @@ var GroupFileStore = class {
55755
55848
  readFile(scope, sessionId) {
55756
55849
  const file = this.filePath(scope, sessionId);
55757
55850
  try {
55758
- const raw = import_node_fs34.default.readFileSync(file, "utf8");
55851
+ const raw = import_node_fs35.default.readFileSync(file, "utf8");
55759
55852
  const parsed = JSON.parse(raw);
55760
55853
  if (!Array.isArray(parsed)) {
55761
55854
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -55781,10 +55874,10 @@ var GroupFileStore = class {
55781
55874
  }
55782
55875
  writeFile(scope, sessionId, entries) {
55783
55876
  const file = this.filePath(scope, sessionId);
55784
- import_node_fs34.default.mkdirSync(import_node_path38.default.dirname(file), { recursive: true });
55877
+ import_node_fs35.default.mkdirSync(import_node_path39.default.dirname(file), { recursive: true });
55785
55878
  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);
55879
+ import_node_fs35.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
55880
+ import_node_fs35.default.renameSync(tmp, file);
55788
55881
  }
55789
55882
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
55790
55883
  list(scope, sessionId) {
@@ -55870,10 +55963,10 @@ var GroupFileStore = class {
55870
55963
  };
55871
55964
 
55872
55965
  // src/discovery/state-file.ts
55873
- var import_node_fs35 = __toESM(require("fs"), 1);
55874
- var import_node_path39 = __toESM(require("path"), 1);
55966
+ var import_node_fs36 = __toESM(require("fs"), 1);
55967
+ var import_node_path40 = __toESM(require("path"), 1);
55875
55968
  function defaultStateFilePath(dataDir) {
55876
- return import_node_path39.default.join(dataDir, "state.json");
55969
+ return import_node_path40.default.join(dataDir, "state.json");
55877
55970
  }
55878
55971
  function isPidAlive(pid) {
55879
55972
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -55895,7 +55988,7 @@ var StateFileManager = class {
55895
55988
  }
55896
55989
  read() {
55897
55990
  try {
55898
- const raw = import_node_fs35.default.readFileSync(this.file, "utf8");
55991
+ const raw = import_node_fs36.default.readFileSync(this.file, "utf8");
55899
55992
  const parsed = JSON.parse(raw);
55900
55993
  return parsed;
55901
55994
  } catch {
@@ -55909,20 +56002,20 @@ var StateFileManager = class {
55909
56002
  return { status: "stale", existing };
55910
56003
  }
55911
56004
  write(state) {
55912
- import_node_fs35.default.mkdirSync(import_node_path39.default.dirname(this.file), { recursive: true });
56005
+ import_node_fs36.default.mkdirSync(import_node_path40.default.dirname(this.file), { recursive: true });
55913
56006
  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);
56007
+ import_node_fs36.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
56008
+ import_node_fs36.default.renameSync(tmp, this.file);
55916
56009
  if (process.platform !== "win32") {
55917
56010
  try {
55918
- import_node_fs35.default.chmodSync(this.file, 384);
56011
+ import_node_fs36.default.chmodSync(this.file, 384);
55919
56012
  } catch {
55920
56013
  }
55921
56014
  }
55922
56015
  }
55923
56016
  delete() {
55924
56017
  try {
55925
- import_node_fs35.default.unlinkSync(this.file);
56018
+ import_node_fs36.default.unlinkSync(this.file);
55926
56019
  } catch {
55927
56020
  }
55928
56021
  }
@@ -55936,14 +56029,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
55936
56029
  }
55937
56030
 
55938
56031
  // src/tunnel/tunnel-manager.ts
55939
- var import_node_fs39 = __toESM(require("fs"), 1);
55940
- var import_node_path43 = __toESM(require("path"), 1);
56032
+ var import_node_fs40 = __toESM(require("fs"), 1);
56033
+ var import_node_path44 = __toESM(require("path"), 1);
55941
56034
  var import_node_crypto10 = __toESM(require("crypto"), 1);
55942
56035
  var import_node_child_process9 = require("child_process");
55943
56036
 
55944
56037
  // src/tunnel/tunnel-store.ts
55945
- var import_node_fs36 = __toESM(require("fs"), 1);
55946
- var import_node_path40 = __toESM(require("path"), 1);
56038
+ var import_node_fs37 = __toESM(require("fs"), 1);
56039
+ var import_node_path41 = __toESM(require("path"), 1);
55947
56040
  var TunnelStore = class {
55948
56041
  constructor(filePath) {
55949
56042
  this.filePath = filePath;
@@ -55951,7 +56044,7 @@ var TunnelStore = class {
55951
56044
  filePath;
55952
56045
  async get() {
55953
56046
  try {
55954
- const raw = await import_node_fs36.default.promises.readFile(this.filePath, "utf8");
56047
+ const raw = await import_node_fs37.default.promises.readFile(this.filePath, "utf8");
55955
56048
  const obj = JSON.parse(raw);
55956
56049
  if (!isPersistedTunnel(obj)) return null;
55957
56050
  return obj;
@@ -55962,22 +56055,22 @@ var TunnelStore = class {
55962
56055
  }
55963
56056
  }
55964
56057
  async set(v2) {
55965
- const dir = import_node_path40.default.dirname(this.filePath);
55966
- await import_node_fs36.default.promises.mkdir(dir, { recursive: true });
56058
+ const dir = import_node_path41.default.dirname(this.filePath);
56059
+ await import_node_fs37.default.promises.mkdir(dir, { recursive: true });
55967
56060
  const data = JSON.stringify(v2, null, 2);
55968
56061
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
55969
- await import_node_fs36.default.promises.writeFile(tmp, data, { mode: 384 });
56062
+ await import_node_fs37.default.promises.writeFile(tmp, data, { mode: 384 });
55970
56063
  if (process.platform !== "win32") {
55971
56064
  try {
55972
- await import_node_fs36.default.promises.chmod(tmp, 384);
56065
+ await import_node_fs37.default.promises.chmod(tmp, 384);
55973
56066
  } catch {
55974
56067
  }
55975
56068
  }
55976
- await import_node_fs36.default.promises.rename(tmp, this.filePath);
56069
+ await import_node_fs37.default.promises.rename(tmp, this.filePath);
55977
56070
  }
55978
56071
  async clear() {
55979
56072
  try {
55980
- await import_node_fs36.default.promises.unlink(this.filePath);
56073
+ await import_node_fs37.default.promises.unlink(this.filePath);
55981
56074
  } catch (err) {
55982
56075
  const code = err?.code;
55983
56076
  if (code !== "ENOENT") throw err;
@@ -56072,9 +56165,9 @@ function escape(v2) {
56072
56165
  }
56073
56166
 
56074
56167
  // src/tunnel/frpc-binary.ts
56075
- var import_node_fs37 = __toESM(require("fs"), 1);
56168
+ var import_node_fs38 = __toESM(require("fs"), 1);
56076
56169
  var import_node_os13 = __toESM(require("os"), 1);
56077
- var import_node_path41 = __toESM(require("path"), 1);
56170
+ var import_node_path42 = __toESM(require("path"), 1);
56078
56171
  var import_node_child_process7 = require("child_process");
56079
56172
  var import_node_stream3 = require("stream");
56080
56173
  var import_promises5 = require("stream/promises");
@@ -56106,20 +56199,20 @@ function frpcDownloadUrl(version2, p2) {
56106
56199
  }
56107
56200
  async function ensureFrpcBinary(opts) {
56108
56201
  if (opts.override) {
56109
- if (!import_node_fs37.default.existsSync(opts.override)) {
56202
+ if (!import_node_fs38.default.existsSync(opts.override)) {
56110
56203
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
56111
56204
  }
56112
56205
  return opts.override;
56113
56206
  }
56114
56207
  const version2 = opts.version ?? FRPC_VERSION;
56115
56208
  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 });
56209
+ const binDir = import_node_path42.default.join(opts.dataDir, "bin");
56210
+ import_node_fs38.default.mkdirSync(binDir, { recursive: true });
56118
56211
  cleanupStaleArtifacts(binDir);
56119
- const stableBin = import_node_path41.default.join(binDir, "frpc");
56120
- if (import_node_fs37.default.existsSync(stableBin)) return stableBin;
56212
+ const stableBin = import_node_path42.default.join(binDir, "frpc");
56213
+ if (import_node_fs38.default.existsSync(stableBin)) return stableBin;
56121
56214
  const partialBin = `${stableBin}.partial`;
56122
- const tarballPath = import_node_path41.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
56215
+ const tarballPath = import_node_path42.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
56123
56216
  try {
56124
56217
  const url = frpcDownloadUrl(version2, platform);
56125
56218
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -56128,8 +56221,8 @@ async function ensureFrpcBinary(opts) {
56128
56221
  } else {
56129
56222
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
56130
56223
  }
56131
- import_node_fs37.default.chmodSync(partialBin, 493);
56132
- import_node_fs37.default.renameSync(partialBin, stableBin);
56224
+ import_node_fs38.default.chmodSync(partialBin, 493);
56225
+ import_node_fs38.default.renameSync(partialBin, stableBin);
56133
56226
  } finally {
56134
56227
  safeUnlink(tarballPath);
56135
56228
  safeUnlink(partialBin);
@@ -56139,15 +56232,15 @@ async function ensureFrpcBinary(opts) {
56139
56232
  function cleanupStaleArtifacts(binDir) {
56140
56233
  let entries;
56141
56234
  try {
56142
- entries = import_node_fs37.default.readdirSync(binDir);
56235
+ entries = import_node_fs38.default.readdirSync(binDir);
56143
56236
  } catch {
56144
56237
  return;
56145
56238
  }
56146
56239
  for (const name of entries) {
56147
56240
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
56148
- const full = import_node_path41.default.join(binDir, name);
56241
+ const full = import_node_path42.default.join(binDir, name);
56149
56242
  try {
56150
- import_node_fs37.default.rmSync(full, { recursive: true, force: true });
56243
+ import_node_fs38.default.rmSync(full, { recursive: true, force: true });
56151
56244
  } catch {
56152
56245
  }
56153
56246
  }
@@ -56155,7 +56248,7 @@ function cleanupStaleArtifacts(binDir) {
56155
56248
  }
56156
56249
  function safeUnlink(p2) {
56157
56250
  try {
56158
- import_node_fs37.default.unlinkSync(p2);
56251
+ import_node_fs38.default.unlinkSync(p2);
56159
56252
  } catch {
56160
56253
  }
56161
56254
  }
@@ -56166,13 +56259,13 @@ async function downloadToFile(url, dest, fetchImpl) {
56166
56259
  if (!res.ok || !res.body) {
56167
56260
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
56168
56261
  }
56169
- const out = import_node_fs37.default.createWriteStream(dest);
56262
+ const out = import_node_fs38.default.createWriteStream(dest);
56170
56263
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
56171
56264
  await (0, import_promises5.pipeline)(nodeStream, out);
56172
56265
  }
56173
56266
  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 });
56267
+ const work = import_node_path42.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
56268
+ import_node_fs38.default.mkdirSync(work, { recursive: true });
56176
56269
  try {
56177
56270
  await new Promise((resolve6, reject) => {
56178
56271
  const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -56180,32 +56273,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
56180
56273
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
56181
56274
  });
56182
56275
  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)) {
56276
+ const src = import_node_path42.default.join(work, dirName, "frpc");
56277
+ if (!import_node_fs38.default.existsSync(src)) {
56185
56278
  throw new Error(`frpc not found inside tarball at ${src}`);
56186
56279
  }
56187
- import_node_fs37.default.copyFileSync(src, destBin);
56280
+ import_node_fs38.default.copyFileSync(src, destBin);
56188
56281
  } finally {
56189
- import_node_fs37.default.rmSync(work, { recursive: true, force: true });
56282
+ import_node_fs38.default.rmSync(work, { recursive: true, force: true });
56190
56283
  }
56191
56284
  }
56192
56285
 
56193
56286
  // src/tunnel/frpc-process.ts
56194
- var import_node_fs38 = __toESM(require("fs"), 1);
56195
- var import_node_path42 = __toESM(require("path"), 1);
56287
+ var import_node_fs39 = __toESM(require("fs"), 1);
56288
+ var import_node_path43 = __toESM(require("path"), 1);
56196
56289
  var import_node_child_process8 = require("child_process");
56197
56290
  function frpcPidFilePath(dataDir) {
56198
- return import_node_path42.default.join(dataDir, "frpc.pid");
56291
+ return import_node_path43.default.join(dataDir, "frpc.pid");
56199
56292
  }
56200
56293
  function writeFrpcPid(dataDir, pid) {
56201
56294
  try {
56202
- import_node_fs38.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
56295
+ import_node_fs39.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
56203
56296
  } catch {
56204
56297
  }
56205
56298
  }
56206
56299
  function clearFrpcPid(dataDir) {
56207
56300
  try {
56208
- import_node_fs38.default.unlinkSync(frpcPidFilePath(dataDir));
56301
+ import_node_fs39.default.unlinkSync(frpcPidFilePath(dataDir));
56209
56302
  } catch {
56210
56303
  }
56211
56304
  }
@@ -56221,7 +56314,7 @@ function defaultIsPidAlive(pid) {
56221
56314
  }
56222
56315
  function defaultReadPidFile(file) {
56223
56316
  try {
56224
- return import_node_fs38.default.readFileSync(file, "utf8");
56317
+ return import_node_fs39.default.readFileSync(file, "utf8");
56225
56318
  } catch {
56226
56319
  return null;
56227
56320
  }
@@ -56237,7 +56330,7 @@ function defaultSleep2(ms) {
56237
56330
  }
56238
56331
  async function killStaleFrpc(deps) {
56239
56332
  const pidFile = frpcPidFilePath(deps.dataDir);
56240
- const tomlPath = import_node_path42.default.join(deps.dataDir, "frpc.toml");
56333
+ const tomlPath = import_node_path43.default.join(deps.dataDir, "frpc.toml");
56241
56334
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
56242
56335
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
56243
56336
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -56261,7 +56354,7 @@ async function killStaleFrpc(deps) {
56261
56354
  }
56262
56355
  if (victims.size === 0) {
56263
56356
  try {
56264
- import_node_fs38.default.unlinkSync(pidFile);
56357
+ import_node_fs39.default.unlinkSync(pidFile);
56265
56358
  } catch {
56266
56359
  }
56267
56360
  return;
@@ -56272,7 +56365,7 @@ async function killStaleFrpc(deps) {
56272
56365
  }
56273
56366
  await sleep2(deps.reapWaitMs ?? 300);
56274
56367
  try {
56275
- import_node_fs38.default.unlinkSync(pidFile);
56368
+ import_node_fs39.default.unlinkSync(pidFile);
56276
56369
  } catch {
56277
56370
  }
56278
56371
  }
@@ -56309,7 +56402,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
56309
56402
  var TunnelManager = class {
56310
56403
  constructor(deps) {
56311
56404
  this.deps = deps;
56312
- this.store = deps.store ?? new TunnelStore(import_node_path43.default.join(deps.dataDir, "tunnel.json"));
56405
+ this.store = deps.store ?? new TunnelStore(import_node_path44.default.join(deps.dataDir, "tunnel.json"));
56313
56406
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
56314
56407
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
56315
56408
  }
@@ -56436,7 +56529,7 @@ var TunnelManager = class {
56436
56529
  dataDir: this.deps.dataDir,
56437
56530
  override: this.deps.frpcBinaryOverride ?? void 0
56438
56531
  });
56439
- const tomlPath = import_node_path43.default.join(this.deps.dataDir, "frpc.toml");
56532
+ const tomlPath = import_node_path44.default.join(this.deps.dataDir, "frpc.toml");
56440
56533
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto10.default.randomBytes(3).toString("hex")}`;
56441
56534
  const toml = buildFrpcToml({
56442
56535
  serverAddr: t.frpsHost,
@@ -56447,14 +56540,14 @@ var TunnelManager = class {
56447
56540
  localPort,
56448
56541
  logLevel: "info"
56449
56542
  });
56450
- await import_node_fs39.default.promises.writeFile(tomlPath, toml, { mode: 384 });
56543
+ await import_node_fs40.default.promises.writeFile(tomlPath, toml, { mode: 384 });
56451
56544
  const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
56452
56545
  stdio: ["ignore", "pipe", "pipe"]
56453
56546
  });
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 });
56547
+ const logDir = import_node_path44.default.join(this.deps.dataDir, "log");
56548
+ import_node_fs40.default.mkdirSync(logDir, { recursive: true });
56549
+ const logFilePath = import_node_path44.default.join(logDir, "frpc.log");
56550
+ const logStream = import_node_fs40.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
56458
56551
  logStream.on("error", () => {
56459
56552
  });
56460
56553
  const tee = (chunk) => {
@@ -56537,27 +56630,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
56537
56630
 
56538
56631
  // src/tunnel/device-key.ts
56539
56632
  var import_node_os14 = __toESM(require("os"), 1);
56540
- var import_node_path44 = __toESM(require("path"), 1);
56633
+ var import_node_path45 = __toESM(require("path"), 1);
56541
56634
  var import_node_crypto11 = __toESM(require("crypto"), 1);
56542
56635
  var DERIVE_SALT = "clawd-tunnel-device-v1";
56543
56636
  function deriveStableDeviceKey(opts = {}) {
56544
56637
  const hostname = opts.hostname ?? import_node_os14.default.hostname();
56545
56638
  const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
56546
56639
  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;
56640
+ const defaultDataDir = import_node_path45.default.resolve(import_node_path45.default.join(home, ".clawd"));
56641
+ const normalizedDataDir = opts.dataDir ? import_node_path45.default.resolve(opts.dataDir) : null;
56549
56642
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
56550
56643
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
56551
56644
  return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
56552
56645
  }
56553
56646
 
56554
56647
  // src/auth-store.ts
56555
- var import_node_fs40 = __toESM(require("fs"), 1);
56556
- var import_node_path45 = __toESM(require("path"), 1);
56648
+ var import_node_fs41 = __toESM(require("fs"), 1);
56649
+ var import_node_path46 = __toESM(require("path"), 1);
56557
56650
  var import_node_crypto12 = __toESM(require("crypto"), 1);
56558
56651
  var AUTH_FILE_NAME = "auth.json";
56559
56652
  function authFilePath(dataDir) {
56560
- return import_node_path45.default.join(dataDir, AUTH_FILE_NAME);
56653
+ return import_node_path46.default.join(dataDir, AUTH_FILE_NAME);
56561
56654
  }
56562
56655
  function loadOrCreateAuthFile(opts) {
56563
56656
  const file = authFilePath(opts.dataDir);
@@ -56589,7 +56682,7 @@ function defaultGenerateOwnerPrincipalId() {
56589
56682
  }
56590
56683
  function readAuthFile(file) {
56591
56684
  try {
56592
- const raw = import_node_fs40.default.readFileSync(file, "utf8");
56685
+ const raw = import_node_fs41.default.readFileSync(file, "utf8");
56593
56686
  const parsed = JSON.parse(raw);
56594
56687
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
56595
56688
  return null;
@@ -56609,25 +56702,25 @@ function readAuthFile(file) {
56609
56702
  }
56610
56703
  }
56611
56704
  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 });
56705
+ import_node_fs41.default.mkdirSync(import_node_path46.default.dirname(file), { recursive: true });
56706
+ import_node_fs41.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
56614
56707
  try {
56615
- import_node_fs40.default.chmodSync(file, 384);
56708
+ import_node_fs41.default.chmodSync(file, 384);
56616
56709
  } catch {
56617
56710
  }
56618
56711
  }
56619
56712
 
56620
56713
  // src/owner-profile.ts
56621
- var import_node_fs41 = __toESM(require("fs"), 1);
56714
+ var import_node_fs42 = __toESM(require("fs"), 1);
56622
56715
  var import_node_os15 = __toESM(require("os"), 1);
56623
- var import_node_path46 = __toESM(require("path"), 1);
56716
+ var import_node_path47 = __toESM(require("path"), 1);
56624
56717
  var PROFILE_FILENAME = "profile.json";
56625
56718
  function loadOwnerDisplayName(dataDir) {
56626
56719
  const fallback = import_node_os15.default.userInfo().username;
56627
- const profilePath = import_node_path46.default.join(dataDir, PROFILE_FILENAME);
56720
+ const profilePath = import_node_path47.default.join(dataDir, PROFILE_FILENAME);
56628
56721
  let raw;
56629
56722
  try {
56630
- raw = import_node_fs41.default.readFileSync(profilePath, "utf8");
56723
+ raw = import_node_fs42.default.readFileSync(profilePath, "utf8");
56631
56724
  } catch {
56632
56725
  return fallback;
56633
56726
  }
@@ -56650,18 +56743,18 @@ function loadOwnerDisplayName(dataDir) {
56650
56743
  }
56651
56744
 
56652
56745
  // 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);
56746
+ var import_node_fs43 = __toESM(require("fs"), 1);
56747
+ var import_node_path48 = __toESM(require("path"), 1);
56655
56748
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
56656
56749
  var OwnerIdentityStore = class {
56657
56750
  file;
56658
56751
  constructor(dataDir) {
56659
- this.file = import_node_path47.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
56752
+ this.file = import_node_path48.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
56660
56753
  }
56661
56754
  read() {
56662
56755
  let raw;
56663
56756
  try {
56664
- raw = import_node_fs42.default.readFileSync(this.file, "utf8");
56757
+ raw = import_node_fs43.default.readFileSync(this.file, "utf8");
56665
56758
  } catch {
56666
56759
  return null;
56667
56760
  }
@@ -56689,16 +56782,16 @@ var OwnerIdentityStore = class {
56689
56782
  };
56690
56783
  }
56691
56784
  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 });
56785
+ import_node_fs43.default.mkdirSync(import_node_path48.default.dirname(this.file), { recursive: true });
56786
+ import_node_fs43.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
56694
56787
  try {
56695
- import_node_fs42.default.chmodSync(this.file, 384);
56788
+ import_node_fs43.default.chmodSync(this.file, 384);
56696
56789
  } catch {
56697
56790
  }
56698
56791
  }
56699
56792
  clear() {
56700
56793
  try {
56701
- import_node_fs42.default.unlinkSync(this.file);
56794
+ import_node_fs43.default.unlinkSync(this.file);
56702
56795
  } catch (err) {
56703
56796
  const code = err?.code;
56704
56797
  if (code !== "ENOENT") throw err;
@@ -56835,9 +56928,9 @@ var CentralClientError = class extends Error {
56835
56928
  code;
56836
56929
  cause;
56837
56930
  };
56838
- async function centralRequest(opts, path78, init) {
56931
+ async function centralRequest(opts, path79, init) {
56839
56932
  const f = opts.fetchImpl ?? globalThis.fetch;
56840
- const url = `${opts.api.replace(/\/+$/, "")}${path78}`;
56933
+ const url = `${opts.api.replace(/\/+$/, "")}${path79}`;
56841
56934
  const ctrl = new AbortController();
56842
56935
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
56843
56936
  let res;
@@ -57031,8 +57124,8 @@ function verifyConnectToken(args) {
57031
57124
  }
57032
57125
 
57033
57126
  // src/feishu-auth/server-key.ts
57034
- var fs52 = __toESM(require("fs"), 1);
57035
- var path56 = __toESM(require("path"), 1);
57127
+ var fs53 = __toESM(require("fs"), 1);
57128
+ var path57 = __toESM(require("path"), 1);
57036
57129
  var FILE_NAME2 = "server-signing-key.json";
57037
57130
  var ServerKeyStore = class {
57038
57131
  constructor(dataDir) {
@@ -57040,12 +57133,12 @@ var ServerKeyStore = class {
57040
57133
  }
57041
57134
  dataDir;
57042
57135
  filePath() {
57043
- return path56.join(this.dataDir, FILE_NAME2);
57136
+ return path57.join(this.dataDir, FILE_NAME2);
57044
57137
  }
57045
57138
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
57046
57139
  read() {
57047
57140
  try {
57048
- const raw = fs52.readFileSync(this.filePath(), "utf8");
57141
+ const raw = fs53.readFileSync(this.filePath(), "utf8");
57049
57142
  const parsed = JSON.parse(raw);
57050
57143
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
57051
57144
  return parsed.publicKeyPem;
@@ -57060,12 +57153,12 @@ var ServerKeyStore = class {
57060
57153
  publicKeyPem,
57061
57154
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
57062
57155
  };
57063
- fs52.mkdirSync(this.dataDir, { recursive: true });
57064
- fs52.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
57156
+ fs53.mkdirSync(this.dataDir, { recursive: true });
57157
+ fs53.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
57065
57158
  }
57066
57159
  clear() {
57067
57160
  try {
57068
- fs52.unlinkSync(this.filePath());
57161
+ fs53.unlinkSync(this.filePath());
57069
57162
  } catch {
57070
57163
  }
57071
57164
  }
@@ -57078,12 +57171,12 @@ init_protocol();
57078
57171
  init_protocol();
57079
57172
 
57080
57173
  // src/session/fork.ts
57081
- var import_node_fs43 = __toESM(require("fs"), 1);
57174
+ var import_node_fs44 = __toESM(require("fs"), 1);
57082
57175
  var import_node_os16 = __toESM(require("os"), 1);
57083
- var import_node_path48 = __toESM(require("path"), 1);
57176
+ var import_node_path49 = __toESM(require("path"), 1);
57084
57177
  init_claude_history();
57085
57178
  function readJsonlEntries(file) {
57086
- const raw = import_node_fs43.default.readFileSync(file, "utf8");
57179
+ const raw = import_node_fs44.default.readFileSync(file, "utf8");
57087
57180
  const out = [];
57088
57181
  for (const line of raw.split("\n")) {
57089
57182
  const t = line.trim();
@@ -57096,19 +57189,19 @@ function readJsonlEntries(file) {
57096
57189
  return out;
57097
57190
  }
57098
57191
  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)) {
57192
+ const baseDir = input.baseDir ?? import_node_path49.default.join(import_node_os16.default.homedir(), ".claude");
57193
+ let projectDir = import_node_path49.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
57194
+ let sourceFile = import_node_path49.default.join(projectDir, `${input.toolSessionId}.jsonl`);
57195
+ if (!import_node_fs44.default.existsSync(sourceFile)) {
57103
57196
  const found = findTranscriptByToolSessionId(
57104
- import_node_path48.default.join(baseDir, "projects"),
57197
+ import_node_path49.default.join(baseDir, "projects"),
57105
57198
  input.toolSessionId
57106
57199
  );
57107
57200
  if (!found) {
57108
57201
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
57109
57202
  }
57110
57203
  sourceFile = found;
57111
- projectDir = import_node_path48.default.dirname(found);
57204
+ projectDir = import_node_path49.default.dirname(found);
57112
57205
  }
57113
57206
  const entries = readJsonlEntries(sourceFile);
57114
57207
  const mainEntries = entries.filter((e) => e.isSidechain !== true);
@@ -57137,10 +57230,10 @@ function forkSession(input) {
57137
57230
  }
57138
57231
  forkedLines.push(JSON.stringify(forked));
57139
57232
  }
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 });
57233
+ const outDir = input.targetCwd ? import_node_path49.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
57234
+ const forkedFilePath = import_node_path49.default.join(outDir, `${forkedToolSessionId}.jsonl`);
57235
+ import_node_fs44.default.mkdirSync(outDir, { recursive: true });
57236
+ import_node_fs44.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
57144
57237
  return { forkedToolSessionId, forkedFilePath };
57145
57238
  }
57146
57239
 
@@ -57599,7 +57692,7 @@ function buildPermissionHandlers(deps) {
57599
57692
  }
57600
57693
 
57601
57694
  // src/handlers/history.ts
57602
- var path59 = __toESM(require("path"), 1);
57695
+ var path60 = __toESM(require("path"), 1);
57603
57696
  init_protocol();
57604
57697
 
57605
57698
  // src/session/recent-dirs.ts
@@ -57617,7 +57710,7 @@ function listRecentDirs(store, limit = 50) {
57617
57710
  }
57618
57711
 
57619
57712
  // src/permission/persona-paths.ts
57620
- var path58 = __toESM(require("path"), 1);
57713
+ var path59 = __toESM(require("path"), 1);
57621
57714
  function getAllowedPersonaIds(grants, action) {
57622
57715
  const ids = /* @__PURE__ */ new Set();
57623
57716
  for (const g2 of grants) {
@@ -57630,42 +57723,42 @@ function getAllowedPersonaIds(grants, action) {
57630
57723
  return ids;
57631
57724
  }
57632
57725
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
57633
- const target = path58.resolve(absPath);
57726
+ const target = path59.resolve(absPath);
57634
57727
  if (userWorkDir) {
57635
- const u = path58.resolve(userWorkDir);
57636
- const usep = u.endsWith(path58.sep) ? "" : path58.sep;
57728
+ const u = path59.resolve(userWorkDir);
57729
+ const usep = u.endsWith(path59.sep) ? "" : path59.sep;
57637
57730
  if (target === u || target.startsWith(u + usep)) return true;
57638
57731
  }
57639
- const root = path58.resolve(personaRoot);
57640
- const sep3 = root.endsWith(path58.sep) ? "" : path58.sep;
57732
+ const root = path59.resolve(personaRoot);
57733
+ const sep3 = root.endsWith(path59.sep) ? "" : path59.sep;
57641
57734
  if (!target.startsWith(root + sep3)) return false;
57642
- const rel = path58.relative(root, target);
57735
+ const rel = path59.relative(root, target);
57643
57736
  if (!rel || rel.startsWith("..")) return false;
57644
- const personaId2 = rel.split(path58.sep)[0];
57737
+ const personaId2 = rel.split(path59.sep)[0];
57645
57738
  if (!personaId2) return false;
57646
57739
  const allowed = getAllowedPersonaIds(grants, action);
57647
57740
  if (allowed === "*") return true;
57648
57741
  return allowed.has(personaId2);
57649
57742
  }
57650
57743
  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;
57744
+ const root = path59.resolve(personaRoot);
57745
+ const target = path59.resolve(absPath);
57746
+ const sep3 = root.endsWith(path59.sep) ? "" : path59.sep;
57654
57747
  if (!target.startsWith(root + sep3)) return null;
57655
- const rel = path58.relative(root, target);
57748
+ const rel = path59.relative(root, target);
57656
57749
  if (!rel || rel.startsWith("..")) return null;
57657
- const id = rel.split(path58.sep)[0];
57750
+ const id = rel.split(path59.sep)[0];
57658
57751
  return id || null;
57659
57752
  }
57660
57753
  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;
57754
+ const d = path59.resolve(dir);
57755
+ const t = path59.resolve(absPath);
57756
+ const sep3 = d.endsWith(path59.sep) ? "" : path59.sep;
57664
57757
  return t === d || t.startsWith(d + sep3);
57665
57758
  }
57666
57759
  function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
57667
57760
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
57668
- return personaIdFromPath(path58.resolve(absPath), personaRoot) === personaId2;
57761
+ return personaIdFromPath(path59.resolve(absPath), personaRoot) === personaId2;
57669
57762
  }
57670
57763
 
57671
57764
  // src/handlers/history.ts
@@ -57717,7 +57810,7 @@ function buildHistoryHandlers(deps) {
57717
57810
  if (!pid) return false;
57718
57811
  return isGuestPathAllowed(
57719
57812
  ctx.grants,
57720
- path59.join(personaRoot, pid),
57813
+ path60.join(personaRoot, pid),
57721
57814
  personaRoot,
57722
57815
  "read",
57723
57816
  userWorkDir
@@ -57729,7 +57822,7 @@ function buildHistoryHandlers(deps) {
57729
57822
  };
57730
57823
  const list = async (frame, _client, ctx) => {
57731
57824
  const args = HistoryListArgs.parse(frame);
57732
- assertGuestPath(ctx, path59.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
57825
+ assertGuestPath(ctx, path60.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
57733
57826
  const sessions = await history.listSessions(args);
57734
57827
  return { response: { type: "history:list", sessions } };
57735
57828
  };
@@ -57773,14 +57866,14 @@ function buildHistoryHandlers(deps) {
57773
57866
  };
57774
57867
  const subagents = async (frame, _client, ctx) => {
57775
57868
  const args = HistorySubagentsArgs.parse(frame);
57776
- assertGuestPath(ctx, path59.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
57869
+ assertGuestPath(ctx, path60.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
57777
57870
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
57778
57871
  const subs = await history.listSubagents(args);
57779
57872
  return { response: { type: "history:subagents", subagents: subs } };
57780
57873
  };
57781
57874
  const subagentRead = async (frame, _client, ctx) => {
57782
57875
  const args = HistorySubagentReadArgs.parse(frame);
57783
- assertGuestPath(ctx, path59.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
57876
+ assertGuestPath(ctx, path60.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
57784
57877
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
57785
57878
  const res = await history.readSubagent(args);
57786
57879
  return { response: { type: "history:subagent-read", ...res } };
@@ -57790,7 +57883,7 @@ function buildHistoryHandlers(deps) {
57790
57883
  if (ctx?.principal.kind === "guest" && personaRoot) {
57791
57884
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
57792
57885
  const filtered = dirs.filter(
57793
- (d) => isGuestPathAllowed(ctx.grants, path59.resolve(d.cwd), personaRoot, "read", userWorkDir)
57886
+ (d) => isGuestPathAllowed(ctx.grants, path60.resolve(d.cwd), personaRoot, "read", userWorkDir)
57794
57887
  );
57795
57888
  return { response: { type: "history:recentDirs", dirs: filtered } };
57796
57889
  }
@@ -57807,7 +57900,7 @@ function buildHistoryHandlers(deps) {
57807
57900
  }
57808
57901
 
57809
57902
  // src/handlers/workspace.ts
57810
- var path60 = __toESM(require("path"), 1);
57903
+ var path61 = __toESM(require("path"), 1);
57811
57904
  var os16 = __toESM(require("os"), 1);
57812
57905
  init_protocol();
57813
57906
  init_protocol();
@@ -57849,22 +57942,22 @@ function buildWorkspaceHandlers(deps) {
57849
57942
  const args = WorkspaceListArgs.parse(frame);
57850
57943
  const isGuest = ctx?.principal.kind === "guest";
57851
57944
  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;
57945
+ const resolvedCwd = path61.resolve(args.cwd ?? fallbackCwd);
57946
+ const target = args.path ? path61.resolve(resolvedCwd, args.path) : resolvedCwd;
57854
57947
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
57855
57948
  const res = workspace.list({ ...args, cwd: resolvedCwd });
57856
57949
  return { response: { type: "workspace:list", ...res } };
57857
57950
  };
57858
57951
  const read = async (frame, _client, ctx) => {
57859
57952
  const args = WorkspaceReadArgs.parse(frame);
57860
- const target = path60.isAbsolute(args.path) ? path60.resolve(args.path) : path60.resolve(args.cwd, args.path);
57953
+ const target = path61.isAbsolute(args.path) ? path61.resolve(args.path) : path61.resolve(args.cwd, args.path);
57861
57954
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
57862
57955
  const res = workspace.read(args);
57863
57956
  return { response: { type: "workspace:read", ...res } };
57864
57957
  };
57865
57958
  const skillsList = async (frame, _client, ctx) => {
57866
57959
  const args = SkillsListArgs.parse(frame);
57867
- const cwdAbs = path60.resolve(args.cwd);
57960
+ const cwdAbs = path61.resolve(args.cwd);
57868
57961
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
57869
57962
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
57870
57963
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -57876,7 +57969,7 @@ function buildWorkspaceHandlers(deps) {
57876
57969
  };
57877
57970
  const agentsList = async (frame, _client, ctx) => {
57878
57971
  const args = AgentsListArgs.parse(frame);
57879
- const cwdAbs = path60.resolve(args.cwd);
57972
+ const cwdAbs = path61.resolve(args.cwd);
57880
57973
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
57881
57974
  if (args.tool === "codex") {
57882
57975
  return { response: { type: "agents:list", agents: [] } };
@@ -57898,20 +57991,20 @@ function buildWorkspaceHandlers(deps) {
57898
57991
  }
57899
57992
 
57900
57993
  // src/handlers/git.ts
57901
- var path62 = __toESM(require("path"), 1);
57994
+ var path63 = __toESM(require("path"), 1);
57902
57995
  init_protocol();
57903
57996
  init_protocol();
57904
57997
 
57905
57998
  // src/workspace/git.ts
57906
57999
  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);
58000
+ var import_node_fs45 = __toESM(require("fs"), 1);
58001
+ var import_node_path50 = __toESM(require("path"), 1);
57909
58002
  var import_node_util = require("util");
57910
58003
  var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
57911
58004
  function normalizePath(p2) {
57912
- const resolved = import_node_path49.default.resolve(p2);
58005
+ const resolved = import_node_path50.default.resolve(p2);
57913
58006
  try {
57914
- return import_node_fs44.default.realpathSync(resolved);
58007
+ return import_node_fs45.default.realpathSync(resolved);
57915
58008
  } catch {
57916
58009
  return resolved;
57917
58010
  }
@@ -57985,7 +58078,7 @@ async function listGitBranches(cwd) {
57985
58078
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
57986
58079
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
57987
58080
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
57988
- if (!isGuestPathAllowed(ctx.grants, path62.resolve(cwd), personaRoot, "read", userWorkDir)) {
58081
+ if (!isGuestPathAllowed(ctx.grants, path63.resolve(cwd), personaRoot, "read", userWorkDir)) {
57989
58082
  throw new ClawdError(
57990
58083
  ERROR_CODES.UNAUTHORIZED,
57991
58084
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -58850,21 +58943,21 @@ function computeMethodAccess(args) {
58850
58943
  }
58851
58944
 
58852
58945
  // src/version.ts
58853
- var version = "0.2.293".length > 0 ? "0.2.293" : "dev";
58946
+ var version = "0.2.294".length > 0 ? "0.2.294" : "dev";
58854
58947
 
58855
58948
  // src/cli-probe/probe.ts
58856
- var fs55 = __toESM(require("fs"), 1);
58857
- var path63 = __toESM(require("path"), 1);
58949
+ var fs56 = __toESM(require("fs"), 1);
58950
+ var path64 = __toESM(require("path"), 1);
58858
58951
  var PKG_NAME = "@clawos-dev/clawd";
58859
58952
  var BIN_NAME = "clawd";
58860
58953
  var MAX_PARENT_HOPS = 5;
58861
58954
  function probeGlobalCli(pathEnv) {
58862
58955
  if (!pathEnv) return null;
58863
- for (const dir of pathEnv.split(path63.delimiter)) {
58956
+ for (const dir of pathEnv.split(path64.delimiter)) {
58864
58957
  if (!dir) continue;
58865
58958
  let real;
58866
58959
  try {
58867
- real = fs55.realpathSync(path63.join(dir, BIN_NAME));
58960
+ real = fs56.realpathSync(path64.join(dir, BIN_NAME));
58868
58961
  } catch {
58869
58962
  continue;
58870
58963
  }
@@ -58874,15 +58967,15 @@ function probeGlobalCli(pathEnv) {
58874
58967
  return null;
58875
58968
  }
58876
58969
  function readOwnPackageVersion(entryPath) {
58877
- let dir = path63.dirname(entryPath);
58970
+ let dir = path64.dirname(entryPath);
58878
58971
  for (let i = 0; i < MAX_PARENT_HOPS; i++) {
58879
58972
  try {
58880
- const raw = fs55.readFileSync(path63.join(dir, "package.json"), "utf8");
58973
+ const raw = fs56.readFileSync(path64.join(dir, "package.json"), "utf8");
58881
58974
  const pkg = JSON.parse(raw);
58882
58975
  if (pkg.name !== PKG_NAME) return null;
58883
58976
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
58884
58977
  } catch {
58885
- const parent = path63.dirname(dir);
58978
+ const parent = path64.dirname(dir);
58886
58979
  if (parent === dir) return null;
58887
58980
  dir = parent;
58888
58981
  }
@@ -59040,7 +59133,7 @@ function buildPersonaHandlers(deps) {
59040
59133
  }
59041
59134
 
59042
59135
  // src/handlers/attachment.ts
59043
- var import_node_path50 = __toESM(require("path"), 1);
59136
+ var import_node_path51 = __toESM(require("path"), 1);
59044
59137
  init_protocol();
59045
59138
  init_protocol();
59046
59139
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -59120,12 +59213,12 @@ function buildAttachmentHandlers(deps) {
59120
59213
  `session ${args.sessionId} scope unresolved`
59121
59214
  );
59122
59215
  }
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);
59216
+ const cwdAbs = import_node_path51.default.resolve(sessionFile.cwd);
59217
+ 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
59218
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
59126
59219
  const entries = deps.groupFileStore.list(scope, args.sessionId);
59127
59220
  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);
59221
+ 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
59222
  return storedAbs === candidateAbs && !e.stale;
59130
59223
  });
59131
59224
  if (!entry) {
@@ -59150,7 +59243,7 @@ function buildAttachmentHandlers(deps) {
59150
59243
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
59151
59244
  const f = deps.sessionStore.read(sessionId);
59152
59245
  if (!f) return;
59153
- assertGuestAttachmentPath(ctx, import_node_path50.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
59246
+ assertGuestAttachmentPath(ctx, import_node_path51.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
59154
59247
  }
59155
59248
  const groupAdd = async (frame, _client, ctx) => {
59156
59249
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -59165,8 +59258,8 @@ function buildAttachmentHandlers(deps) {
59165
59258
  if (!scope) {
59166
59259
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
59167
59260
  }
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);
59261
+ const cwdAbs = import_node_path51.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
59262
+ 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
59263
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
59171
59264
  const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
59172
59265
  const size = 0;
@@ -59225,19 +59318,19 @@ function buildAttachmentHandlers(deps) {
59225
59318
 
59226
59319
  // src/handlers/extension.ts
59227
59320
  var import_promises9 = __toESM(require("fs/promises"), 1);
59228
- var import_node_path55 = __toESM(require("path"), 1);
59321
+ var import_node_path56 = __toESM(require("path"), 1);
59229
59322
  init_protocol();
59230
59323
 
59231
59324
  // src/extension/bundle-zip.ts
59232
59325
  var import_promises6 = __toESM(require("fs/promises"), 1);
59233
- var import_node_path51 = __toESM(require("path"), 1);
59326
+ var import_node_path52 = __toESM(require("path"), 1);
59234
59327
  var import_node_crypto14 = __toESM(require("crypto"), 1);
59235
59328
  var import_jszip2 = __toESM(require_lib3(), 1);
59236
59329
  async function bundleExtensionDir(dir) {
59237
59330
  const entries = await listFilesSorted(dir);
59238
59331
  const zip = new import_jszip2.default();
59239
59332
  for (const rel of entries) {
59240
- const abs = import_node_path51.default.join(dir, rel);
59333
+ const abs = import_node_path52.default.join(dir, rel);
59241
59334
  const content = await import_promises6.default.readFile(abs);
59242
59335
  zip.file(rel, content, { date: FIXED_DATE });
59243
59336
  }
@@ -59258,7 +59351,7 @@ async function listFilesSorted(rootDir) {
59258
59351
  return out;
59259
59352
  }
59260
59353
  async function walk(absRoot, relPrefix, out) {
59261
- const dirAbs = import_node_path51.default.join(absRoot, relPrefix);
59354
+ const dirAbs = import_node_path52.default.join(absRoot, relPrefix);
59262
59355
  const entries = await import_promises6.default.readdir(dirAbs, { withFileTypes: true });
59263
59356
  for (const e of entries) {
59264
59357
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -59312,25 +59405,25 @@ function computePublishCheck(args) {
59312
59405
 
59313
59406
  // src/extension/install-flow.ts
59314
59407
  var import_promises7 = __toESM(require("fs/promises"), 1);
59315
- var import_node_path53 = __toESM(require("path"), 1);
59408
+ var import_node_path54 = __toESM(require("path"), 1);
59316
59409
  var import_node_os19 = __toESM(require("os"), 1);
59317
59410
  var import_node_crypto15 = __toESM(require("crypto"), 1);
59318
59411
  var import_jszip3 = __toESM(require_lib3(), 1);
59319
59412
 
59320
59413
  // src/extension/paths.ts
59321
59414
  var import_node_os18 = __toESM(require("os"), 1);
59322
- var import_node_path52 = __toESM(require("path"), 1);
59415
+ var import_node_path53 = __toESM(require("path"), 1);
59323
59416
  function clawdHomeRoot(override) {
59324
- return override ?? process.env.CLAWD_HOME ?? import_node_path52.default.join(import_node_os18.default.homedir(), ".clawd");
59417
+ return override ?? process.env.CLAWD_HOME ?? import_node_path53.default.join(import_node_os18.default.homedir(), ".clawd");
59325
59418
  }
59326
59419
  function extensionsRoot(override) {
59327
- return import_node_path52.default.join(clawdHomeRoot(override), "extensions");
59420
+ return import_node_path53.default.join(clawdHomeRoot(override), "extensions");
59328
59421
  }
59329
59422
  function publishedChannelsFile(override) {
59330
- return import_node_path52.default.join(clawdHomeRoot(override), "extensions-published.json");
59423
+ return import_node_path53.default.join(clawdHomeRoot(override), "extensions-published.json");
59331
59424
  }
59332
59425
  function bundleCacheRoot(override) {
59333
- return import_node_path52.default.join(clawdHomeRoot(override), "extension-bundles");
59426
+ return import_node_path53.default.join(clawdHomeRoot(override), "extension-bundles");
59334
59427
  }
59335
59428
 
59336
59429
  // src/extension/install-flow.ts
@@ -59357,7 +59450,7 @@ async function installFromChannel(args, deps) {
59357
59450
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
59358
59451
  }
59359
59452
  for (const name of Object.keys(zip.files)) {
59360
- if (name.includes("..") || name.startsWith("/") || import_node_path53.default.isAbsolute(name)) {
59453
+ if (name.includes("..") || name.startsWith("/") || import_node_path54.default.isAbsolute(name)) {
59361
59454
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
59362
59455
  }
59363
59456
  }
@@ -59389,7 +59482,7 @@ async function installFromChannel(args, deps) {
59389
59482
  );
59390
59483
  }
59391
59484
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
59392
- const destDir = import_node_path53.default.join(deps.extensionsRoot, localExtId);
59485
+ const destDir = import_node_path54.default.join(deps.extensionsRoot, localExtId);
59393
59486
  let destExists = false;
59394
59487
  try {
59395
59488
  await import_promises7.default.access(destDir);
@@ -59403,16 +59496,16 @@ async function installFromChannel(args, deps) {
59403
59496
  );
59404
59497
  }
59405
59498
  const stage = await import_promises7.default.mkdtemp(
59406
- import_node_path53.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
59499
+ import_node_path54.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
59407
59500
  );
59408
59501
  try {
59409
59502
  for (const [name, entry] of Object.entries(zip.files)) {
59410
- const dest = import_node_path53.default.join(stage, name);
59503
+ const dest = import_node_path54.default.join(stage, name);
59411
59504
  if (entry.dir) {
59412
59505
  await import_promises7.default.mkdir(dest, { recursive: true });
59413
59506
  continue;
59414
59507
  }
59415
- await import_promises7.default.mkdir(import_node_path53.default.dirname(dest), { recursive: true });
59508
+ await import_promises7.default.mkdir(import_node_path54.default.dirname(dest), { recursive: true });
59416
59509
  if (name === "manifest.json") {
59417
59510
  const rewritten = { ...parsed.data, id: localExtId };
59418
59511
  await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -59433,7 +59526,7 @@ async function installFromChannel(args, deps) {
59433
59526
 
59434
59527
  // src/extension/update-flow.ts
59435
59528
  var import_promises8 = __toESM(require("fs/promises"), 1);
59436
- var import_node_path54 = __toESM(require("path"), 1);
59529
+ var import_node_path55 = __toESM(require("path"), 1);
59437
59530
  var import_node_os20 = __toESM(require("os"), 1);
59438
59531
  var import_node_crypto16 = __toESM(require("crypto"), 1);
59439
59532
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -59450,11 +59543,11 @@ async function updateFromChannel(args, deps) {
59450
59543
  channelRef.extId,
59451
59544
  channelRef.ownerPrincipalId
59452
59545
  );
59453
- const liveDir = import_node_path54.default.join(deps.extensionsRoot, localExtId);
59546
+ const liveDir = import_node_path55.default.join(deps.extensionsRoot, localExtId);
59454
59547
  const prevDir = `${liveDir}.prev`;
59455
59548
  let existingVersion;
59456
59549
  try {
59457
- const raw = await import_promises8.default.readFile(import_node_path54.default.join(liveDir, "manifest.json"), "utf8");
59550
+ const raw = await import_promises8.default.readFile(import_node_path55.default.join(liveDir, "manifest.json"), "utf8");
59458
59551
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
59459
59552
  if (!parsed2.success) {
59460
59553
  throw new UpdateError(
@@ -59487,7 +59580,7 @@ async function updateFromChannel(args, deps) {
59487
59580
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
59488
59581
  }
59489
59582
  for (const name of Object.keys(zip.files)) {
59490
- if (name.includes("..") || name.startsWith("/") || import_node_path54.default.isAbsolute(name)) {
59583
+ if (name.includes("..") || name.startsWith("/") || import_node_path55.default.isAbsolute(name)) {
59491
59584
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
59492
59585
  }
59493
59586
  }
@@ -59522,16 +59615,16 @@ async function updateFromChannel(args, deps) {
59522
59615
  await import_promises8.default.rm(prevDir, { recursive: true, force: true });
59523
59616
  await import_promises8.default.rename(liveDir, prevDir);
59524
59617
  const stage = await import_promises8.default.mkdtemp(
59525
- import_node_path54.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
59618
+ import_node_path55.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
59526
59619
  );
59527
59620
  try {
59528
59621
  for (const [name, entry] of Object.entries(zip.files)) {
59529
- const dest = import_node_path54.default.join(stage, name);
59622
+ const dest = import_node_path55.default.join(stage, name);
59530
59623
  if (entry.dir) {
59531
59624
  await import_promises8.default.mkdir(dest, { recursive: true });
59532
59625
  continue;
59533
59626
  }
59534
- await import_promises8.default.mkdir(import_node_path54.default.dirname(dest), { recursive: true });
59627
+ await import_promises8.default.mkdir(import_node_path55.default.dirname(dest), { recursive: true });
59535
59628
  if (name === "manifest.json") {
59536
59629
  const rewritten = { ...parsed.data, id: localExtId };
59537
59630
  await import_promises8.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -59598,7 +59691,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
59598
59691
  );
59599
59692
  }
59600
59693
  }
59601
- const manifestPath = import_node_path55.default.join(root, extId, "manifest.json");
59694
+ const manifestPath = import_node_path56.default.join(root, extId, "manifest.json");
59602
59695
  const manifest = await readManifest(root, extId);
59603
59696
  const next = { ...manifest, version: newVersion };
59604
59697
  const tmp = `${manifestPath}.tmp`;
@@ -59606,7 +59699,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
59606
59699
  await import_promises9.default.rename(tmp, manifestPath);
59607
59700
  }
59608
59701
  async function readManifest(root, extId) {
59609
- const file = import_node_path55.default.join(root, extId, "manifest.json");
59702
+ const file = import_node_path56.default.join(root, extId, "manifest.json");
59610
59703
  let raw;
59611
59704
  try {
59612
59705
  raw = await import_promises9.default.readFile(file, "utf8");
@@ -59690,7 +59783,7 @@ function buildExtensionHandlers(deps) {
59690
59783
  };
59691
59784
  async function buildSnapshotMeta(extId) {
59692
59785
  const manifest = await readManifest(deps.root, extId);
59693
- const { sha256, buffer } = await bundleExtensionDir(import_node_path55.default.join(deps.root, extId));
59786
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path56.default.join(deps.root, extId));
59694
59787
  return { manifest, contentHash: sha256, buffer };
59695
59788
  }
59696
59789
  const publish = async (frame, _client, ctx) => {
@@ -59865,9 +59958,9 @@ function buildExtensionHandlers(deps) {
59865
59958
  }
59866
59959
 
59867
59960
  // src/app-builder/project-store.ts
59868
- var import_node_fs45 = require("fs");
59961
+ var import_node_fs46 = require("fs");
59869
59962
  var import_node_child_process11 = require("child_process");
59870
- var import_node_path56 = require("path");
59963
+ var import_node_path57 = require("path");
59871
59964
  init_protocol();
59872
59965
  var PROJECTS_DIR = "projects";
59873
59966
  var META_FILE = ".clawd-project.json";
@@ -59881,19 +59974,19 @@ var ProjectStore = class {
59881
59974
  root;
59882
59975
  /** projects/<name>/.clawd-project.json 路径 */
59883
59976
  metaPath(name) {
59884
- return (0, import_node_path56.join)(this.projectsRoot(), name, META_FILE);
59977
+ return (0, import_node_path57.join)(this.projectsRoot(), name, META_FILE);
59885
59978
  }
59886
59979
  /** projects/<name>/ 目录路径(cwd 用) */
59887
59980
  projectDir(name) {
59888
- return (0, import_node_path56.join)(this.projectsRoot(), name);
59981
+ return (0, import_node_path57.join)(this.projectsRoot(), name);
59889
59982
  }
59890
59983
  projectsRoot() {
59891
- return (0, import_node_path56.join)(this.root, PROJECTS_DIR);
59984
+ return (0, import_node_path57.join)(this.root, PROJECTS_DIR);
59892
59985
  }
59893
59986
  async list() {
59894
59987
  let entries;
59895
59988
  try {
59896
- entries = await import_node_fs45.promises.readdir(this.projectsRoot());
59989
+ entries = await import_node_fs46.promises.readdir(this.projectsRoot());
59897
59990
  } catch (err) {
59898
59991
  if (err.code === "ENOENT") return [];
59899
59992
  throw err;
@@ -59901,7 +59994,7 @@ var ProjectStore = class {
59901
59994
  const out = [];
59902
59995
  for (const name of entries) {
59903
59996
  try {
59904
- const raw = await import_node_fs45.promises.readFile(this.metaPath(name), "utf8");
59997
+ const raw = await import_node_fs46.promises.readFile(this.metaPath(name), "utf8");
59905
59998
  const json = JSON.parse(raw);
59906
59999
  let migrated = false;
59907
60000
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -59912,7 +60005,7 @@ var ProjectStore = class {
59912
60005
  if (parsed.success) {
59913
60006
  out.push(parsed.data);
59914
60007
  if (migrated) {
59915
- void import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
60008
+ void import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
59916
60009
  });
59917
60010
  }
59918
60011
  }
@@ -59956,8 +60049,8 @@ var ProjectStore = class {
59956
60049
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
59957
60050
  }
59958
60051
  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");
60052
+ await import_node_fs46.promises.mkdir(dir, { recursive: true });
60053
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
59961
60054
  return meta;
59962
60055
  }
59963
60056
  /**
@@ -60000,7 +60093,7 @@ var ProjectStore = class {
60000
60093
  }
60001
60094
  async delete(name) {
60002
60095
  const dir = this.projectDir(name);
60003
- await import_node_fs45.promises.rm(dir, { recursive: true, force: true });
60096
+ await import_node_fs46.promises.rm(dir, { recursive: true, force: true });
60004
60097
  }
60005
60098
  async updatePort(name, newPort) {
60006
60099
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -60016,7 +60109,7 @@ var ProjectStore = class {
60016
60109
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
60017
60110
  }
60018
60111
  const updated = { ...target, port: newPort };
60019
- await import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
60112
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
60020
60113
  return updated;
60021
60114
  }
60022
60115
  /**
@@ -60033,7 +60126,7 @@ var ProjectStore = class {
60033
60126
  if (!validated.success) {
60034
60127
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
60035
60128
  }
60036
- await import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60129
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60037
60130
  return validated.data;
60038
60131
  }
60039
60132
  /**
@@ -60054,7 +60147,7 @@ var ProjectStore = class {
60054
60147
  if (!validated.success) {
60055
60148
  throw new Error(`invalid publishJob: ${validated.error.message}`);
60056
60149
  }
60057
- await import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60150
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60058
60151
  return validated.data;
60059
60152
  }
60060
60153
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -60069,7 +60162,7 @@ var ProjectStore = class {
60069
60162
  if (!validated.success) {
60070
60163
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
60071
60164
  }
60072
- await import_node_fs45.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60165
+ await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
60073
60166
  return validated.data;
60074
60167
  }
60075
60168
  };
@@ -60190,8 +60283,8 @@ var PublishJobRegistry = class {
60190
60283
 
60191
60284
  // src/app-builder/publish-job-runner.ts
60192
60285
  var import_node_child_process13 = require("child_process");
60193
- var import_node_fs46 = require("fs");
60194
- var import_node_path57 = require("path");
60286
+ var import_node_fs47 = require("fs");
60287
+ var import_node_path58 = require("path");
60195
60288
 
60196
60289
  // src/app-builder/publish-stage-parser.ts
60197
60290
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -60223,10 +60316,10 @@ async function startPublishJob(deps, args) {
60223
60316
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
60224
60317
  }
60225
60318
  const projDir = projectDir(args.name);
60226
- const logPath = (0, import_node_path57.join)(projDir, ".publish.log");
60319
+ const logPath = (0, import_node_path58.join)(projDir, ".publish.log");
60227
60320
  let logStream = null;
60228
60321
  try {
60229
- logStream = (0, import_node_fs46.createWriteStream)(logPath, { flags: "w" });
60322
+ logStream = (0, import_node_fs47.createWriteStream)(logPath, { flags: "w" });
60230
60323
  } catch {
60231
60324
  logStream = null;
60232
60325
  }
@@ -60483,8 +60576,8 @@ async function recoverInterruptedJobs(deps) {
60483
60576
 
60484
60577
  // src/handlers/app-builder.ts
60485
60578
  init_protocol();
60486
- var import_node_path58 = require("path");
60487
- var import_node_fs47 = require("fs");
60579
+ var import_node_path59 = require("path");
60580
+ var import_node_fs48 = require("fs");
60488
60581
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
60489
60582
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
60490
60583
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -60565,7 +60658,7 @@ function buildAppBuilderHandlers(deps) {
60565
60658
  async function listAllUsersProjects() {
60566
60659
  if (!deps.usersRoot || !deps.getStore) return [];
60567
60660
  const getStore = deps.getStore;
60568
- const userIds = await import_node_fs47.promises.readdir(deps.usersRoot).catch(() => []);
60661
+ const userIds = await import_node_fs48.promises.readdir(deps.usersRoot).catch(() => []);
60569
60662
  const perUser = await Promise.all(
60570
60663
  userIds.map((uid) => getStore(uid).list().catch(() => []))
60571
60664
  );
@@ -60634,8 +60727,8 @@ function buildAppBuilderHandlers(deps) {
60634
60727
  const project = await userStore.create(f.name, reservedPorts);
60635
60728
  try {
60636
60729
  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");
60730
+ const templateSrcDir = (0, import_node_path59.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
60731
+ const scaffoldScript = (0, import_node_path59.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
60639
60732
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
60640
60733
  deps.logger?.info("app-builder.scaffold.done", {
60641
60734
  name: project.name,
@@ -60839,7 +60932,7 @@ function buildAppBuilderHandlers(deps) {
60839
60932
  await userStore.clearPublishJob(args.name);
60840
60933
  }
60841
60934
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
60842
- const scriptPath = (0, import_node_path58.join)(deps.deployKitRoot, "scripts", "publish.sh");
60935
+ const scriptPath = (0, import_node_path59.join)(deps.deployKitRoot, "scripts", "publish.sh");
60843
60936
  deps.logger?.info("app-builder.publish.start", {
60844
60937
  name: args.name,
60845
60938
  sessionId: boundSession.sessionId,
@@ -61015,7 +61108,7 @@ function buildVisitorHandlers(deps) {
61015
61108
 
61016
61109
  // src/extension/registry.ts
61017
61110
  var import_promises10 = __toESM(require("fs/promises"), 1);
61018
- var import_node_path59 = __toESM(require("path"), 1);
61111
+ var import_node_path60 = __toESM(require("path"), 1);
61019
61112
  async function loadAll(root) {
61020
61113
  let entries;
61021
61114
  try {
@@ -61028,13 +61121,13 @@ async function loadAll(root) {
61028
61121
  for (const ent of entries) {
61029
61122
  if (!ent.isDirectory()) continue;
61030
61123
  if (ent.name.startsWith(".")) continue;
61031
- records.push(await loadOne(import_node_path59.default.join(root, ent.name), ent.name));
61124
+ records.push(await loadOne(import_node_path60.default.join(root, ent.name), ent.name));
61032
61125
  }
61033
61126
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
61034
61127
  return records;
61035
61128
  }
61036
61129
  async function loadOne(dir, dirName) {
61037
- const manifestPath = import_node_path59.default.join(dir, "manifest.json");
61130
+ const manifestPath = import_node_path60.default.join(dir, "manifest.json");
61038
61131
  let raw;
61039
61132
  try {
61040
61133
  raw = await import_promises10.default.readFile(manifestPath, "utf8");
@@ -61079,7 +61172,7 @@ async function loadOne(dir, dirName) {
61079
61172
 
61080
61173
  // src/extension/uninstall.ts
61081
61174
  var import_promises11 = __toESM(require("fs/promises"), 1);
61082
- var import_node_path60 = __toESM(require("path"), 1);
61175
+ var import_node_path61 = __toESM(require("path"), 1);
61083
61176
  var UninstallError = class extends Error {
61084
61177
  constructor(code, message) {
61085
61178
  super(message);
@@ -61088,7 +61181,7 @@ var UninstallError = class extends Error {
61088
61181
  code;
61089
61182
  };
61090
61183
  async function uninstall(deps) {
61091
- const dir = import_node_path60.default.join(deps.root, deps.extId);
61184
+ const dir = import_node_path61.default.join(deps.root, deps.extId);
61092
61185
  try {
61093
61186
  await import_promises11.default.access(dir);
61094
61187
  } catch {
@@ -61618,7 +61711,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
61618
61711
 
61619
61712
  // src/extension/runtime.ts
61620
61713
  var import_node_child_process16 = require("child_process");
61621
- var import_node_path61 = __toESM(require("path"), 1);
61714
+ var import_node_path62 = __toESM(require("path"), 1);
61622
61715
  var import_promises12 = require("timers/promises");
61623
61716
 
61624
61717
  // src/extension/port-allocator.ts
@@ -61719,7 +61812,7 @@ var Runtime = class {
61719
61812
  /\$CLAWOS_EXT_PORT/g,
61720
61813
  String(port)
61721
61814
  );
61722
- const dir = import_node_path61.default.join(this.root, extId);
61815
+ const dir = import_node_path62.default.join(this.root, extId);
61723
61816
  const env = {
61724
61817
  ...process.env,
61725
61818
  CLAWOS_EXT_PORT: String(port),
@@ -61831,7 +61924,7 @@ ${handle.stderrTail}`
61831
61924
 
61832
61925
  // src/extension/published-channels.ts
61833
61926
  var import_promises13 = __toESM(require("fs/promises"), 1);
61834
- var import_node_path62 = __toESM(require("path"), 1);
61927
+ var import_node_path63 = __toESM(require("path"), 1);
61835
61928
  init_zod();
61836
61929
  var PublishedChannelsError = class extends Error {
61837
61930
  constructor(code, message) {
@@ -61930,7 +62023,7 @@ var PublishedChannelStore = class {
61930
62023
  )
61931
62024
  };
61932
62025
  const tmp = `${this.filePath}.tmp`;
61933
- await import_promises13.default.mkdir(import_node_path62.default.dirname(this.filePath), { recursive: true });
62026
+ await import_promises13.default.mkdir(import_node_path63.default.dirname(this.filePath), { recursive: true });
61934
62027
  await import_promises13.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
61935
62028
  await import_promises13.default.rename(tmp, this.filePath);
61936
62029
  }
@@ -61938,7 +62031,7 @@ var PublishedChannelStore = class {
61938
62031
 
61939
62032
  // src/extension/bundle-cache.ts
61940
62033
  var import_promises14 = __toESM(require("fs/promises"), 1);
61941
- var import_node_path63 = __toESM(require("path"), 1);
62034
+ var import_node_path64 = __toESM(require("path"), 1);
61942
62035
  var BundleCache = class {
61943
62036
  constructor(rootDir) {
61944
62037
  this.rootDir = rootDir;
@@ -61947,14 +62040,14 @@ var BundleCache = class {
61947
62040
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
61948
62041
  async write(snapshotHash, buffer) {
61949
62042
  await import_promises14.default.mkdir(this.rootDir, { recursive: true });
61950
- const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
62043
+ const file = import_node_path64.default.join(this.rootDir, `${snapshotHash}.zip`);
61951
62044
  const tmp = `${file}.tmp`;
61952
62045
  await import_promises14.default.writeFile(tmp, buffer, { mode: 384 });
61953
62046
  await import_promises14.default.rename(tmp, file);
61954
62047
  }
61955
62048
  /** Returns the bundle bytes, or null when the file doesn't exist. */
61956
62049
  async read(snapshotHash) {
61957
- const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
62050
+ const file = import_node_path64.default.join(this.rootDir, `${snapshotHash}.zip`);
61958
62051
  try {
61959
62052
  return await import_promises14.default.readFile(file);
61960
62053
  } catch (e) {
@@ -61964,7 +62057,7 @@ var BundleCache = class {
61964
62057
  }
61965
62058
  /** Idempotent — missing file is not an error. */
61966
62059
  async delete(snapshotHash) {
61967
- const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
62060
+ const file = import_node_path64.default.join(this.rootDir, `${snapshotHash}.zip`);
61968
62061
  await import_promises14.default.rm(file, { force: true });
61969
62062
  }
61970
62063
  };
@@ -61987,24 +62080,24 @@ async function startDaemon(config) {
61987
62080
  sampling: logShippingCfg.sampling,
61988
62081
  homeDir: import_node_os22.default.homedir()
61989
62082
  });
61990
- const logDir = import_node_path64.default.join(config.dataDir, "log");
61991
- import_node_fs48.default.mkdirSync(logDir, { recursive: true });
62083
+ const logDir = import_node_path65.default.join(config.dataDir, "log");
62084
+ import_node_fs49.default.mkdirSync(logDir, { recursive: true });
61992
62085
  const logger = createLogger({
61993
62086
  level: config.logLevel,
61994
- file: import_node_path64.default.join(logDir, "clawd.log"),
62087
+ file: import_node_path65.default.join(logDir, "clawd.log"),
61995
62088
  logClient
61996
62089
  });
61997
62090
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
61998
62091
  const screenIdleProbeLogger = createFileOnlyLogger({
61999
- file: import_node_path64.default.join(logDir, "screen-idle-probe.log"),
62092
+ file: import_node_path65.default.join(logDir, "screen-idle-probe.log"),
62000
62093
  level: "debug"
62001
62094
  });
62002
62095
  logger.info("screen-idle probe logger enabled", {
62003
- file: import_node_path64.default.join(logDir, "screen-idle-probe.log")
62096
+ file: import_node_path65.default.join(logDir, "screen-idle-probe.log")
62004
62097
  });
62005
62098
  const CAP_TARGETS = [
62006
- import_node_path64.default.join(logDir, "clawd.log"),
62007
- import_node_path64.default.join(logDir, "screen-idle-probe.log")
62099
+ import_node_path65.default.join(logDir, "clawd.log"),
62100
+ import_node_path65.default.join(logDir, "screen-idle-probe.log")
62008
62101
  ];
62009
62102
  const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
62010
62103
  const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
@@ -62100,8 +62193,8 @@ async function startDaemon(config) {
62100
62193
  const agents = new AgentsScanner();
62101
62194
  const history = new ClaudeHistoryReader();
62102
62195
  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");
62196
+ const personaStore = new PersonaStore(import_node_path65.default.join(config.dataDir, "personas"));
62197
+ const usersRoot = import_node_path65.default.join(config.dataDir, "users");
62105
62198
  const defaultsRoot = findDefaultsRoot(logger);
62106
62199
  if (defaultsRoot) {
62107
62200
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -62123,7 +62216,7 @@ async function startDaemon(config) {
62123
62216
  retirePersonaBuilder({ store: personaStore, logger });
62124
62217
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
62125
62218
  const dispatchStore = createDispatchStore({
62126
- filePath: import_node_path64.default.join(config.dataDir, "dispatch.json"),
62219
+ filePath: import_node_path65.default.join(config.dataDir, "dispatch.json"),
62127
62220
  now: () => Date.now(),
62128
62221
  onFlushError: (err) => logger.error("dispatch store flush failed", {
62129
62222
  reason: err instanceof Error ? err.message : String(err)
@@ -62138,18 +62231,18 @@ async function startDaemon(config) {
62138
62231
  now: () => Date.now(),
62139
62232
  onCompleted: (sid) => deliverPendingRef?.(sid)
62140
62233
  });
62141
- const here = typeof __dirname === "string" ? __dirname : import_node_path64.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
62234
+ const here = typeof __dirname === "string" ? __dirname : import_node_path65.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
62142
62235
  const mcpConfigs = [];
62143
62236
  const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
62144
62237
  const dispatchServerCandidates = [
62145
- import_node_path64.default.join(here, "dispatch", "mcp-server.cjs"),
62238
+ import_node_path65.default.join(here, "dispatch", "mcp-server.cjs"),
62146
62239
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
62147
- import_node_path64.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
62240
+ import_node_path65.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
62148
62241
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
62149
62242
  ];
62150
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62243
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62151
62244
  if (dispatchServerScriptPath) {
62152
- const dispatchLogPath = import_node_path64.default.join(logDir, "dispatch-mcp-server.log");
62245
+ const dispatchLogPath = import_node_path65.default.join(logDir, "dispatch-mcp-server.log");
62153
62246
  const dispatchCfgPath = writeDispatchMcpConfig({
62154
62247
  dataDir: config.dataDir,
62155
62248
  serverScriptPath: dispatchServerScriptPath,
@@ -62169,12 +62262,12 @@ async function startDaemon(config) {
62169
62262
  });
62170
62263
  }
62171
62264
  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")
62265
+ import_node_path65.default.join(here, "ticket", "mcp-server.cjs"),
62266
+ import_node_path65.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
62174
62267
  ];
62175
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62268
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62176
62269
  if (ticketServerScriptPath) {
62177
- const ticketLogPath = import_node_path64.default.join(logDir, "ticket-mcp-server.log");
62270
+ const ticketLogPath = import_node_path65.default.join(logDir, "ticket-mcp-server.log");
62178
62271
  const ticketCfgPath = writeTicketMcpConfig({
62179
62272
  dataDir: config.dataDir,
62180
62273
  serverScriptPath: ticketServerScriptPath,
@@ -62196,12 +62289,12 @@ async function startDaemon(config) {
62196
62289
  });
62197
62290
  }
62198
62291
  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")
62292
+ import_node_path65.default.join(here, "shift", "mcp-server.cjs"),
62293
+ import_node_path65.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
62201
62294
  ];
62202
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62295
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62203
62296
  if (shiftServerScriptPath) {
62204
- const shiftLogPath = import_node_path64.default.join(logDir, "shift-mcp-server.log");
62297
+ const shiftLogPath = import_node_path65.default.join(logDir, "shift-mcp-server.log");
62205
62298
  const shiftCfgPath = await writeShiftMcpConfig({
62206
62299
  dataDir: config.dataDir,
62207
62300
  serverScriptPath: shiftServerScriptPath,
@@ -62222,12 +62315,12 @@ async function startDaemon(config) {
62222
62315
  );
62223
62316
  }
62224
62317
  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")
62318
+ import_node_path65.default.join(here, "inbox", "mcp-server.cjs"),
62319
+ import_node_path65.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
62227
62320
  ];
62228
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62321
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62229
62322
  if (inboxServerScriptPath) {
62230
- const inboxLogPath = import_node_path64.default.join(logDir, "inbox-mcp-server.log");
62323
+ const inboxLogPath = import_node_path65.default.join(logDir, "inbox-mcp-server.log");
62231
62324
  const inboxCfgPath = await writeInboxMcpConfig({
62232
62325
  dataDir: config.dataDir,
62233
62326
  serverScriptPath: inboxServerScriptPath,
@@ -62248,10 +62341,10 @@ async function startDaemon(config) {
62248
62341
  );
62249
62342
  }
62250
62343
  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")
62344
+ import_node_path65.default.join(here, "peer-ops", "mcp-server.cjs"),
62345
+ import_node_path65.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
62253
62346
  ];
62254
- const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62347
+ const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62255
62348
  if (peerOpsServerScriptPath) {
62256
62349
  const peerOpsCfgPath = writePeerOpsMcpConfig({
62257
62350
  dataDir: config.dataDir,
@@ -62271,12 +62364,12 @@ async function startDaemon(config) {
62271
62364
  );
62272
62365
  }
62273
62366
  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")
62367
+ import_node_path65.default.join(here, "rpc-tool", "mcp-server.cjs"),
62368
+ import_node_path65.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
62276
62369
  ];
62277
- const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs48.default.existsSync(p2));
62370
+ const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
62278
62371
  if (rpcToolServerScriptPath) {
62279
- const rpcToolLogPath = import_node_path64.default.join(logDir, "rpc-tool-mcp-server.log");
62372
+ const rpcToolLogPath = import_node_path65.default.join(logDir, "rpc-tool-mcp-server.log");
62280
62373
  const rpcToolCfgPath = writeRpcToolMcpConfig({
62281
62374
  dataDir: config.dataDir,
62282
62375
  serverScriptPath: rpcToolServerScriptPath,
@@ -62297,7 +62390,7 @@ async function startDaemon(config) {
62297
62390
  );
62298
62391
  }
62299
62392
  const shiftStore = createShiftStore({
62300
- filePath: import_node_path64.default.join(config.dataDir, "shift.json"),
62393
+ filePath: import_node_path65.default.join(config.dataDir, "shift.json"),
62301
62394
  ownerIdProvider: () => ownerPrincipalId,
62302
62395
  now: () => Date.now()
62303
62396
  });
@@ -62319,7 +62412,7 @@ async function startDaemon(config) {
62319
62412
  getAdapter,
62320
62413
  historyReader: history,
62321
62414
  dataDir: config.dataDir,
62322
- personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
62415
+ personaRoot: import_node_path65.default.join(config.dataDir, "personas"),
62323
62416
  // dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
62324
62417
  // personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
62325
62418
  getPersonaTool: (personaId2) => personaRegistry.get(personaId2)?.tool,
@@ -62370,10 +62463,10 @@ async function startDaemon(config) {
62370
62463
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
62371
62464
  attachmentGroup: {
62372
62465
  onFileEdit: (input) => {
62373
- const absPath = import_node_path64.default.isAbsolute(input.relPath) ? input.relPath : import_node_path64.default.join(input.cwd, input.relPath);
62466
+ const absPath = import_node_path65.default.isAbsolute(input.relPath) ? input.relPath : import_node_path65.default.join(input.cwd, input.relPath);
62374
62467
  let size = 0;
62375
62468
  try {
62376
- size = import_node_fs48.default.statSync(absPath).size;
62469
+ size = import_node_fs49.default.statSync(absPath).size;
62377
62470
  } catch (err) {
62378
62471
  logger.warn("attachment.onFileEdit stat failed", {
62379
62472
  sessionId: input.sessionId,
@@ -62620,11 +62713,11 @@ async function startDaemon(config) {
62620
62713
  // 'persona/<pid>/owner',default 走 'default'。
62621
62714
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
62622
62715
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
62623
- personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
62716
+ personaRoot: import_node_path65.default.join(config.dataDir, "personas"),
62624
62717
  usersRoot
62625
62718
  },
62626
62719
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
62627
- personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
62720
+ personaRoot: import_node_path65.default.join(config.dataDir, "personas"),
62628
62721
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
62629
62722
  usersRoot,
62630
62723
  // v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
@@ -62750,11 +62843,11 @@ async function startDaemon(config) {
62750
62843
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
62751
62844
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
62752
62845
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
62753
- appBuilderPersonaRoot: import_node_path64.default.join(config.dataDir, "personas", "persona-app-builder"),
62846
+ appBuilderPersonaRoot: import_node_path65.default.join(config.dataDir, "personas", "persona-app-builder"),
62754
62847
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
62755
- deployKitRoot: import_node_path64.default.join(config.dataDir, "deploy-kit"),
62848
+ deployKitRoot: import_node_path65.default.join(config.dataDir, "deploy-kit"),
62756
62849
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
62757
- resolvePersonaRoot: (personaId2) => import_node_path64.default.join(config.dataDir, "personas", personaId2),
62850
+ resolvePersonaRoot: (personaId2) => import_node_path65.default.join(config.dataDir, "personas", personaId2),
62758
62851
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
62759
62852
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
62760
62853
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -62857,7 +62950,7 @@ async function startDaemon(config) {
62857
62950
  });
62858
62951
  shiftScheduler.start();
62859
62952
  logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
62860
- const larkBotStore = createLarkBotBindingStore(import_node_path64.default.join(config.dataDir, "personas"));
62953
+ const larkBotStore = createLarkBotBindingStore(import_node_path65.default.join(config.dataDir, "personas"));
62861
62954
  const larkBotCloud = createLarkBotCloudClient({
62862
62955
  api: config.clawosApi ?? DEFAULT_CLAWOS_API,
62863
62956
  apiKey: resolveClawdTicketsApiKey(),
@@ -62868,6 +62961,9 @@ async function startDaemon(config) {
62868
62961
  manager,
62869
62962
  cloud: larkBotCloud,
62870
62963
  store: larkBotStore,
62964
+ fetchResource: (appId, messageId, fileKey, maxBytes) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes),
62965
+ // 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
62966
+ mediaRootFor: (chatId) => import_node_path65.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
62871
62967
  logger: {
62872
62968
  warn: (msg) => logger.warn(msg),
62873
62969
  info: (msg) => logger.info(msg)
@@ -63150,8 +63246,8 @@ async function startDaemon(config) {
63150
63246
  const lines = [
63151
63247
  `Tunnel: ${r.url}`,
63152
63248
  ...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")}`
63249
+ `Frpc config: ${import_node_path65.default.join(config.dataDir, "frpc.toml")}`,
63250
+ `Frpc log: ${import_node_path65.default.join(logDir, "frpc.log")}`
63155
63251
  ];
63156
63252
  const width = Math.max(...lines.map((l) => l.length));
63157
63253
  const bar = "\u2550".repeat(width + 4);
@@ -63164,8 +63260,8 @@ ${bar}
63164
63260
 
63165
63261
  `);
63166
63262
  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 });
63263
+ const connectPath = import_node_path65.default.join(config.dataDir, "connect.txt");
63264
+ import_node_fs49.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
63169
63265
  } catch {
63170
63266
  }
63171
63267
  } catch (err) {
@@ -63239,9 +63335,9 @@ ${bar}
63239
63335
  };
63240
63336
  }
63241
63337
  function migrateDropPersonsDir(dataDir) {
63242
- const dir = import_node_path64.default.join(dataDir, "persons");
63338
+ const dir = import_node_path65.default.join(dataDir, "persons");
63243
63339
  try {
63244
- import_node_fs48.default.rmSync(dir, { recursive: true, force: true });
63340
+ import_node_fs49.default.rmSync(dir, { recursive: true, force: true });
63245
63341
  } catch {
63246
63342
  }
63247
63343
  }