@clawos-dev/clawd 0.2.156 → 0.2.157-beta.329.b324109

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
@@ -720,8 +720,8 @@ var init_parseUtil = __esm({
720
720
  init_errors2();
721
721
  init_en();
722
722
  makeIssue = (params) => {
723
- const { data, path: path60, errorMaps, issueData } = params;
724
- const fullPath = [...path60, ...issueData.path || []];
723
+ const { data, path: path61, errorMaps, issueData } = params;
724
+ const fullPath = [...path61, ...issueData.path || []];
725
725
  const fullIssue = {
726
726
  ...issueData,
727
727
  path: fullPath
@@ -1032,11 +1032,11 @@ var init_types = __esm({
1032
1032
  init_parseUtil();
1033
1033
  init_util();
1034
1034
  ParseInputLazyPath = class {
1035
- constructor(parent, value, path60, key) {
1035
+ constructor(parent, value, path61, key) {
1036
1036
  this._cachedPath = [];
1037
1037
  this.parent = parent;
1038
1038
  this.data = value;
1039
- this._path = path60;
1039
+ this._path = path61;
1040
1040
  this._key = key;
1041
1041
  }
1042
1042
  get path() {
@@ -6298,8 +6298,8 @@ var require_req = __commonJS({
6298
6298
  if (req.originalUrl) {
6299
6299
  _req.url = req.originalUrl;
6300
6300
  } else {
6301
- const path60 = req.path;
6302
- _req.url = typeof path60 === "string" ? path60 : req.url ? req.url.path || req.url : void 0;
6301
+ const path61 = req.path;
6302
+ _req.url = typeof path61 === "string" ? path61 : req.url ? req.url.path || req.url : void 0;
6303
6303
  }
6304
6304
  if (req.query) {
6305
6305
  _req.query = req.query;
@@ -6464,14 +6464,14 @@ var require_redact = __commonJS({
6464
6464
  }
6465
6465
  return obj;
6466
6466
  }
6467
- function parsePath(path60) {
6467
+ function parsePath(path61) {
6468
6468
  const parts = [];
6469
6469
  let current = "";
6470
6470
  let inBrackets = false;
6471
6471
  let inQuotes = false;
6472
6472
  let quoteChar = "";
6473
- for (let i = 0; i < path60.length; i++) {
6474
- const char = path60[i];
6473
+ for (let i = 0; i < path61.length; i++) {
6474
+ const char = path61[i];
6475
6475
  if (!inBrackets && char === ".") {
6476
6476
  if (current) {
6477
6477
  parts.push(current);
@@ -6602,10 +6602,10 @@ var require_redact = __commonJS({
6602
6602
  return current;
6603
6603
  }
6604
6604
  function redactPaths(obj, paths, censor, remove = false) {
6605
- for (const path60 of paths) {
6606
- const parts = parsePath(path60);
6605
+ for (const path61 of paths) {
6606
+ const parts = parsePath(path61);
6607
6607
  if (parts.includes("*")) {
6608
- redactWildcardPath(obj, parts, censor, path60, remove);
6608
+ redactWildcardPath(obj, parts, censor, path61, remove);
6609
6609
  } else {
6610
6610
  if (remove) {
6611
6611
  removeKey(obj, parts);
@@ -6690,8 +6690,8 @@ var require_redact = __commonJS({
6690
6690
  }
6691
6691
  } else {
6692
6692
  if (afterWildcard.includes("*")) {
6693
- const wrappedCensor = typeof censor === "function" ? (value, path60) => {
6694
- const fullPath = [...pathArray.slice(0, pathLength), ...path60];
6693
+ const wrappedCensor = typeof censor === "function" ? (value, path61) => {
6694
+ const fullPath = [...pathArray.slice(0, pathLength), ...path61];
6695
6695
  return censor(value, fullPath);
6696
6696
  } : censor;
6697
6697
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -6726,8 +6726,8 @@ var require_redact = __commonJS({
6726
6726
  return null;
6727
6727
  }
6728
6728
  const pathStructure = /* @__PURE__ */ new Map();
6729
- for (const path60 of pathsToClone) {
6730
- const parts = parsePath(path60);
6729
+ for (const path61 of pathsToClone) {
6730
+ const parts = parsePath(path61);
6731
6731
  let current = pathStructure;
6732
6732
  for (let i = 0; i < parts.length; i++) {
6733
6733
  const part = parts[i];
@@ -6779,24 +6779,24 @@ var require_redact = __commonJS({
6779
6779
  }
6780
6780
  return cloneSelectively(obj, pathStructure);
6781
6781
  }
6782
- function validatePath(path60) {
6783
- if (typeof path60 !== "string") {
6782
+ function validatePath(path61) {
6783
+ if (typeof path61 !== "string") {
6784
6784
  throw new Error("Paths must be (non-empty) strings");
6785
6785
  }
6786
- if (path60 === "") {
6786
+ if (path61 === "") {
6787
6787
  throw new Error("Invalid redaction path ()");
6788
6788
  }
6789
- if (path60.includes("..")) {
6790
- throw new Error(`Invalid redaction path (${path60})`);
6789
+ if (path61.includes("..")) {
6790
+ throw new Error(`Invalid redaction path (${path61})`);
6791
6791
  }
6792
- if (path60.includes(",")) {
6793
- throw new Error(`Invalid redaction path (${path60})`);
6792
+ if (path61.includes(",")) {
6793
+ throw new Error(`Invalid redaction path (${path61})`);
6794
6794
  }
6795
6795
  let bracketCount = 0;
6796
6796
  let inQuotes = false;
6797
6797
  let quoteChar = "";
6798
- for (let i = 0; i < path60.length; i++) {
6799
- const char = path60[i];
6798
+ for (let i = 0; i < path61.length; i++) {
6799
+ const char = path61[i];
6800
6800
  if ((char === '"' || char === "'") && bracketCount > 0) {
6801
6801
  if (!inQuotes) {
6802
6802
  inQuotes = true;
@@ -6810,20 +6810,20 @@ var require_redact = __commonJS({
6810
6810
  } else if (char === "]" && !inQuotes) {
6811
6811
  bracketCount--;
6812
6812
  if (bracketCount < 0) {
6813
- throw new Error(`Invalid redaction path (${path60})`);
6813
+ throw new Error(`Invalid redaction path (${path61})`);
6814
6814
  }
6815
6815
  }
6816
6816
  }
6817
6817
  if (bracketCount !== 0) {
6818
- throw new Error(`Invalid redaction path (${path60})`);
6818
+ throw new Error(`Invalid redaction path (${path61})`);
6819
6819
  }
6820
6820
  }
6821
6821
  function validatePaths(paths) {
6822
6822
  if (!Array.isArray(paths)) {
6823
6823
  throw new TypeError("paths must be an array");
6824
6824
  }
6825
- for (const path60 of paths) {
6826
- validatePath(path60);
6825
+ for (const path61 of paths) {
6826
+ validatePath(path61);
6827
6827
  }
6828
6828
  }
6829
6829
  function slowRedact(options = {}) {
@@ -6991,8 +6991,8 @@ var require_redaction = __commonJS({
6991
6991
  if (shape[k2] === null) {
6992
6992
  o[k2] = (value) => topCensor(value, [k2]);
6993
6993
  } else {
6994
- const wrappedCensor = typeof censor === "function" ? (value, path60) => {
6995
- return censor(value, [k2, ...path60]);
6994
+ const wrappedCensor = typeof censor === "function" ? (value, path61) => {
6995
+ return censor(value, [k2, ...path61]);
6996
6996
  } : censor;
6997
6997
  o[k2] = Redact({
6998
6998
  paths: shape[k2],
@@ -7210,10 +7210,10 @@ var require_atomic_sleep = __commonJS({
7210
7210
  var require_sonic_boom = __commonJS({
7211
7211
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
7212
7212
  "use strict";
7213
- var fs54 = require("fs");
7213
+ var fs55 = require("fs");
7214
7214
  var EventEmitter3 = require("events");
7215
7215
  var inherits = require("util").inherits;
7216
- var path60 = require("path");
7216
+ var path61 = require("path");
7217
7217
  var sleep2 = require_atomic_sleep();
7218
7218
  var assert = require("assert");
7219
7219
  var BUSY_WRITE_TIMEOUT = 100;
@@ -7267,20 +7267,20 @@ var require_sonic_boom = __commonJS({
7267
7267
  const mode = sonic.mode;
7268
7268
  if (sonic.sync) {
7269
7269
  try {
7270
- if (sonic.mkdir) fs54.mkdirSync(path60.dirname(file), { recursive: true });
7271
- const fd = fs54.openSync(file, flags, mode);
7270
+ if (sonic.mkdir) fs55.mkdirSync(path61.dirname(file), { recursive: true });
7271
+ const fd = fs55.openSync(file, flags, mode);
7272
7272
  fileOpened(null, fd);
7273
7273
  } catch (err) {
7274
7274
  fileOpened(err);
7275
7275
  throw err;
7276
7276
  }
7277
7277
  } else if (sonic.mkdir) {
7278
- fs54.mkdir(path60.dirname(file), { recursive: true }, (err) => {
7278
+ fs55.mkdir(path61.dirname(file), { recursive: true }, (err) => {
7279
7279
  if (err) return fileOpened(err);
7280
- fs54.open(file, flags, mode, fileOpened);
7280
+ fs55.open(file, flags, mode, fileOpened);
7281
7281
  });
7282
7282
  } else {
7283
- fs54.open(file, flags, mode, fileOpened);
7283
+ fs55.open(file, flags, mode, fileOpened);
7284
7284
  }
7285
7285
  }
7286
7286
  function SonicBoom(opts) {
@@ -7321,8 +7321,8 @@ var require_sonic_boom = __commonJS({
7321
7321
  this.flush = flushBuffer;
7322
7322
  this.flushSync = flushBufferSync;
7323
7323
  this._actualWrite = actualWriteBuffer;
7324
- fsWriteSync = () => fs54.writeSync(this.fd, this._writingBuf);
7325
- fsWrite = () => fs54.write(this.fd, this._writingBuf, this.release);
7324
+ fsWriteSync = () => fs55.writeSync(this.fd, this._writingBuf);
7325
+ fsWrite = () => fs55.write(this.fd, this._writingBuf, this.release);
7326
7326
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
7327
7327
  this._writingBuf = "";
7328
7328
  this.write = write;
@@ -7331,15 +7331,15 @@ var require_sonic_boom = __commonJS({
7331
7331
  this._actualWrite = actualWrite;
7332
7332
  fsWriteSync = () => {
7333
7333
  if (Buffer.isBuffer(this._writingBuf)) {
7334
- return fs54.writeSync(this.fd, this._writingBuf);
7334
+ return fs55.writeSync(this.fd, this._writingBuf);
7335
7335
  }
7336
- return fs54.writeSync(this.fd, this._writingBuf, "utf8");
7336
+ return fs55.writeSync(this.fd, this._writingBuf, "utf8");
7337
7337
  };
7338
7338
  fsWrite = () => {
7339
7339
  if (Buffer.isBuffer(this._writingBuf)) {
7340
- return fs54.write(this.fd, this._writingBuf, this.release);
7340
+ return fs55.write(this.fd, this._writingBuf, this.release);
7341
7341
  }
7342
- return fs54.write(this.fd, this._writingBuf, "utf8", this.release);
7342
+ return fs55.write(this.fd, this._writingBuf, "utf8", this.release);
7343
7343
  };
7344
7344
  } else {
7345
7345
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -7396,7 +7396,7 @@ var require_sonic_boom = __commonJS({
7396
7396
  }
7397
7397
  }
7398
7398
  if (this._fsync) {
7399
- fs54.fsyncSync(this.fd);
7399
+ fs55.fsyncSync(this.fd);
7400
7400
  }
7401
7401
  const len = this._len;
7402
7402
  if (this._reopening) {
@@ -7510,7 +7510,7 @@ var require_sonic_boom = __commonJS({
7510
7510
  const onDrain = () => {
7511
7511
  if (!this._fsync) {
7512
7512
  try {
7513
- fs54.fsync(this.fd, (err) => {
7513
+ fs55.fsync(this.fd, (err) => {
7514
7514
  this._flushPending = false;
7515
7515
  cb(err);
7516
7516
  });
@@ -7612,7 +7612,7 @@ var require_sonic_boom = __commonJS({
7612
7612
  const fd = this.fd;
7613
7613
  this.once("ready", () => {
7614
7614
  if (fd !== this.fd) {
7615
- fs54.close(fd, (err) => {
7615
+ fs55.close(fd, (err) => {
7616
7616
  if (err) {
7617
7617
  return this.emit("error", err);
7618
7618
  }
@@ -7661,7 +7661,7 @@ var require_sonic_boom = __commonJS({
7661
7661
  buf = this._bufs[0];
7662
7662
  }
7663
7663
  try {
7664
- const n = Buffer.isBuffer(buf) ? fs54.writeSync(this.fd, buf) : fs54.writeSync(this.fd, buf, "utf8");
7664
+ const n = Buffer.isBuffer(buf) ? fs55.writeSync(this.fd, buf) : fs55.writeSync(this.fd, buf, "utf8");
7665
7665
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
7666
7666
  buf = releasedBufObj.writingBuf;
7667
7667
  this._len = releasedBufObj.len;
@@ -7677,7 +7677,7 @@ var require_sonic_boom = __commonJS({
7677
7677
  }
7678
7678
  }
7679
7679
  try {
7680
- fs54.fsyncSync(this.fd);
7680
+ fs55.fsyncSync(this.fd);
7681
7681
  } catch {
7682
7682
  }
7683
7683
  }
@@ -7698,7 +7698,7 @@ var require_sonic_boom = __commonJS({
7698
7698
  buf = mergeBuf(this._bufs[0], this._lens[0]);
7699
7699
  }
7700
7700
  try {
7701
- const n = fs54.writeSync(this.fd, buf);
7701
+ const n = fs55.writeSync(this.fd, buf);
7702
7702
  buf = buf.subarray(n);
7703
7703
  this._len = Math.max(this._len - n, 0);
7704
7704
  if (buf.length <= 0) {
@@ -7726,13 +7726,13 @@ var require_sonic_boom = __commonJS({
7726
7726
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
7727
7727
  if (this.sync) {
7728
7728
  try {
7729
- const written = Buffer.isBuffer(this._writingBuf) ? fs54.writeSync(this.fd, this._writingBuf) : fs54.writeSync(this.fd, this._writingBuf, "utf8");
7729
+ const written = Buffer.isBuffer(this._writingBuf) ? fs55.writeSync(this.fd, this._writingBuf) : fs55.writeSync(this.fd, this._writingBuf, "utf8");
7730
7730
  release(null, written);
7731
7731
  } catch (err) {
7732
7732
  release(err);
7733
7733
  }
7734
7734
  } else {
7735
- fs54.write(this.fd, this._writingBuf, release);
7735
+ fs55.write(this.fd, this._writingBuf, release);
7736
7736
  }
7737
7737
  }
7738
7738
  function actualWriteBuffer() {
@@ -7741,7 +7741,7 @@ var require_sonic_boom = __commonJS({
7741
7741
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
7742
7742
  if (this.sync) {
7743
7743
  try {
7744
- const written = fs54.writeSync(this.fd, this._writingBuf);
7744
+ const written = fs55.writeSync(this.fd, this._writingBuf);
7745
7745
  release(null, written);
7746
7746
  } catch (err) {
7747
7747
  release(err);
@@ -7750,7 +7750,7 @@ var require_sonic_boom = __commonJS({
7750
7750
  if (kCopyBuffer) {
7751
7751
  this._writingBuf = Buffer.from(this._writingBuf);
7752
7752
  }
7753
- fs54.write(this.fd, this._writingBuf, release);
7753
+ fs55.write(this.fd, this._writingBuf, release);
7754
7754
  }
7755
7755
  }
7756
7756
  function actualClose(sonic) {
@@ -7766,12 +7766,12 @@ var require_sonic_boom = __commonJS({
7766
7766
  sonic._lens = [];
7767
7767
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
7768
7768
  try {
7769
- fs54.fsync(sonic.fd, closeWrapped);
7769
+ fs55.fsync(sonic.fd, closeWrapped);
7770
7770
  } catch {
7771
7771
  }
7772
7772
  function closeWrapped() {
7773
7773
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7774
- fs54.close(sonic.fd, done);
7774
+ fs55.close(sonic.fd, done);
7775
7775
  } else {
7776
7776
  done();
7777
7777
  }
@@ -10906,11 +10906,11 @@ var init_lib = __esm({
10906
10906
  }
10907
10907
  }
10908
10908
  },
10909
- addToPath: function addToPath(path60, added, removed, oldPosInc, options) {
10910
- var last = path60.lastComponent;
10909
+ addToPath: function addToPath(path61, added, removed, oldPosInc, options) {
10910
+ var last = path61.lastComponent;
10911
10911
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
10912
10912
  return {
10913
- oldPos: path60.oldPos + oldPosInc,
10913
+ oldPos: path61.oldPos + oldPosInc,
10914
10914
  lastComponent: {
10915
10915
  count: last.count + 1,
10916
10916
  added,
@@ -10920,7 +10920,7 @@ var init_lib = __esm({
10920
10920
  };
10921
10921
  } else {
10922
10922
  return {
10923
- oldPos: path60.oldPos + oldPosInc,
10923
+ oldPos: path61.oldPos + oldPosInc,
10924
10924
  lastComponent: {
10925
10925
  count: 1,
10926
10926
  added,
@@ -11366,10 +11366,10 @@ function attachmentToHistoryMessage(o, ts) {
11366
11366
  const memories = raw.map((m2) => {
11367
11367
  if (!m2 || typeof m2 !== "object") return null;
11368
11368
  const rec3 = m2;
11369
- const path60 = typeof rec3.path === "string" ? rec3.path : null;
11369
+ const path61 = typeof rec3.path === "string" ? rec3.path : null;
11370
11370
  const content = typeof rec3.content === "string" ? rec3.content : null;
11371
- if (!path60 || content == null) return null;
11372
- const entry = { path: path60, content };
11371
+ if (!path61 || content == null) return null;
11372
+ const entry = { path: path61, content };
11373
11373
  if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
11374
11374
  return entry;
11375
11375
  }).filter((m2) => m2 !== null);
@@ -11892,6 +11892,9 @@ function buildSpawnArgs(ctx) {
11892
11892
  if (ctx.dispatchMcpConfigPath) {
11893
11893
  args.push("--mcp-config", ctx.dispatchMcpConfigPath);
11894
11894
  }
11895
+ if (ctx.ticketMcpConfigPath) {
11896
+ args.push("--mcp-config", ctx.ticketMcpConfigPath);
11897
+ }
11895
11898
  if (ctx.effort) args.push("--effort", ctx.effort);
11896
11899
  if (ctx.toolSessionId) args.push("--resume", ctx.toolSessionId);
11897
11900
  return args;
@@ -12171,10 +12174,10 @@ function parseAttachment(obj) {
12171
12174
  const memories = raw.map((m2) => {
12172
12175
  if (!m2 || typeof m2 !== "object") return null;
12173
12176
  const rec3 = m2;
12174
- const path60 = typeof rec3.path === "string" ? rec3.path : null;
12177
+ const path61 = typeof rec3.path === "string" ? rec3.path : null;
12175
12178
  const content = typeof rec3.content === "string" ? rec3.content : null;
12176
- if (!path60 || content == null) return null;
12177
- const out = { path: path60, content };
12179
+ if (!path61 || content == null) return null;
12180
+ const out = { path: path61, content };
12178
12181
  if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
12179
12182
  return out;
12180
12183
  }).filter((m2) => m2 !== null);
@@ -23961,8 +23964,8 @@ var require_utils = __commonJS({
23961
23964
  var result = transform[inputType][outputType](input);
23962
23965
  return result;
23963
23966
  };
23964
- exports2.resolve = function(path60) {
23965
- var parts = path60.split("/");
23967
+ exports2.resolve = function(path61) {
23968
+ var parts = path61.split("/");
23966
23969
  var result = [];
23967
23970
  for (var index = 0; index < parts.length; index++) {
23968
23971
  var part = parts[index];
@@ -29815,18 +29818,18 @@ var require_object = __commonJS({
29815
29818
  var object = new ZipObject(name, zipObjectContent, o);
29816
29819
  this.files[name] = object;
29817
29820
  };
29818
- var parentFolder = function(path60) {
29819
- if (path60.slice(-1) === "/") {
29820
- path60 = path60.substring(0, path60.length - 1);
29821
+ var parentFolder = function(path61) {
29822
+ if (path61.slice(-1) === "/") {
29823
+ path61 = path61.substring(0, path61.length - 1);
29821
29824
  }
29822
- var lastSlash = path60.lastIndexOf("/");
29823
- return lastSlash > 0 ? path60.substring(0, lastSlash) : "";
29825
+ var lastSlash = path61.lastIndexOf("/");
29826
+ return lastSlash > 0 ? path61.substring(0, lastSlash) : "";
29824
29827
  };
29825
- var forceTrailingSlash = function(path60) {
29826
- if (path60.slice(-1) !== "/") {
29827
- path60 += "/";
29828
+ var forceTrailingSlash = function(path61) {
29829
+ if (path61.slice(-1) !== "/") {
29830
+ path61 += "/";
29828
29831
  }
29829
- return path60;
29832
+ return path61;
29830
29833
  };
29831
29834
  var folderAdd = function(name, createFolders) {
29832
29835
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -30828,7 +30831,7 @@ var require_lib3 = __commonJS({
30828
30831
  // src/run-case/recorder.ts
30829
30832
  function startRunCaseRecorder(opts) {
30830
30833
  const now = opts.now ?? Date.now;
30831
- const dir = import_node_path48.default.dirname(opts.recordPath);
30834
+ const dir = import_node_path49.default.dirname(opts.recordPath);
30832
30835
  let stream = null;
30833
30836
  let closing = false;
30834
30837
  let closedSettled = false;
@@ -30842,8 +30845,8 @@ function startRunCaseRecorder(opts) {
30842
30845
  });
30843
30846
  const ensureStream = () => {
30844
30847
  if (stream) return stream;
30845
- import_node_fs37.default.mkdirSync(dir, { recursive: true });
30846
- stream = import_node_fs37.default.createWriteStream(opts.recordPath, { flags: "a" });
30848
+ import_node_fs38.default.mkdirSync(dir, { recursive: true });
30849
+ stream = import_node_fs38.default.createWriteStream(opts.recordPath, { flags: "a" });
30847
30850
  stream.on("close", () => closedResolve());
30848
30851
  return stream;
30849
30852
  };
@@ -30868,12 +30871,12 @@ function startRunCaseRecorder(opts) {
30868
30871
  };
30869
30872
  return { tap, close, closed };
30870
30873
  }
30871
- var import_node_fs37, import_node_path48;
30874
+ var import_node_fs38, import_node_path49;
30872
30875
  var init_recorder = __esm({
30873
30876
  "src/run-case/recorder.ts"() {
30874
30877
  "use strict";
30875
- import_node_fs37 = __toESM(require("fs"), 1);
30876
- import_node_path48 = __toESM(require("path"), 1);
30878
+ import_node_fs38 = __toESM(require("fs"), 1);
30879
+ import_node_path49 = __toESM(require("path"), 1);
30877
30880
  }
30878
30881
  });
30879
30882
 
@@ -30916,7 +30919,7 @@ var init_wire = __esm({
30916
30919
  // src/run-case/controller.ts
30917
30920
  async function runController(opts) {
30918
30921
  const now = opts.now ?? Date.now;
30919
- const cwd = opts.cwd ?? (0, import_node_fs38.mkdtempSync)(import_node_path49.default.join(import_node_os21.default.tmpdir(), "clawd-runcase-"));
30922
+ const cwd = opts.cwd ?? (0, import_node_fs39.mkdtempSync)(import_node_path50.default.join(import_node_os21.default.tmpdir(), "clawd-runcase-"));
30920
30923
  const ownsCwd = opts.cwd === void 0;
30921
30924
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
30922
30925
  const spawnCtx = { cwd };
@@ -31077,19 +31080,19 @@ async function runController(opts) {
31077
31080
  if (sigintHandler) process.off("SIGINT", sigintHandler);
31078
31081
  if (ownsCwd) {
31079
31082
  try {
31080
- (0, import_node_fs38.rmSync)(cwd, { recursive: true, force: true });
31083
+ (0, import_node_fs39.rmSync)(cwd, { recursive: true, force: true });
31081
31084
  } catch {
31082
31085
  }
31083
31086
  }
31084
31087
  return exitCode ?? 0;
31085
31088
  }
31086
- var import_node_fs38, import_node_os21, import_node_path49;
31089
+ var import_node_fs39, import_node_os21, import_node_path50;
31087
31090
  var init_controller = __esm({
31088
31091
  "src/run-case/controller.ts"() {
31089
31092
  "use strict";
31090
- import_node_fs38 = require("fs");
31093
+ import_node_fs39 = require("fs");
31091
31094
  import_node_os21 = __toESM(require("os"), 1);
31092
- import_node_path49 = __toESM(require("path"), 1);
31095
+ import_node_path50 = __toESM(require("path"), 1);
31093
31096
  init_claude();
31094
31097
  init_stdout_splitter();
31095
31098
  init_permission_stdio();
@@ -31351,8 +31354,8 @@ Env (advanced):
31351
31354
  `;
31352
31355
 
31353
31356
  // src/index.ts
31354
- var import_node_path47 = __toESM(require("path"), 1);
31355
- var import_node_fs36 = __toESM(require("fs"), 1);
31357
+ var import_node_path48 = __toESM(require("path"), 1);
31358
+ var import_node_fs37 = __toESM(require("fs"), 1);
31356
31359
  var import_node_os20 = __toESM(require("os"), 1);
31357
31360
 
31358
31361
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
@@ -32218,6 +32221,8 @@ function buildSpawnContext(state, deps) {
32218
32221
  const dispatchId = deps.lookupDispatchByBSessionId?.(file.sessionId);
32219
32222
  if (dispatchId) env.CLAWD_DISPATCH_ID = dispatchId;
32220
32223
  const dispatchMcpConfigPath2 = deps.getDispatchMcpConfigPath?.() ?? null;
32224
+ const ticketMcpConfigPathRaw = deps.getTicketMcpConfigPath?.() ?? null;
32225
+ const ticketMcpConfigPath2 = ticketMcpConfigPathRaw && file.ownerPersonaId === "persona-developer" ? ticketMcpConfigPathRaw : null;
32221
32226
  const ctx = {
32222
32227
  cwd: file.cwd,
32223
32228
  toolSessionId: file.toolSessionId,
@@ -32230,7 +32235,8 @@ function buildSpawnContext(state, deps) {
32230
32235
  personaRoot: deps.personaRoot,
32231
32236
  // Persona dispatch:所有 session(A 和 B)都挂同一份 dispatch.mcp.json,让两边的 cc
32232
32237
  // 都能看到 personaDispatch / personaDispatchComplete tool;按 env 区分实际行为。
32233
- dispatchMcpConfigPath: dispatchMcpConfigPath2 ?? void 0
32238
+ dispatchMcpConfigPath: dispatchMcpConfigPath2 ?? void 0,
32239
+ ticketMcpConfigPath: ticketMcpConfigPath2 ?? void 0
32234
32240
  };
32235
32241
  const meta = state.subSessionMeta;
32236
32242
  if (meta?.personaMode) {
@@ -32996,6 +33002,8 @@ var SessionRunner = class {
32996
33002
  // Persona dispatch:透传 dispatch.mcp.json 路径闭包 + B→dispatchId 反查闭包。
32997
33003
  // 见 reducer.buildSpawnContext 注 CLAWD_DISPATCH_ID env / 派生 SpawnContext.dispatchMcpConfigPath
32998
33004
  getDispatchMcpConfigPath: this.hooks.getDispatchMcpConfigPath,
33005
+ // Ticket MCP:透传 ticket.mcp.json 路径闭包(reducer 内做 persona-developer gating)
33006
+ getTicketMcpConfigPath: this.hooks.getTicketMcpConfigPath,
32999
33007
  lookupDispatchByBSessionId: this.hooks.lookupDispatchByBSessionId,
33000
33008
  // ReadyGate v2:透传 mode 让 reducer send / ready-detected 分支决定走暂存队列还是直写
33001
33009
  mode: this.hooks.mode,
@@ -33791,6 +33799,7 @@ var SessionManager = class {
33791
33799
  // Persona dispatch (Task 7): dispatch.mcp.json 路径 + B sessionId → dispatchId 反查
33792
33800
  // 闭包透传给 reducer,让 cc spawn 加 --mcp-config flag + B session 注 CLAWD_DISPATCH_ID env.
33793
33801
  getDispatchMcpConfigPath: this.deps.dispatchMcpConfigPath ? () => this.deps.dispatchMcpConfigPath ?? null : void 0,
33802
+ getTicketMcpConfigPath: this.deps.ticketMcpConfigPath ? () => this.deps.ticketMcpConfigPath ?? null : void 0,
33794
33803
  lookupDispatchByBSessionId: this.deps.personaDispatchManager ? (bSid) => this.deps.personaDispatchManager?.lookupDispatchByBSessionId(bSid) : void 0,
33795
33804
  // file-sharing (spec §6 PR 3):闭包 scope + sessionId,runner 只暴露 tool/relPath/cwd
33796
33805
  onFileEdit: attachmentGroup ? (input) => attachmentGroup.onFileEdit({
@@ -36328,8 +36337,8 @@ function turnStartInput(text) {
36328
36337
  const items = [];
36329
36338
  let leftover = text;
36330
36339
  for (const m2 of text.matchAll(SKILL_RE)) {
36331
- const [marker, name, path60] = m2;
36332
- items.push({ type: "skill", name, path: path60 });
36340
+ const [marker, name, path61] = m2;
36341
+ items.push({ type: "skill", name, path: path61 });
36333
36342
  leftover = leftover.replace(marker, "");
36334
36343
  }
36335
36344
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -37623,6 +37632,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
37623
37632
  if (ctx.dispatchMcpConfigPath) {
37624
37633
  args.push("--mcp-config", ctx.dispatchMcpConfigPath);
37625
37634
  }
37635
+ if (ctx.ticketMcpConfigPath) {
37636
+ args.push("--mcp-config", ctx.ticketMcpConfigPath);
37637
+ }
37626
37638
  if (ctx.effort) args.push("--effort", ctx.effort);
37627
37639
  return args;
37628
37640
  }
@@ -37723,6 +37735,43 @@ function writeDispatchMcpConfig(args) {
37723
37735
  return cfgPath;
37724
37736
  }
37725
37737
 
37738
+ // src/ticket/mcp-config.ts
37739
+ var import_node_fs15 = __toESM(require("fs"), 1);
37740
+ var import_node_path12 = __toESM(require("path"), 1);
37741
+ function ticketMcpConfigPath(dataDir) {
37742
+ return import_node_path12.default.join(dataDir, "ticket.mcp.json");
37743
+ }
37744
+ function writeTicketMcpConfig(args) {
37745
+ const cfgPath = ticketMcpConfigPath(args.dataDir);
37746
+ const content = {
37747
+ _comment: "daemon \u542F\u52A8\u65F6\u81EA\u52A8\u751F\u6210\uFF1Bcc spawn \u901A\u8FC7 --mcp-config \u6CE8\u5165\u3002ticket-mcp-server.cjs \u662F daemon \u81EA\u5E26\u7684 stdio MCP server\uFF0CHTTP client \u8C03 clawos api /clawd-tickets/*\u3002env \u542B api url\u3001\u5199\u6B7B API key\u3001\u98DE\u4E66 unionId\u3001displayName snapshot\u3002",
37748
+ mcpServers: {
37749
+ "clawd-ticket": {
37750
+ type: "stdio",
37751
+ command: "node",
37752
+ args: [args.serverScriptPath],
37753
+ env: {
37754
+ CLAWD_TICKET_API_URL: args.apiBaseUrl,
37755
+ CLAWD_TICKET_API_KEY: args.apiKey,
37756
+ CLAWD_TICKET_OWNER_UNION_ID: args.ownerUnionId,
37757
+ CLAWD_TICKET_OWNER_NAME: args.ownerName
37758
+ }
37759
+ }
37760
+ }
37761
+ };
37762
+ import_node_fs15.default.mkdirSync(args.dataDir, { recursive: true });
37763
+ import_node_fs15.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
37764
+ return cfgPath;
37765
+ }
37766
+
37767
+ // src/ticket/constants.ts
37768
+ var DEFAULT_CLAWD_TICKETS_API_KEY = "cf057f047674896978ddcc813adbc4a186551a6fcf59ad9d";
37769
+ function resolveClawdTicketsApiKey() {
37770
+ const fromEnv = process.env.CLAWD_TICKETS_API_KEY;
37771
+ if (fromEnv && fromEnv.length > 0) return fromEnv;
37772
+ return DEFAULT_CLAWD_TICKETS_API_KEY;
37773
+ }
37774
+
37726
37775
  // src/handlers/persona-dispatch.ts
37727
37776
  init_protocol();
37728
37777
  function buildPersonaDispatchHandlers(deps) {
@@ -37975,13 +38024,13 @@ function mapSkillsListResponse(res) {
37975
38024
  const r = s ?? {};
37976
38025
  const name = str3(r.name);
37977
38026
  if (!name) continue;
37978
- const path60 = str3(r.path);
38027
+ const path61 = str3(r.path);
37979
38028
  const description = str3(r.description);
37980
38029
  const isPlugin = name.includes(":");
37981
38030
  out.push({
37982
38031
  name,
37983
38032
  source: isPlugin ? "plugin" : "project",
37984
- ...path60 ? { path: path60 } : {},
38033
+ ...path61 ? { path: path61 } : {},
37985
38034
  ...description ? { description } : {},
37986
38035
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
37987
38036
  });
@@ -38020,23 +38069,23 @@ async function listCodexSkills(cwd, deps = {}) {
38020
38069
  }
38021
38070
 
38022
38071
  // src/workspace/browser.ts
38023
- var import_node_fs15 = __toESM(require("fs"), 1);
38072
+ var import_node_fs16 = __toESM(require("fs"), 1);
38024
38073
  var import_node_os7 = __toESM(require("os"), 1);
38025
- var import_node_path12 = __toESM(require("path"), 1);
38074
+ var import_node_path13 = __toESM(require("path"), 1);
38026
38075
  init_protocol();
38027
38076
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
38028
38077
  function resolveInsideCwd(cwd, subpath) {
38029
- const absCwd = import_node_path12.default.resolve(cwd);
38030
- const joined = import_node_path12.default.resolve(absCwd, subpath ?? ".");
38031
- const rel = import_node_path12.default.relative(absCwd, joined);
38032
- if (rel.startsWith("..") || import_node_path12.default.isAbsolute(rel)) {
38078
+ const absCwd = import_node_path13.default.resolve(cwd);
38079
+ const joined = import_node_path13.default.resolve(absCwd, subpath ?? ".");
38080
+ const rel = import_node_path13.default.relative(absCwd, joined);
38081
+ if (rel.startsWith("..") || import_node_path13.default.isAbsolute(rel)) {
38033
38082
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
38034
38083
  }
38035
38084
  return joined;
38036
38085
  }
38037
38086
  function ensureCwd(cwd) {
38038
38087
  try {
38039
- const stat = import_node_fs15.default.statSync(cwd);
38088
+ const stat = import_node_fs16.default.statSync(cwd);
38040
38089
  if (!stat.isDirectory()) {
38041
38090
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
38042
38091
  }
@@ -38050,7 +38099,7 @@ var WorkspaceBrowser = class {
38050
38099
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os7.default.homedir();
38051
38100
  ensureCwd(cwd);
38052
38101
  const full = resolveInsideCwd(cwd, args.path);
38053
- const dirents = import_node_fs15.default.readdirSync(full, { withFileTypes: true });
38102
+ const dirents = import_node_fs16.default.readdirSync(full, { withFileTypes: true });
38054
38103
  const entries = [];
38055
38104
  for (const d of dirents) {
38056
38105
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -38060,7 +38109,7 @@ var WorkspaceBrowser = class {
38060
38109
  mtime: ""
38061
38110
  };
38062
38111
  try {
38063
- const st = import_node_fs15.default.statSync(import_node_path12.default.join(full, d.name));
38112
+ const st = import_node_fs16.default.statSync(import_node_path13.default.join(full, d.name));
38064
38113
  entry.mtime = new Date(st.mtimeMs).toISOString();
38065
38114
  if (d.isFile()) entry.size = st.size;
38066
38115
  } catch {
@@ -38076,14 +38125,14 @@ var WorkspaceBrowser = class {
38076
38125
  read(args) {
38077
38126
  ensureCwd(args.cwd);
38078
38127
  const full = resolveInsideCwd(args.cwd, args.path);
38079
- const st = import_node_fs15.default.statSync(full);
38128
+ const st = import_node_fs16.default.statSync(full);
38080
38129
  if (!st.isFile()) {
38081
38130
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
38082
38131
  }
38083
38132
  if (st.size > MAX_FILE_BYTES) {
38084
38133
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
38085
38134
  }
38086
- const buf = import_node_fs15.default.readFileSync(full);
38135
+ const buf = import_node_fs16.default.readFileSync(full);
38087
38136
  const isBinary = buf.includes(0);
38088
38137
  if (isBinary) {
38089
38138
  return {
@@ -38105,20 +38154,20 @@ var WorkspaceBrowser = class {
38105
38154
  };
38106
38155
 
38107
38156
  // src/skills/agents-scanner.ts
38108
- var import_node_fs16 = __toESM(require("fs"), 1);
38157
+ var import_node_fs17 = __toESM(require("fs"), 1);
38109
38158
  var import_node_os8 = __toESM(require("os"), 1);
38110
- var import_node_path13 = __toESM(require("path"), 1);
38159
+ var import_node_path14 = __toESM(require("path"), 1);
38111
38160
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
38112
38161
  function isDirLikeSync2(p2) {
38113
38162
  try {
38114
- return import_node_fs16.default.statSync(p2).isDirectory();
38163
+ return import_node_fs17.default.statSync(p2).isDirectory();
38115
38164
  } catch {
38116
38165
  return false;
38117
38166
  }
38118
38167
  }
38119
38168
  function fileExistsSync(p2) {
38120
38169
  try {
38121
- return import_node_fs16.default.statSync(p2).isFile();
38170
+ return import_node_fs17.default.statSync(p2).isFile();
38122
38171
  } catch {
38123
38172
  return false;
38124
38173
  }
@@ -38126,7 +38175,7 @@ function fileExistsSync(p2) {
38126
38175
  function parseAgentFile(filePath) {
38127
38176
  let content;
38128
38177
  try {
38129
- content = import_node_fs16.default.readFileSync(filePath, "utf8");
38178
+ content = import_node_fs17.default.readFileSync(filePath, "utf8");
38130
38179
  } catch {
38131
38180
  return {};
38132
38181
  }
@@ -38139,16 +38188,16 @@ function parseAgentFile(filePath) {
38139
38188
  function scanAgentsDir(dir, source, seen, out) {
38140
38189
  let entries;
38141
38190
  try {
38142
- entries = import_node_fs16.default.readdirSync(dir, { withFileTypes: true });
38191
+ entries = import_node_fs17.default.readdirSync(dir, { withFileTypes: true });
38143
38192
  } catch {
38144
38193
  return;
38145
38194
  }
38146
38195
  for (const ent of entries) {
38147
38196
  if (!ent.name.endsWith(".md")) continue;
38148
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path13.default.join(dir, ent.name)))) {
38197
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path14.default.join(dir, ent.name)))) {
38149
38198
  continue;
38150
38199
  }
38151
- const filePath = import_node_path13.default.join(dir, ent.name);
38200
+ const filePath = import_node_path14.default.join(dir, ent.name);
38152
38201
  const baseName = ent.name.replace(/\.md$/, "");
38153
38202
  if (seen.has(baseName)) continue;
38154
38203
  seen.add(baseName);
@@ -38166,12 +38215,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
38166
38215
  function walk2(dir, namespaces) {
38167
38216
  let entries;
38168
38217
  try {
38169
- entries = import_node_fs16.default.readdirSync(dir, { withFileTypes: true });
38218
+ entries = import_node_fs17.default.readdirSync(dir, { withFileTypes: true });
38170
38219
  } catch {
38171
38220
  return;
38172
38221
  }
38173
38222
  for (const ent of entries) {
38174
- const childPath = import_node_path13.default.join(dir, ent.name);
38223
+ const childPath = import_node_path14.default.join(dir, ent.name);
38175
38224
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
38176
38225
  walk2(childPath, [...namespaces, ent.name]);
38177
38226
  continue;
@@ -38196,13 +38245,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
38196
38245
  walk2(root, []);
38197
38246
  }
38198
38247
  function readInstalledPlugins2(home) {
38199
- const pluginsDir = import_node_path13.default.join(home, ".claude", "plugins");
38200
- const v2 = import_node_path13.default.join(pluginsDir, "installed_plugins_v2.json");
38201
- const v1 = import_node_path13.default.join(pluginsDir, "installed_plugins.json");
38248
+ const pluginsDir = import_node_path14.default.join(home, ".claude", "plugins");
38249
+ const v2 = import_node_path14.default.join(pluginsDir, "installed_plugins_v2.json");
38250
+ const v1 = import_node_path14.default.join(pluginsDir, "installed_plugins.json");
38202
38251
  let raw = null;
38203
38252
  for (const candidate of [v2, v1]) {
38204
38253
  try {
38205
- raw = import_node_fs16.default.readFileSync(candidate, "utf8");
38254
+ raw = import_node_fs17.default.readFileSync(candidate, "utf8");
38206
38255
  break;
38207
38256
  } catch {
38208
38257
  }
@@ -38227,19 +38276,19 @@ function readInstalledPlugins2(home) {
38227
38276
  return out;
38228
38277
  }
38229
38278
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
38230
- let cur = import_node_path13.default.resolve(startCwd);
38231
- const fsRoot = import_node_path13.default.parse(cur).root;
38279
+ let cur = import_node_path14.default.resolve(startCwd);
38280
+ const fsRoot = import_node_path14.default.parse(cur).root;
38232
38281
  while (true) {
38233
- scanAgentsDir(import_node_path13.default.join(cur, ".claude", "agents"), "project", seen, out);
38282
+ scanAgentsDir(import_node_path14.default.join(cur, ".claude", "agents"), "project", seen, out);
38234
38283
  let hasGit = false;
38235
38284
  try {
38236
- hasGit = import_node_fs16.default.existsSync(import_node_path13.default.join(cur, ".git"));
38285
+ hasGit = import_node_fs17.default.existsSync(import_node_path14.default.join(cur, ".git"));
38237
38286
  } catch {
38238
38287
  }
38239
38288
  if (hasGit) return;
38240
38289
  if (cur === home) return;
38241
38290
  if (cur === fsRoot) return;
38242
- const parent = import_node_path13.default.dirname(cur);
38291
+ const parent = import_node_path14.default.dirname(cur);
38243
38292
  if (parent === cur) return;
38244
38293
  cur = parent;
38245
38294
  }
@@ -38274,7 +38323,7 @@ var AgentsScanner = class {
38274
38323
  }
38275
38324
  const fsBlock = [];
38276
38325
  scanAgentsDir(
38277
- import_node_path13.default.join(this.home, ".claude", "agents"),
38326
+ import_node_path14.default.join(this.home, ".claude", "agents"),
38278
38327
  "global",
38279
38328
  seen,
38280
38329
  fsBlock
@@ -38288,7 +38337,7 @@ var AgentsScanner = class {
38288
38337
  ...this.extraPluginRoots
38289
38338
  ];
38290
38339
  for (const { name, root } of plugins) {
38291
- const agentsRoot = import_node_path13.default.join(root, "agents");
38340
+ const agentsRoot = import_node_path14.default.join(root, "agents");
38292
38341
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
38293
38342
  }
38294
38343
  return [...builtinBlock, ...fsBlock];
@@ -38296,15 +38345,15 @@ var AgentsScanner = class {
38296
38345
  };
38297
38346
 
38298
38347
  // src/observer/session-observer.ts
38299
- var import_node_fs18 = __toESM(require("fs"), 1);
38348
+ var import_node_fs19 = __toESM(require("fs"), 1);
38300
38349
  var import_node_os10 = __toESM(require("os"), 1);
38301
- var import_node_path15 = __toESM(require("path"), 1);
38350
+ var import_node_path16 = __toESM(require("path"), 1);
38302
38351
  init_claude_history();
38303
38352
 
38304
38353
  // src/observer/subagent-meta-observer.ts
38305
- var import_node_fs17 = __toESM(require("fs"), 1);
38354
+ var import_node_fs18 = __toESM(require("fs"), 1);
38306
38355
  var import_node_os9 = __toESM(require("os"), 1);
38307
- var import_node_path14 = __toESM(require("path"), 1);
38356
+ var import_node_path15 = __toESM(require("path"), 1);
38308
38357
  init_claude_history();
38309
38358
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
38310
38359
  var SubagentMetaObserver = class {
@@ -38317,7 +38366,7 @@ var SubagentMetaObserver = class {
38317
38366
  watches = /* @__PURE__ */ new Map();
38318
38367
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
38319
38368
  resolveSubagentDir(cwd, toolSessionId) {
38320
- return import_node_path14.default.join(
38369
+ return import_node_path15.default.join(
38321
38370
  this.home,
38322
38371
  ".claude",
38323
38372
  "projects",
@@ -38347,7 +38396,7 @@ var SubagentMetaObserver = class {
38347
38396
  attachWatcher(w2) {
38348
38397
  if (w2.watcher) return;
38349
38398
  try {
38350
- w2.watcher = import_node_fs17.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
38399
+ w2.watcher = import_node_fs18.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
38351
38400
  if (!name) return;
38352
38401
  const m2 = META_RE.exec(String(name));
38353
38402
  if (!m2) return;
@@ -38359,7 +38408,7 @@ var SubagentMetaObserver = class {
38359
38408
  scan(w2) {
38360
38409
  let entries;
38361
38410
  try {
38362
- entries = import_node_fs17.default.readdirSync(w2.dirPath);
38411
+ entries = import_node_fs18.default.readdirSync(w2.dirPath);
38363
38412
  } catch {
38364
38413
  return;
38365
38414
  }
@@ -38373,10 +38422,10 @@ var SubagentMetaObserver = class {
38373
38422
  if (!m2) return;
38374
38423
  const agentId = m2[1];
38375
38424
  if (w2.emitted.has(agentId)) return;
38376
- const file = import_node_path14.default.join(w2.dirPath, name);
38425
+ const file = import_node_path15.default.join(w2.dirPath, name);
38377
38426
  let raw;
38378
38427
  try {
38379
- raw = import_node_fs17.default.readFileSync(file, "utf8");
38428
+ raw = import_node_fs18.default.readFileSync(file, "utf8");
38380
38429
  } catch {
38381
38430
  return;
38382
38431
  }
@@ -38433,14 +38482,14 @@ var SessionObserver = class {
38433
38482
  metaObserver;
38434
38483
  resolveJsonlPath(cwd, toolSessionId, override) {
38435
38484
  if (override) return override;
38436
- return import_node_path15.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
38485
+ return import_node_path16.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
38437
38486
  }
38438
38487
  start(args) {
38439
38488
  this.stop(args.sessionId);
38440
38489
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
38441
38490
  let size = 0;
38442
38491
  try {
38443
- size = import_node_fs18.default.statSync(filePath).size;
38492
+ size = import_node_fs19.default.statSync(filePath).size;
38444
38493
  } catch {
38445
38494
  }
38446
38495
  const w2 = {
@@ -38454,10 +38503,10 @@ var SessionObserver = class {
38454
38503
  prevIsRejectSentinel: false
38455
38504
  };
38456
38505
  try {
38457
- import_node_fs18.default.mkdirSync(import_node_path15.default.dirname(filePath), { recursive: true });
38506
+ import_node_fs19.default.mkdirSync(import_node_path16.default.dirname(filePath), { recursive: true });
38458
38507
  } catch {
38459
38508
  }
38460
- w2.watcher = import_node_fs18.default.watch(import_node_path15.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
38509
+ w2.watcher = import_node_fs19.default.watch(import_node_path16.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
38461
38510
  if (!changedName || !filePath.endsWith(changedName)) return;
38462
38511
  this.poll(w2);
38463
38512
  });
@@ -38480,7 +38529,7 @@ var SessionObserver = class {
38480
38529
  // 异常静默吞,不阻塞 watcher 启动
38481
38530
  hydrateMetaTail(w2, maxLines = 200) {
38482
38531
  try {
38483
- const raw = import_node_fs18.default.readFileSync(w2.filePath, "utf8");
38532
+ const raw = import_node_fs19.default.readFileSync(w2.filePath, "utf8");
38484
38533
  if (!raw) return;
38485
38534
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
38486
38535
  if (allLines.length === 0) return;
@@ -38504,7 +38553,7 @@ var SessionObserver = class {
38504
38553
  poll(w2) {
38505
38554
  let size = 0;
38506
38555
  try {
38507
- size = import_node_fs18.default.statSync(w2.filePath).size;
38556
+ size = import_node_fs19.default.statSync(w2.filePath).size;
38508
38557
  } catch {
38509
38558
  return;
38510
38559
  }
@@ -38513,11 +38562,11 @@ var SessionObserver = class {
38513
38562
  w2.buf = "";
38514
38563
  }
38515
38564
  if (size === w2.lastSize) return;
38516
- const fd = import_node_fs18.default.openSync(w2.filePath, "r");
38565
+ const fd = import_node_fs19.default.openSync(w2.filePath, "r");
38517
38566
  try {
38518
38567
  const len = size - w2.lastSize;
38519
38568
  const buf = Buffer.alloc(len);
38520
- import_node_fs18.default.readSync(fd, buf, 0, len, w2.lastSize);
38569
+ import_node_fs19.default.readSync(fd, buf, 0, len, w2.lastSize);
38521
38570
  w2.lastSize = size;
38522
38571
  w2.buf += buf.toString("utf8");
38523
38572
  let newlineIndex;
@@ -38540,7 +38589,7 @@ var SessionObserver = class {
38540
38589
  }
38541
38590
  }
38542
38591
  } finally {
38543
- import_node_fs18.default.closeSync(fd);
38592
+ import_node_fs19.default.closeSync(fd);
38544
38593
  }
38545
38594
  }
38546
38595
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -39263,14 +39312,14 @@ async function authenticate(token, deps) {
39263
39312
  }
39264
39313
 
39265
39314
  // src/permission/capability-store.ts
39266
- var fs21 = __toESM(require("fs"), 1);
39267
- var path20 = __toESM(require("path"), 1);
39315
+ var fs22 = __toESM(require("fs"), 1);
39316
+ var path21 = __toESM(require("path"), 1);
39268
39317
  var CAPABILITIES_FILE_NAME = "capabilities.json";
39269
39318
  var FILE_VERSION = 1;
39270
39319
  var CapabilityStore = class {
39271
39320
  constructor(dataDir) {
39272
39321
  this.dataDir = dataDir;
39273
- fs21.mkdirSync(dataDir, { recursive: true });
39322
+ fs22.mkdirSync(dataDir, { recursive: true });
39274
39323
  this.cache = this.readFromDisk();
39275
39324
  }
39276
39325
  dataDir;
@@ -39294,13 +39343,13 @@ var CapabilityStore = class {
39294
39343
  this.flush();
39295
39344
  }
39296
39345
  filePath() {
39297
- return path20.join(this.dataDir, CAPABILITIES_FILE_NAME);
39346
+ return path21.join(this.dataDir, CAPABILITIES_FILE_NAME);
39298
39347
  }
39299
39348
  readFromDisk() {
39300
39349
  const file = this.filePath();
39301
39350
  let raw;
39302
39351
  try {
39303
- raw = fs21.readFileSync(file, "utf8");
39352
+ raw = fs22.readFileSync(file, "utf8");
39304
39353
  } catch (err) {
39305
39354
  if (err?.code === "ENOENT") return [];
39306
39355
  return [];
@@ -39328,10 +39377,10 @@ var CapabilityStore = class {
39328
39377
  }
39329
39378
  atomicWrite(file, content) {
39330
39379
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
39331
- fs21.writeFileSync(tmp, content, { mode: 384 });
39332
- fs21.renameSync(tmp, file);
39380
+ fs22.writeFileSync(tmp, content, { mode: 384 });
39381
+ fs22.renameSync(tmp, file);
39333
39382
  try {
39334
- fs21.chmodSync(file, 384);
39383
+ fs22.chmodSync(file, 384);
39335
39384
  } catch {
39336
39385
  }
39337
39386
  }
@@ -39424,14 +39473,14 @@ var CapabilityManager = class {
39424
39473
  };
39425
39474
 
39426
39475
  // src/permission/cleanup.ts
39427
- var fs22 = __toESM(require("fs"), 1);
39476
+ var fs23 = __toESM(require("fs"), 1);
39428
39477
  function cleanupGuestSessionsForCapability(cap, factory) {
39429
39478
  const removed = [];
39430
39479
  for (const g2 of cap.grants) {
39431
39480
  if (g2.resource.type !== "persona") continue;
39432
39481
  const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
39433
39482
  try {
39434
- fs22.rmSync(dir, { recursive: true, force: true });
39483
+ fs23.rmSync(dir, { recursive: true, force: true });
39435
39484
  removed.push(dir);
39436
39485
  } catch {
39437
39486
  }
@@ -39440,13 +39489,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
39440
39489
  }
39441
39490
 
39442
39491
  // src/inbox/inbox-store.ts
39443
- var fs23 = __toESM(require("fs"), 1);
39444
- var path21 = __toESM(require("path"), 1);
39492
+ var fs24 = __toESM(require("fs"), 1);
39493
+ var path22 = __toESM(require("path"), 1);
39445
39494
  var INBOX_SUBDIR = "inbox";
39446
39495
  var InboxStore = class {
39447
39496
  constructor(dataDir) {
39448
39497
  this.dataDir = dataDir;
39449
- fs23.mkdirSync(this.dirPath(), { recursive: true });
39498
+ fs24.mkdirSync(this.dirPath(), { recursive: true });
39450
39499
  }
39451
39500
  dataDir;
39452
39501
  /**
@@ -39458,7 +39507,7 @@ var InboxStore = class {
39458
39507
  const file = this.filePath(peerDeviceId);
39459
39508
  let raw;
39460
39509
  try {
39461
- raw = fs23.readFileSync(file, "utf8");
39510
+ raw = fs24.readFileSync(file, "utf8");
39462
39511
  } catch (err) {
39463
39512
  if (err?.code === "ENOENT") return [];
39464
39513
  return [];
@@ -39474,7 +39523,7 @@ var InboxStore = class {
39474
39523
  const dir = this.dirPath();
39475
39524
  let entries;
39476
39525
  try {
39477
- entries = fs23.readdirSync(dir);
39526
+ entries = fs24.readdirSync(dir);
39478
39527
  } catch (err) {
39479
39528
  if (err?.code === "ENOENT") return [];
39480
39529
  return [];
@@ -39490,9 +39539,9 @@ var InboxStore = class {
39490
39539
  if (existing.some((m2) => m2.id === message.id)) return;
39491
39540
  const file = this.filePath(message.peerDeviceId);
39492
39541
  const line = JSON.stringify(message) + "\n";
39493
- fs23.appendFileSync(file, line, { mode: 384 });
39542
+ fs24.appendFileSync(file, line, { mode: 384 });
39494
39543
  try {
39495
- fs23.chmodSync(file, 384);
39544
+ fs24.chmodSync(file, 384);
39496
39545
  } catch {
39497
39546
  }
39498
39547
  }
@@ -39522,7 +39571,7 @@ var InboxStore = class {
39522
39571
  removeByPeerDeviceId(peerDeviceId) {
39523
39572
  const file = this.filePath(peerDeviceId);
39524
39573
  try {
39525
- fs23.unlinkSync(file);
39574
+ fs24.unlinkSync(file);
39526
39575
  } catch (err) {
39527
39576
  if (err?.code === "ENOENT") return;
39528
39577
  }
@@ -39531,18 +39580,18 @@ var InboxStore = class {
39531
39580
  const file = this.filePath(peerDeviceId);
39532
39581
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
39533
39582
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
39534
- fs23.writeFileSync(tmp, content, { mode: 384 });
39535
- fs23.renameSync(tmp, file);
39583
+ fs24.writeFileSync(tmp, content, { mode: 384 });
39584
+ fs24.renameSync(tmp, file);
39536
39585
  try {
39537
- fs23.chmodSync(file, 384);
39586
+ fs24.chmodSync(file, 384);
39538
39587
  } catch {
39539
39588
  }
39540
39589
  }
39541
39590
  dirPath() {
39542
- return path21.join(this.dataDir, INBOX_SUBDIR);
39591
+ return path22.join(this.dataDir, INBOX_SUBDIR);
39543
39592
  }
39544
39593
  filePath(peerDeviceId) {
39545
- return path21.join(this.dirPath(), `${peerDeviceId}.jsonl`);
39594
+ return path22.join(this.dirPath(), `${peerDeviceId}.jsonl`);
39546
39595
  }
39547
39596
  };
39548
39597
  function parseAllLines(raw) {
@@ -39629,8 +39678,8 @@ var InboxManager = class {
39629
39678
  };
39630
39679
 
39631
39680
  // src/state/contact-store.ts
39632
- var fs24 = __toESM(require("fs"), 1);
39633
- var path22 = __toESM(require("path"), 1);
39681
+ var fs25 = __toESM(require("fs"), 1);
39682
+ var path23 = __toESM(require("path"), 1);
39634
39683
  var FILE_NAME = "contacts.json";
39635
39684
  var ContactStore = class {
39636
39685
  constructor(dataDir) {
@@ -39640,10 +39689,10 @@ var ContactStore = class {
39640
39689
  contacts = /* @__PURE__ */ new Map();
39641
39690
  load() {
39642
39691
  this.contacts.clear();
39643
- const file = path22.join(this.dataDir, FILE_NAME);
39692
+ const file = path23.join(this.dataDir, FILE_NAME);
39644
39693
  let raw;
39645
39694
  try {
39646
- raw = fs24.readFileSync(file, "utf8");
39695
+ raw = fs25.readFileSync(file, "utf8");
39647
39696
  } catch (err) {
39648
39697
  if (err?.code !== "ENOENT") this.renameBak(file);
39649
39698
  return;
@@ -39686,20 +39735,20 @@ var ContactStore = class {
39686
39735
  return existed;
39687
39736
  }
39688
39737
  flush() {
39689
- const file = path22.join(this.dataDir, FILE_NAME);
39738
+ const file = path23.join(this.dataDir, FILE_NAME);
39690
39739
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
39691
39740
  const content = JSON.stringify(
39692
39741
  { contacts: Array.from(this.contacts.values()) },
39693
39742
  null,
39694
39743
  2
39695
39744
  );
39696
- fs24.mkdirSync(this.dataDir, { recursive: true });
39697
- fs24.writeFileSync(tmp, content, { mode: 384 });
39698
- fs24.renameSync(tmp, file);
39745
+ fs25.mkdirSync(this.dataDir, { recursive: true });
39746
+ fs25.writeFileSync(tmp, content, { mode: 384 });
39747
+ fs25.renameSync(tmp, file);
39699
39748
  }
39700
39749
  renameBak(file) {
39701
39750
  try {
39702
- fs24.renameSync(file, `${file}.bak`);
39751
+ fs25.renameSync(file, `${file}.bak`);
39703
39752
  } catch {
39704
39753
  }
39705
39754
  }
@@ -39849,61 +39898,61 @@ async function autoReverseContact(args) {
39849
39898
  }
39850
39899
 
39851
39900
  // src/migrations/2026-05-20-flatten-sessions.ts
39852
- var fs25 = __toESM(require("fs"), 1);
39853
- var path23 = __toESM(require("path"), 1);
39901
+ var fs26 = __toESM(require("fs"), 1);
39902
+ var path24 = __toESM(require("path"), 1);
39854
39903
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
39855
39904
  function migrateFlattenSessions(opts) {
39856
39905
  const dataDir = opts.dataDir;
39857
39906
  const now = opts.now ?? Date.now;
39858
- const sessionsDir = path23.join(dataDir, "sessions");
39859
- const flagPath = path23.join(sessionsDir, MIGRATION_FLAG_NAME);
39907
+ const sessionsDir = path24.join(dataDir, "sessions");
39908
+ const flagPath = path24.join(sessionsDir, MIGRATION_FLAG_NAME);
39860
39909
  if (existsSync3(flagPath)) {
39861
39910
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
39862
39911
  }
39863
39912
  let movedBare = 0;
39864
39913
  let movedVmOwner = 0;
39865
39914
  let archivedListener = 0;
39866
- const defaultDir = path23.join(sessionsDir, "default");
39915
+ const defaultDir = path24.join(sessionsDir, "default");
39867
39916
  if (existsSync3(defaultDir)) {
39868
39917
  for (const entry of readdirSafe(defaultDir)) {
39869
39918
  if (!entry.endsWith(".json")) continue;
39870
- const src = path23.join(defaultDir, entry);
39871
- const dst = path23.join(sessionsDir, entry);
39872
- fs25.renameSync(src, dst);
39919
+ const src = path24.join(defaultDir, entry);
39920
+ const dst = path24.join(sessionsDir, entry);
39921
+ fs26.renameSync(src, dst);
39873
39922
  movedBare += 1;
39874
39923
  }
39875
39924
  rmdirIfEmpty(defaultDir);
39876
39925
  }
39877
39926
  for (const pid of readdirSafe(sessionsDir)) {
39878
- const personaDir = path23.join(sessionsDir, pid);
39927
+ const personaDir = path24.join(sessionsDir, pid);
39879
39928
  if (!isDir(personaDir)) continue;
39880
39929
  if (pid === "default") continue;
39881
- const ownerSrc = path23.join(personaDir, "owner");
39930
+ const ownerSrc = path24.join(personaDir, "owner");
39882
39931
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
39883
- const ownerDst = path23.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
39884
- fs25.mkdirSync(ownerDst, { recursive: true });
39932
+ const ownerDst = path24.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
39933
+ fs26.mkdirSync(ownerDst, { recursive: true });
39885
39934
  for (const file of readdirSafe(ownerSrc)) {
39886
39935
  if (!file.endsWith(".json")) continue;
39887
- fs25.renameSync(path23.join(ownerSrc, file), path23.join(ownerDst, file));
39936
+ fs26.renameSync(path24.join(ownerSrc, file), path24.join(ownerDst, file));
39888
39937
  movedVmOwner += 1;
39889
39938
  }
39890
39939
  rmdirIfEmpty(ownerSrc);
39891
39940
  }
39892
- const listenerSrc = path23.join(personaDir, "listener");
39941
+ const listenerSrc = path24.join(personaDir, "listener");
39893
39942
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
39894
- const archiveDst = path23.join(dataDir, ".legacy", `listener-${pid}`);
39895
- fs25.mkdirSync(archiveDst, { recursive: true });
39943
+ const archiveDst = path24.join(dataDir, ".legacy", `listener-${pid}`);
39944
+ fs26.mkdirSync(archiveDst, { recursive: true });
39896
39945
  for (const file of readdirSafe(listenerSrc)) {
39897
39946
  if (!file.endsWith(".json")) continue;
39898
- fs25.renameSync(path23.join(listenerSrc, file), path23.join(archiveDst, file));
39947
+ fs26.renameSync(path24.join(listenerSrc, file), path24.join(archiveDst, file));
39899
39948
  archivedListener += 1;
39900
39949
  }
39901
39950
  rmdirIfEmpty(listenerSrc);
39902
39951
  }
39903
39952
  rmdirIfEmpty(personaDir);
39904
39953
  }
39905
- fs25.mkdirSync(sessionsDir, { recursive: true });
39906
- fs25.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
39954
+ fs26.mkdirSync(sessionsDir, { recursive: true });
39955
+ fs26.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
39907
39956
  return {
39908
39957
  skipped: false,
39909
39958
  flagWritten: true,
@@ -39914,7 +39963,7 @@ function migrateFlattenSessions(opts) {
39914
39963
  }
39915
39964
  function existsSync3(p2) {
39916
39965
  try {
39917
- fs25.statSync(p2);
39966
+ fs26.statSync(p2);
39918
39967
  return true;
39919
39968
  } catch {
39920
39969
  return false;
@@ -39922,31 +39971,31 @@ function existsSync3(p2) {
39922
39971
  }
39923
39972
  function isDir(p2) {
39924
39973
  try {
39925
- return fs25.statSync(p2).isDirectory();
39974
+ return fs26.statSync(p2).isDirectory();
39926
39975
  } catch {
39927
39976
  return false;
39928
39977
  }
39929
39978
  }
39930
39979
  function readdirSafe(p2) {
39931
39980
  try {
39932
- return fs25.readdirSync(p2);
39981
+ return fs26.readdirSync(p2);
39933
39982
  } catch {
39934
39983
  return [];
39935
39984
  }
39936
39985
  }
39937
39986
  function rmdirIfEmpty(p2) {
39938
39987
  try {
39939
- fs25.rmdirSync(p2);
39988
+ fs26.rmdirSync(p2);
39940
39989
  } catch {
39941
39990
  }
39942
39991
  }
39943
39992
 
39944
39993
  // src/transport/http-router.ts
39945
- var import_node_fs20 = __toESM(require("fs"), 1);
39946
- var import_node_path19 = __toESM(require("path"), 1);
39994
+ var import_node_fs21 = __toESM(require("fs"), 1);
39995
+ var import_node_path20 = __toESM(require("path"), 1);
39947
39996
 
39948
39997
  // src/attachment/mime.ts
39949
- var import_node_path16 = __toESM(require("path"), 1);
39998
+ var import_node_path17 = __toESM(require("path"), 1);
39950
39999
  var TEXT_PLAIN = "text/plain; charset=utf-8";
39951
40000
  var EXT_TO_NATIVE_MIME = {
39952
40001
  // 图片
@@ -40053,7 +40102,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
40053
40102
  ".mk"
40054
40103
  ]);
40055
40104
  function lookupMime(filePathOrName) {
40056
- const ext = import_node_path16.default.extname(filePathOrName).toLowerCase();
40105
+ const ext = import_node_path17.default.extname(filePathOrName).toLowerCase();
40057
40106
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
40058
40107
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
40059
40108
  return "application/octet-stream";
@@ -40122,8 +40171,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
40122
40171
  }
40123
40172
 
40124
40173
  // src/attachment/upload.ts
40125
- var import_node_fs19 = __toESM(require("fs"), 1);
40126
- var import_node_path17 = __toESM(require("path"), 1);
40174
+ var import_node_fs20 = __toESM(require("fs"), 1);
40175
+ var import_node_path18 = __toESM(require("path"), 1);
40127
40176
  var import_node_crypto5 = __toESM(require("crypto"), 1);
40128
40177
  var import_promises = require("stream/promises");
40129
40178
  var UploadError = class extends Error {
@@ -40135,22 +40184,22 @@ var UploadError = class extends Error {
40135
40184
  code;
40136
40185
  };
40137
40186
  function assertValidFileName(fileName) {
40138
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path17.default.basename(fileName)) {
40187
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path18.default.basename(fileName)) {
40139
40188
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
40140
40189
  }
40141
40190
  }
40142
40191
  var HASH_PREFIX_LEN = 16;
40143
40192
  async function writeUploadedAttachment(args) {
40144
40193
  assertValidFileName(args.fileName);
40145
- const attachmentsRoot = import_node_path17.default.join(args.sessionDir, ".attachments");
40194
+ const attachmentsRoot = import_node_path18.default.join(args.sessionDir, ".attachments");
40146
40195
  try {
40147
- import_node_fs19.default.mkdirSync(attachmentsRoot, { recursive: true });
40196
+ import_node_fs20.default.mkdirSync(attachmentsRoot, { recursive: true });
40148
40197
  } catch (err) {
40149
40198
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
40150
40199
  }
40151
40200
  const hasher = import_node_crypto5.default.createHash("sha256");
40152
40201
  let actualSize = 0;
40153
- const tmpPath = import_node_path17.default.join(
40202
+ const tmpPath = import_node_path18.default.join(
40154
40203
  attachmentsRoot,
40155
40204
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto5.default.randomBytes(4).toString("hex")}`
40156
40205
  );
@@ -40165,18 +40214,18 @@ async function writeUploadedAttachment(args) {
40165
40214
  yield buf;
40166
40215
  }
40167
40216
  },
40168
- import_node_fs19.default.createWriteStream(tmpPath, { mode: 384 })
40217
+ import_node_fs20.default.createWriteStream(tmpPath, { mode: 384 })
40169
40218
  );
40170
40219
  } catch (err) {
40171
40220
  try {
40172
- import_node_fs19.default.unlinkSync(tmpPath);
40221
+ import_node_fs20.default.unlinkSync(tmpPath);
40173
40222
  } catch {
40174
40223
  }
40175
40224
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
40176
40225
  }
40177
40226
  if (actualSize !== args.contentLength) {
40178
40227
  try {
40179
- import_node_fs19.default.unlinkSync(tmpPath);
40228
+ import_node_fs20.default.unlinkSync(tmpPath);
40180
40229
  } catch {
40181
40230
  }
40182
40231
  throw new UploadError(
@@ -40185,35 +40234,35 @@ async function writeUploadedAttachment(args) {
40185
40234
  );
40186
40235
  }
40187
40236
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
40188
- const hashDir = import_node_path17.default.join(attachmentsRoot, attachmentId);
40237
+ const hashDir = import_node_path18.default.join(attachmentsRoot, attachmentId);
40189
40238
  let finalFileName;
40190
40239
  let hashDirExists = false;
40191
40240
  try {
40192
- hashDirExists = import_node_fs19.default.statSync(hashDir).isDirectory();
40241
+ hashDirExists = import_node_fs20.default.statSync(hashDir).isDirectory();
40193
40242
  } catch {
40194
40243
  }
40195
40244
  if (hashDirExists) {
40196
- const existing = import_node_fs19.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
40245
+ const existing = import_node_fs20.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
40197
40246
  finalFileName = existing[0] ?? args.fileName;
40198
40247
  try {
40199
- import_node_fs19.default.unlinkSync(tmpPath);
40248
+ import_node_fs20.default.unlinkSync(tmpPath);
40200
40249
  } catch {
40201
40250
  }
40202
40251
  } else {
40203
40252
  try {
40204
- import_node_fs19.default.mkdirSync(hashDir, { recursive: true });
40253
+ import_node_fs20.default.mkdirSync(hashDir, { recursive: true });
40205
40254
  finalFileName = args.fileName;
40206
- import_node_fs19.default.renameSync(tmpPath, import_node_path17.default.join(hashDir, finalFileName));
40255
+ import_node_fs20.default.renameSync(tmpPath, import_node_path18.default.join(hashDir, finalFileName));
40207
40256
  } catch (err) {
40208
40257
  try {
40209
- import_node_fs19.default.unlinkSync(tmpPath);
40258
+ import_node_fs20.default.unlinkSync(tmpPath);
40210
40259
  } catch {
40211
40260
  }
40212
40261
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
40213
40262
  }
40214
40263
  }
40215
- const absPath = import_node_path17.default.join(hashDir, finalFileName);
40216
- const relPath = import_node_path17.default.relative(args.sessionDir, absPath);
40264
+ const absPath = import_node_path18.default.join(hashDir, finalFileName);
40265
+ const relPath = import_node_path18.default.relative(args.sessionDir, absPath);
40217
40266
  args.groupFileStore.upsert(args.scope, args.sessionId, {
40218
40267
  relPath: absPath,
40219
40268
  // 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
@@ -40227,7 +40276,7 @@ async function writeUploadedAttachment(args) {
40227
40276
 
40228
40277
  // src/extension/import.ts
40229
40278
  var import_promises2 = __toESM(require("fs/promises"), 1);
40230
- var import_node_path18 = __toESM(require("path"), 1);
40279
+ var import_node_path19 = __toESM(require("path"), 1);
40231
40280
  var import_node_os11 = __toESM(require("os"), 1);
40232
40281
  var import_jszip = __toESM(require_lib3(), 1);
40233
40282
  var ImportError = class extends Error {
@@ -40245,7 +40294,7 @@ async function importZip(buf, root) {
40245
40294
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
40246
40295
  }
40247
40296
  for (const name of Object.keys(zip.files)) {
40248
- if (name.includes("..") || name.startsWith("/") || import_node_path18.default.isAbsolute(name)) {
40297
+ if (name.includes("..") || name.startsWith("/") || import_node_path19.default.isAbsolute(name)) {
40249
40298
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
40250
40299
  }
40251
40300
  }
@@ -40278,7 +40327,7 @@ async function importZip(buf, root) {
40278
40327
  );
40279
40328
  }
40280
40329
  }
40281
- const destDir = import_node_path18.default.join(root, manifest.id);
40330
+ const destDir = import_node_path19.default.join(root, manifest.id);
40282
40331
  let destExists = false;
40283
40332
  try {
40284
40333
  await import_promises2.default.access(destDir);
@@ -40288,15 +40337,15 @@ async function importZip(buf, root) {
40288
40337
  if (destExists) {
40289
40338
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
40290
40339
  }
40291
- const stage = await import_promises2.default.mkdtemp(import_node_path18.default.join(import_node_os11.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
40340
+ const stage = await import_promises2.default.mkdtemp(import_node_path19.default.join(import_node_os11.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
40292
40341
  try {
40293
40342
  for (const [name, entry] of Object.entries(zip.files)) {
40294
- const dest = import_node_path18.default.join(stage, name);
40343
+ const dest = import_node_path19.default.join(stage, name);
40295
40344
  if (entry.dir) {
40296
40345
  await import_promises2.default.mkdir(dest, { recursive: true });
40297
40346
  continue;
40298
40347
  }
40299
- await import_promises2.default.mkdir(import_node_path18.default.dirname(dest), { recursive: true });
40348
+ await import_promises2.default.mkdir(import_node_path19.default.dirname(dest), { recursive: true });
40300
40349
  const content = await entry.async("nodebuffer");
40301
40350
  await import_promises2.default.writeFile(dest, content);
40302
40351
  }
@@ -40418,7 +40467,7 @@ function isValidUploadFileName(fileName) {
40418
40467
  if (fileName === "." || fileName === "..") return false;
40419
40468
  if (fileName.startsWith(".")) return false;
40420
40469
  if (fileName.includes("/") || fileName.includes("\\")) return false;
40421
- return fileName === import_node_path19.default.basename(fileName);
40470
+ return fileName === import_node_path20.default.basename(fileName);
40422
40471
  }
40423
40472
  function createHttpRouter(deps) {
40424
40473
  return async (req, res) => {
@@ -40567,7 +40616,7 @@ function createHttpRouter(deps) {
40567
40616
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
40568
40617
  return true;
40569
40618
  }
40570
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path19.default.basename(r.absPath)));
40619
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path20.default.basename(r.absPath)));
40571
40620
  return true;
40572
40621
  }
40573
40622
  const ctx = deps.authResolver.resolveFromHeader(
@@ -40688,7 +40737,7 @@ function createHttpRouter(deps) {
40688
40737
  return true;
40689
40738
  }
40690
40739
  let absPath;
40691
- if (import_node_path19.default.isAbsolute(pathParam)) {
40740
+ if (import_node_path20.default.isAbsolute(pathParam)) {
40692
40741
  absPath = pathParam;
40693
40742
  } else if (deps.sessionStore) {
40694
40743
  const file = deps.sessionStore.read(sid);
@@ -40696,7 +40745,7 @@ function createHttpRouter(deps) {
40696
40745
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
40697
40746
  return true;
40698
40747
  }
40699
- absPath = import_node_path19.default.join(file.cwd, pathParam);
40748
+ absPath = import_node_path20.default.join(file.cwd, pathParam);
40700
40749
  } else {
40701
40750
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
40702
40751
  return true;
@@ -40783,7 +40832,7 @@ function withCtx(ctx, body) {
40783
40832
  function streamFile(res, absPath, logger) {
40784
40833
  let stat;
40785
40834
  try {
40786
- stat = import_node_fs20.default.statSync(absPath);
40835
+ stat = import_node_fs21.default.statSync(absPath);
40787
40836
  } catch (err) {
40788
40837
  const code = err?.code;
40789
40838
  if (code === "ENOENT") {
@@ -40798,7 +40847,7 @@ function streamFile(res, absPath, logger) {
40798
40847
  return;
40799
40848
  }
40800
40849
  const mime = lookupMime(absPath);
40801
- const basename = import_node_path19.default.basename(absPath);
40850
+ const basename = import_node_path20.default.basename(absPath);
40802
40851
  res.writeHead(200, {
40803
40852
  "Content-Type": mime,
40804
40853
  "Content-Length": String(stat.size),
@@ -40806,7 +40855,7 @@ function streamFile(res, absPath, logger) {
40806
40855
  // 防止浏览器把任意 mime 当 html 渲染
40807
40856
  "X-Content-Type-Options": "nosniff"
40808
40857
  });
40809
- const stream = import_node_fs20.default.createReadStream(absPath);
40858
+ const stream = import_node_fs21.default.createReadStream(absPath);
40810
40859
  stream.on("error", (err) => {
40811
40860
  logger?.warn("streamFile read error", { absPath, err: err.message });
40812
40861
  res.destroy();
@@ -40815,8 +40864,8 @@ function streamFile(res, absPath, logger) {
40815
40864
  }
40816
40865
 
40817
40866
  // src/attachment/gc.ts
40818
- var import_node_fs21 = __toESM(require("fs"), 1);
40819
- var import_node_path20 = __toESM(require("path"), 1);
40867
+ var import_node_fs22 = __toESM(require("fs"), 1);
40868
+ var import_node_path21 = __toESM(require("path"), 1);
40820
40869
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
40821
40870
  function runAttachmentGc(args) {
40822
40871
  const now = (args.now ?? Date.now)();
@@ -40825,38 +40874,38 @@ function runAttachmentGc(args) {
40825
40874
  for (const { scope, sessionId } of args.sessionScopes) {
40826
40875
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
40827
40876
  if (entry.stale) continue;
40828
- if (import_node_path20.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
40877
+ if (import_node_path21.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
40829
40878
  }
40830
40879
  }
40831
40880
  for (const { scope, sessionId } of args.sessionScopes) {
40832
- const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path20.default.join(
40881
+ const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path21.default.join(
40833
40882
  args.dataDir,
40834
40883
  "sessions",
40835
40884
  ...scopeSubPath(scope).map(safeFileName),
40836
40885
  safeFileName(sessionId)
40837
40886
  );
40838
- const attRoot = import_node_path20.default.join(sessionDir, ".attachments");
40887
+ const attRoot = import_node_path21.default.join(sessionDir, ".attachments");
40839
40888
  let hashDirs;
40840
40889
  try {
40841
- hashDirs = import_node_fs21.default.readdirSync(attRoot);
40890
+ hashDirs = import_node_fs22.default.readdirSync(attRoot);
40842
40891
  } catch (err) {
40843
40892
  if (err.code === "ENOENT") continue;
40844
40893
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
40845
40894
  continue;
40846
40895
  }
40847
40896
  for (const hashDir of hashDirs) {
40848
- const hashDirAbs = import_node_path20.default.join(attRoot, hashDir);
40897
+ const hashDirAbs = import_node_path21.default.join(attRoot, hashDir);
40849
40898
  let files;
40850
40899
  try {
40851
- files = import_node_fs21.default.readdirSync(hashDirAbs);
40900
+ files = import_node_fs22.default.readdirSync(hashDirAbs);
40852
40901
  } catch {
40853
40902
  continue;
40854
40903
  }
40855
40904
  for (const name of files) {
40856
- const file = import_node_path20.default.join(hashDirAbs, name);
40905
+ const file = import_node_path21.default.join(hashDirAbs, name);
40857
40906
  let stat;
40858
40907
  try {
40859
- stat = import_node_fs21.default.statSync(file);
40908
+ stat = import_node_fs22.default.statSync(file);
40860
40909
  } catch {
40861
40910
  continue;
40862
40911
  }
@@ -40865,26 +40914,26 @@ function runAttachmentGc(args) {
40865
40914
  if (age < ttlMs) continue;
40866
40915
  if (liveAbs.has(file)) continue;
40867
40916
  try {
40868
- import_node_fs21.default.unlinkSync(file);
40917
+ import_node_fs22.default.unlinkSync(file);
40869
40918
  } catch (err) {
40870
40919
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
40871
40920
  }
40872
40921
  }
40873
40922
  try {
40874
- if (import_node_fs21.default.readdirSync(hashDirAbs).length === 0) import_node_fs21.default.rmdirSync(hashDirAbs);
40923
+ if (import_node_fs22.default.readdirSync(hashDirAbs).length === 0) import_node_fs22.default.rmdirSync(hashDirAbs);
40875
40924
  } catch {
40876
40925
  }
40877
40926
  }
40878
40927
  try {
40879
- if (import_node_fs21.default.readdirSync(attRoot).length === 0) import_node_fs21.default.rmdirSync(attRoot);
40928
+ if (import_node_fs22.default.readdirSync(attRoot).length === 0) import_node_fs22.default.rmdirSync(attRoot);
40880
40929
  } catch {
40881
40930
  }
40882
40931
  }
40883
40932
  }
40884
40933
 
40885
40934
  // src/attachment/group.ts
40886
- var import_node_fs22 = __toESM(require("fs"), 1);
40887
- var import_node_path21 = __toESM(require("path"), 1);
40935
+ var import_node_fs23 = __toESM(require("fs"), 1);
40936
+ var import_node_path22 = __toESM(require("path"), 1);
40888
40937
  var import_node_crypto6 = __toESM(require("crypto"), 1);
40889
40938
  init_protocol();
40890
40939
  var GroupFileStore = class {
@@ -40896,11 +40945,11 @@ var GroupFileStore = class {
40896
40945
  this.logger = opts.logger;
40897
40946
  }
40898
40947
  rootForScope(scope) {
40899
- return import_node_path21.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
40948
+ return import_node_path22.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
40900
40949
  }
40901
40950
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
40902
40951
  filePath(scope, sessionId) {
40903
- return import_node_path21.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
40952
+ return import_node_path22.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
40904
40953
  }
40905
40954
  cacheKey(scope, sessionId) {
40906
40955
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -40909,7 +40958,7 @@ var GroupFileStore = class {
40909
40958
  readFile(scope, sessionId) {
40910
40959
  const file = this.filePath(scope, sessionId);
40911
40960
  try {
40912
- const raw = import_node_fs22.default.readFileSync(file, "utf8");
40961
+ const raw = import_node_fs23.default.readFileSync(file, "utf8");
40913
40962
  const parsed = JSON.parse(raw);
40914
40963
  if (!Array.isArray(parsed)) {
40915
40964
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -40935,10 +40984,10 @@ var GroupFileStore = class {
40935
40984
  }
40936
40985
  writeFile(scope, sessionId, entries) {
40937
40986
  const file = this.filePath(scope, sessionId);
40938
- import_node_fs22.default.mkdirSync(import_node_path21.default.dirname(file), { recursive: true });
40987
+ import_node_fs23.default.mkdirSync(import_node_path22.default.dirname(file), { recursive: true });
40939
40988
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
40940
- import_node_fs22.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
40941
- import_node_fs22.default.renameSync(tmp, file);
40989
+ import_node_fs23.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
40990
+ import_node_fs23.default.renameSync(tmp, file);
40942
40991
  }
40943
40992
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
40944
40993
  list(scope, sessionId) {
@@ -41024,10 +41073,10 @@ var GroupFileStore = class {
41024
41073
  };
41025
41074
 
41026
41075
  // src/discovery/state-file.ts
41027
- var import_node_fs23 = __toESM(require("fs"), 1);
41028
- var import_node_path22 = __toESM(require("path"), 1);
41076
+ var import_node_fs24 = __toESM(require("fs"), 1);
41077
+ var import_node_path23 = __toESM(require("path"), 1);
41029
41078
  function defaultStateFilePath(dataDir) {
41030
- return import_node_path22.default.join(dataDir, "state.json");
41079
+ return import_node_path23.default.join(dataDir, "state.json");
41031
41080
  }
41032
41081
  function isPidAlive(pid) {
41033
41082
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -41049,7 +41098,7 @@ var StateFileManager = class {
41049
41098
  }
41050
41099
  read() {
41051
41100
  try {
41052
- const raw = import_node_fs23.default.readFileSync(this.file, "utf8");
41101
+ const raw = import_node_fs24.default.readFileSync(this.file, "utf8");
41053
41102
  const parsed = JSON.parse(raw);
41054
41103
  return parsed;
41055
41104
  } catch {
@@ -41063,20 +41112,20 @@ var StateFileManager = class {
41063
41112
  return { status: "stale", existing };
41064
41113
  }
41065
41114
  write(state) {
41066
- import_node_fs23.default.mkdirSync(import_node_path22.default.dirname(this.file), { recursive: true });
41115
+ import_node_fs24.default.mkdirSync(import_node_path23.default.dirname(this.file), { recursive: true });
41067
41116
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
41068
- import_node_fs23.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
41069
- import_node_fs23.default.renameSync(tmp, this.file);
41117
+ import_node_fs24.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
41118
+ import_node_fs24.default.renameSync(tmp, this.file);
41070
41119
  if (process.platform !== "win32") {
41071
41120
  try {
41072
- import_node_fs23.default.chmodSync(this.file, 384);
41121
+ import_node_fs24.default.chmodSync(this.file, 384);
41073
41122
  } catch {
41074
41123
  }
41075
41124
  }
41076
41125
  }
41077
41126
  delete() {
41078
41127
  try {
41079
- import_node_fs23.default.unlinkSync(this.file);
41128
+ import_node_fs24.default.unlinkSync(this.file);
41080
41129
  } catch {
41081
41130
  }
41082
41131
  }
@@ -41091,14 +41140,14 @@ function readDaemonSourceFromEnv(env = process.env) {
41091
41140
  }
41092
41141
 
41093
41142
  // src/tunnel/tunnel-manager.ts
41094
- var import_node_fs27 = __toESM(require("fs"), 1);
41095
- var import_node_path26 = __toESM(require("path"), 1);
41143
+ var import_node_fs28 = __toESM(require("fs"), 1);
41144
+ var import_node_path27 = __toESM(require("path"), 1);
41096
41145
  var import_node_crypto7 = __toESM(require("crypto"), 1);
41097
41146
  var import_node_child_process9 = require("child_process");
41098
41147
 
41099
41148
  // src/tunnel/tunnel-store.ts
41100
- var import_node_fs24 = __toESM(require("fs"), 1);
41101
- var import_node_path23 = __toESM(require("path"), 1);
41149
+ var import_node_fs25 = __toESM(require("fs"), 1);
41150
+ var import_node_path24 = __toESM(require("path"), 1);
41102
41151
  var TunnelStore = class {
41103
41152
  constructor(filePath) {
41104
41153
  this.filePath = filePath;
@@ -41106,7 +41155,7 @@ var TunnelStore = class {
41106
41155
  filePath;
41107
41156
  async get() {
41108
41157
  try {
41109
- const raw = await import_node_fs24.default.promises.readFile(this.filePath, "utf8");
41158
+ const raw = await import_node_fs25.default.promises.readFile(this.filePath, "utf8");
41110
41159
  const obj = JSON.parse(raw);
41111
41160
  if (!isPersistedTunnel(obj)) return null;
41112
41161
  return obj;
@@ -41117,22 +41166,22 @@ var TunnelStore = class {
41117
41166
  }
41118
41167
  }
41119
41168
  async set(v2) {
41120
- const dir = import_node_path23.default.dirname(this.filePath);
41121
- await import_node_fs24.default.promises.mkdir(dir, { recursive: true });
41169
+ const dir = import_node_path24.default.dirname(this.filePath);
41170
+ await import_node_fs25.default.promises.mkdir(dir, { recursive: true });
41122
41171
  const data = JSON.stringify(v2, null, 2);
41123
41172
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
41124
- await import_node_fs24.default.promises.writeFile(tmp, data, { mode: 384 });
41173
+ await import_node_fs25.default.promises.writeFile(tmp, data, { mode: 384 });
41125
41174
  if (process.platform !== "win32") {
41126
41175
  try {
41127
- await import_node_fs24.default.promises.chmod(tmp, 384);
41176
+ await import_node_fs25.default.promises.chmod(tmp, 384);
41128
41177
  } catch {
41129
41178
  }
41130
41179
  }
41131
- await import_node_fs24.default.promises.rename(tmp, this.filePath);
41180
+ await import_node_fs25.default.promises.rename(tmp, this.filePath);
41132
41181
  }
41133
41182
  async clear() {
41134
41183
  try {
41135
- await import_node_fs24.default.promises.unlink(this.filePath);
41184
+ await import_node_fs25.default.promises.unlink(this.filePath);
41136
41185
  } catch (err) {
41137
41186
  const code = err?.code;
41138
41187
  if (code !== "ENOENT") throw err;
@@ -41227,9 +41276,9 @@ function escape(v2) {
41227
41276
  }
41228
41277
 
41229
41278
  // src/tunnel/frpc-binary.ts
41230
- var import_node_fs25 = __toESM(require("fs"), 1);
41279
+ var import_node_fs26 = __toESM(require("fs"), 1);
41231
41280
  var import_node_os12 = __toESM(require("os"), 1);
41232
- var import_node_path24 = __toESM(require("path"), 1);
41281
+ var import_node_path25 = __toESM(require("path"), 1);
41233
41282
  var import_node_child_process7 = require("child_process");
41234
41283
  var import_node_stream3 = require("stream");
41235
41284
  var import_promises3 = require("stream/promises");
@@ -41261,20 +41310,20 @@ function frpcDownloadUrl(version2, p2) {
41261
41310
  }
41262
41311
  async function ensureFrpcBinary(opts) {
41263
41312
  if (opts.override) {
41264
- if (!import_node_fs25.default.existsSync(opts.override)) {
41313
+ if (!import_node_fs26.default.existsSync(opts.override)) {
41265
41314
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
41266
41315
  }
41267
41316
  return opts.override;
41268
41317
  }
41269
41318
  const version2 = opts.version ?? FRPC_VERSION;
41270
41319
  const platform = opts.platform ?? detectPlatform();
41271
- const binDir = import_node_path24.default.join(opts.dataDir, "bin");
41272
- import_node_fs25.default.mkdirSync(binDir, { recursive: true });
41320
+ const binDir = import_node_path25.default.join(opts.dataDir, "bin");
41321
+ import_node_fs26.default.mkdirSync(binDir, { recursive: true });
41273
41322
  cleanupStaleArtifacts(binDir);
41274
- const stableBin = import_node_path24.default.join(binDir, "frpc");
41275
- if (import_node_fs25.default.existsSync(stableBin)) return stableBin;
41323
+ const stableBin = import_node_path25.default.join(binDir, "frpc");
41324
+ if (import_node_fs26.default.existsSync(stableBin)) return stableBin;
41276
41325
  const partialBin = `${stableBin}.partial`;
41277
- const tarballPath = import_node_path24.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
41326
+ const tarballPath = import_node_path25.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
41278
41327
  try {
41279
41328
  const url = frpcDownloadUrl(version2, platform);
41280
41329
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -41283,8 +41332,8 @@ async function ensureFrpcBinary(opts) {
41283
41332
  } else {
41284
41333
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
41285
41334
  }
41286
- import_node_fs25.default.chmodSync(partialBin, 493);
41287
- import_node_fs25.default.renameSync(partialBin, stableBin);
41335
+ import_node_fs26.default.chmodSync(partialBin, 493);
41336
+ import_node_fs26.default.renameSync(partialBin, stableBin);
41288
41337
  } finally {
41289
41338
  safeUnlink(tarballPath);
41290
41339
  safeUnlink(partialBin);
@@ -41294,15 +41343,15 @@ async function ensureFrpcBinary(opts) {
41294
41343
  function cleanupStaleArtifacts(binDir) {
41295
41344
  let entries;
41296
41345
  try {
41297
- entries = import_node_fs25.default.readdirSync(binDir);
41346
+ entries = import_node_fs26.default.readdirSync(binDir);
41298
41347
  } catch {
41299
41348
  return;
41300
41349
  }
41301
41350
  for (const name of entries) {
41302
41351
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
41303
- const full = import_node_path24.default.join(binDir, name);
41352
+ const full = import_node_path25.default.join(binDir, name);
41304
41353
  try {
41305
- import_node_fs25.default.rmSync(full, { recursive: true, force: true });
41354
+ import_node_fs26.default.rmSync(full, { recursive: true, force: true });
41306
41355
  } catch {
41307
41356
  }
41308
41357
  }
@@ -41310,7 +41359,7 @@ function cleanupStaleArtifacts(binDir) {
41310
41359
  }
41311
41360
  function safeUnlink(p2) {
41312
41361
  try {
41313
- import_node_fs25.default.unlinkSync(p2);
41362
+ import_node_fs26.default.unlinkSync(p2);
41314
41363
  } catch {
41315
41364
  }
41316
41365
  }
@@ -41321,13 +41370,13 @@ async function downloadToFile(url, dest, fetchImpl) {
41321
41370
  if (!res.ok || !res.body) {
41322
41371
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
41323
41372
  }
41324
- const out = import_node_fs25.default.createWriteStream(dest);
41373
+ const out = import_node_fs26.default.createWriteStream(dest);
41325
41374
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
41326
41375
  await (0, import_promises3.pipeline)(nodeStream, out);
41327
41376
  }
41328
41377
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
41329
- const work = import_node_path24.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
41330
- import_node_fs25.default.mkdirSync(work, { recursive: true });
41378
+ const work = import_node_path25.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
41379
+ import_node_fs26.default.mkdirSync(work, { recursive: true });
41331
41380
  try {
41332
41381
  await new Promise((resolve6, reject) => {
41333
41382
  const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -41335,32 +41384,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
41335
41384
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
41336
41385
  });
41337
41386
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
41338
- const src = import_node_path24.default.join(work, dirName, "frpc");
41339
- if (!import_node_fs25.default.existsSync(src)) {
41387
+ const src = import_node_path25.default.join(work, dirName, "frpc");
41388
+ if (!import_node_fs26.default.existsSync(src)) {
41340
41389
  throw new Error(`frpc not found inside tarball at ${src}`);
41341
41390
  }
41342
- import_node_fs25.default.copyFileSync(src, destBin);
41391
+ import_node_fs26.default.copyFileSync(src, destBin);
41343
41392
  } finally {
41344
- import_node_fs25.default.rmSync(work, { recursive: true, force: true });
41393
+ import_node_fs26.default.rmSync(work, { recursive: true, force: true });
41345
41394
  }
41346
41395
  }
41347
41396
 
41348
41397
  // src/tunnel/frpc-process.ts
41349
- var import_node_fs26 = __toESM(require("fs"), 1);
41350
- var import_node_path25 = __toESM(require("path"), 1);
41398
+ var import_node_fs27 = __toESM(require("fs"), 1);
41399
+ var import_node_path26 = __toESM(require("path"), 1);
41351
41400
  var import_node_child_process8 = require("child_process");
41352
41401
  function frpcPidFilePath(dataDir) {
41353
- return import_node_path25.default.join(dataDir, "frpc.pid");
41402
+ return import_node_path26.default.join(dataDir, "frpc.pid");
41354
41403
  }
41355
41404
  function writeFrpcPid(dataDir, pid) {
41356
41405
  try {
41357
- import_node_fs26.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
41406
+ import_node_fs27.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
41358
41407
  } catch {
41359
41408
  }
41360
41409
  }
41361
41410
  function clearFrpcPid(dataDir) {
41362
41411
  try {
41363
- import_node_fs26.default.unlinkSync(frpcPidFilePath(dataDir));
41412
+ import_node_fs27.default.unlinkSync(frpcPidFilePath(dataDir));
41364
41413
  } catch {
41365
41414
  }
41366
41415
  }
@@ -41376,7 +41425,7 @@ function defaultIsPidAlive(pid) {
41376
41425
  }
41377
41426
  function defaultReadPidFile(file) {
41378
41427
  try {
41379
- return import_node_fs26.default.readFileSync(file, "utf8");
41428
+ return import_node_fs27.default.readFileSync(file, "utf8");
41380
41429
  } catch {
41381
41430
  return null;
41382
41431
  }
@@ -41392,7 +41441,7 @@ function defaultSleep(ms) {
41392
41441
  }
41393
41442
  async function killStaleFrpc(deps) {
41394
41443
  const pidFile = frpcPidFilePath(deps.dataDir);
41395
- const tomlPath = import_node_path25.default.join(deps.dataDir, "frpc.toml");
41444
+ const tomlPath = import_node_path26.default.join(deps.dataDir, "frpc.toml");
41396
41445
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
41397
41446
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
41398
41447
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -41416,7 +41465,7 @@ async function killStaleFrpc(deps) {
41416
41465
  }
41417
41466
  if (victims.size === 0) {
41418
41467
  try {
41419
- import_node_fs26.default.unlinkSync(pidFile);
41468
+ import_node_fs27.default.unlinkSync(pidFile);
41420
41469
  } catch {
41421
41470
  }
41422
41471
  return;
@@ -41427,7 +41476,7 @@ async function killStaleFrpc(deps) {
41427
41476
  }
41428
41477
  await sleep2(deps.reapWaitMs ?? 300);
41429
41478
  try {
41430
- import_node_fs26.default.unlinkSync(pidFile);
41479
+ import_node_fs27.default.unlinkSync(pidFile);
41431
41480
  } catch {
41432
41481
  }
41433
41482
  }
@@ -41464,7 +41513,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
41464
41513
  var TunnelManager = class {
41465
41514
  constructor(deps) {
41466
41515
  this.deps = deps;
41467
- this.store = deps.store ?? new TunnelStore(import_node_path26.default.join(deps.dataDir, "tunnel.json"));
41516
+ this.store = deps.store ?? new TunnelStore(import_node_path27.default.join(deps.dataDir, "tunnel.json"));
41468
41517
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
41469
41518
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
41470
41519
  }
@@ -41591,7 +41640,7 @@ var TunnelManager = class {
41591
41640
  dataDir: this.deps.dataDir,
41592
41641
  override: this.deps.frpcBinaryOverride ?? void 0
41593
41642
  });
41594
- const tomlPath = import_node_path26.default.join(this.deps.dataDir, "frpc.toml");
41643
+ const tomlPath = import_node_path27.default.join(this.deps.dataDir, "frpc.toml");
41595
41644
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
41596
41645
  const toml = buildFrpcToml({
41597
41646
  serverAddr: t.frpsHost,
@@ -41602,12 +41651,12 @@ var TunnelManager = class {
41602
41651
  localPort,
41603
41652
  logLevel: "info"
41604
41653
  });
41605
- await import_node_fs27.default.promises.writeFile(tomlPath, toml, { mode: 384 });
41654
+ await import_node_fs28.default.promises.writeFile(tomlPath, toml, { mode: 384 });
41606
41655
  const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
41607
41656
  stdio: ["ignore", "pipe", "pipe"]
41608
41657
  });
41609
- const logFilePath = import_node_path26.default.join(this.deps.dataDir, "frpc.log");
41610
- const logStream = import_node_fs27.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
41658
+ const logFilePath = import_node_path27.default.join(this.deps.dataDir, "frpc.log");
41659
+ const logStream = import_node_fs28.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
41611
41660
  logStream.on("error", () => {
41612
41661
  });
41613
41662
  const tee = (chunk) => {
@@ -41690,27 +41739,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
41690
41739
 
41691
41740
  // src/tunnel/device-key.ts
41692
41741
  var import_node_os13 = __toESM(require("os"), 1);
41693
- var import_node_path27 = __toESM(require("path"), 1);
41742
+ var import_node_path28 = __toESM(require("path"), 1);
41694
41743
  var import_node_crypto8 = __toESM(require("crypto"), 1);
41695
41744
  var DERIVE_SALT = "clawd-tunnel-device-v1";
41696
41745
  function deriveStableDeviceKey(opts = {}) {
41697
41746
  const hostname = opts.hostname ?? import_node_os13.default.hostname();
41698
41747
  const uid = opts.uid ?? (typeof import_node_os13.default.userInfo === "function" ? import_node_os13.default.userInfo().uid : 0);
41699
41748
  const home = opts.home ?? import_node_os13.default.homedir();
41700
- const defaultDataDir = import_node_path27.default.resolve(import_node_path27.default.join(home, ".clawd"));
41701
- const normalizedDataDir = opts.dataDir ? import_node_path27.default.resolve(opts.dataDir) : null;
41749
+ const defaultDataDir = import_node_path28.default.resolve(import_node_path28.default.join(home, ".clawd"));
41750
+ const normalizedDataDir = opts.dataDir ? import_node_path28.default.resolve(opts.dataDir) : null;
41702
41751
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
41703
41752
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
41704
41753
  return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
41705
41754
  }
41706
41755
 
41707
41756
  // src/auth-store.ts
41708
- var import_node_fs28 = __toESM(require("fs"), 1);
41709
- var import_node_path28 = __toESM(require("path"), 1);
41757
+ var import_node_fs29 = __toESM(require("fs"), 1);
41758
+ var import_node_path29 = __toESM(require("path"), 1);
41710
41759
  var import_node_crypto9 = __toESM(require("crypto"), 1);
41711
41760
  var AUTH_FILE_NAME = "auth.json";
41712
41761
  function authFilePath(dataDir) {
41713
- return import_node_path28.default.join(dataDir, AUTH_FILE_NAME);
41762
+ return import_node_path29.default.join(dataDir, AUTH_FILE_NAME);
41714
41763
  }
41715
41764
  function loadOrCreateAuthFile(opts) {
41716
41765
  const file = authFilePath(opts.dataDir);
@@ -41744,7 +41793,7 @@ function defaultGenerateOwnerPrincipalId() {
41744
41793
  }
41745
41794
  function readAuthFile(file) {
41746
41795
  try {
41747
- const raw = import_node_fs28.default.readFileSync(file, "utf8");
41796
+ const raw = import_node_fs29.default.readFileSync(file, "utf8");
41748
41797
  const parsed = JSON.parse(raw);
41749
41798
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
41750
41799
  return null;
@@ -41763,25 +41812,25 @@ function readAuthFile(file) {
41763
41812
  }
41764
41813
  }
41765
41814
  function writeAuthFile(file, content) {
41766
- import_node_fs28.default.mkdirSync(import_node_path28.default.dirname(file), { recursive: true });
41767
- import_node_fs28.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
41815
+ import_node_fs29.default.mkdirSync(import_node_path29.default.dirname(file), { recursive: true });
41816
+ import_node_fs29.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
41768
41817
  try {
41769
- import_node_fs28.default.chmodSync(file, 384);
41818
+ import_node_fs29.default.chmodSync(file, 384);
41770
41819
  } catch {
41771
41820
  }
41772
41821
  }
41773
41822
 
41774
41823
  // src/owner-profile.ts
41775
- var import_node_fs29 = __toESM(require("fs"), 1);
41824
+ var import_node_fs30 = __toESM(require("fs"), 1);
41776
41825
  var import_node_os14 = __toESM(require("os"), 1);
41777
- var import_node_path29 = __toESM(require("path"), 1);
41826
+ var import_node_path30 = __toESM(require("path"), 1);
41778
41827
  var PROFILE_FILENAME = "profile.json";
41779
41828
  function loadOwnerDisplayName(dataDir) {
41780
41829
  const fallback = import_node_os14.default.userInfo().username;
41781
- const profilePath = import_node_path29.default.join(dataDir, PROFILE_FILENAME);
41830
+ const profilePath = import_node_path30.default.join(dataDir, PROFILE_FILENAME);
41782
41831
  let raw;
41783
41832
  try {
41784
- raw = import_node_fs29.default.readFileSync(profilePath, "utf8");
41833
+ raw = import_node_fs30.default.readFileSync(profilePath, "utf8");
41785
41834
  } catch {
41786
41835
  return fallback;
41787
41836
  }
@@ -41804,18 +41853,18 @@ function loadOwnerDisplayName(dataDir) {
41804
41853
  }
41805
41854
 
41806
41855
  // src/feishu-auth/owner-identity-store.ts
41807
- var import_node_fs30 = __toESM(require("fs"), 1);
41808
- var import_node_path30 = __toESM(require("path"), 1);
41856
+ var import_node_fs31 = __toESM(require("fs"), 1);
41857
+ var import_node_path31 = __toESM(require("path"), 1);
41809
41858
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
41810
41859
  var OwnerIdentityStore = class {
41811
41860
  file;
41812
41861
  constructor(dataDir) {
41813
- this.file = import_node_path30.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
41862
+ this.file = import_node_path31.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
41814
41863
  }
41815
41864
  read() {
41816
41865
  let raw;
41817
41866
  try {
41818
- raw = import_node_fs30.default.readFileSync(this.file, "utf8");
41867
+ raw = import_node_fs31.default.readFileSync(this.file, "utf8");
41819
41868
  } catch {
41820
41869
  return null;
41821
41870
  }
@@ -41843,16 +41892,16 @@ var OwnerIdentityStore = class {
41843
41892
  };
41844
41893
  }
41845
41894
  write(record) {
41846
- import_node_fs30.default.mkdirSync(import_node_path30.default.dirname(this.file), { recursive: true });
41847
- import_node_fs30.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
41895
+ import_node_fs31.default.mkdirSync(import_node_path31.default.dirname(this.file), { recursive: true });
41896
+ import_node_fs31.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
41848
41897
  try {
41849
- import_node_fs30.default.chmodSync(this.file, 384);
41898
+ import_node_fs31.default.chmodSync(this.file, 384);
41850
41899
  } catch {
41851
41900
  }
41852
41901
  }
41853
41902
  clear() {
41854
41903
  try {
41855
- import_node_fs30.default.unlinkSync(this.file);
41904
+ import_node_fs31.default.unlinkSync(this.file);
41856
41905
  } catch (err) {
41857
41906
  const code = err?.code;
41858
41907
  if (code !== "ENOENT") throw err;
@@ -41973,9 +42022,9 @@ var CentralClientError = class extends Error {
41973
42022
  code;
41974
42023
  cause;
41975
42024
  };
41976
- async function centralRequest(opts, path60, init) {
42025
+ async function centralRequest(opts, path61, init) {
41977
42026
  const f = opts.fetchImpl ?? globalThis.fetch;
41978
- const url = `${opts.api.replace(/\/+$/, "")}${path60}`;
42027
+ const url = `${opts.api.replace(/\/+$/, "")}${path61}`;
41979
42028
  const ctrl = new AbortController();
41980
42029
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
41981
42030
  let res;
@@ -42117,8 +42166,8 @@ function verifyConnectToken(args) {
42117
42166
  }
42118
42167
 
42119
42168
  // src/feishu-auth/server-key.ts
42120
- var fs39 = __toESM(require("fs"), 1);
42121
- var path39 = __toESM(require("path"), 1);
42169
+ var fs40 = __toESM(require("fs"), 1);
42170
+ var path40 = __toESM(require("path"), 1);
42122
42171
  var FILE_NAME2 = "server-signing-key.json";
42123
42172
  var ServerKeyStore = class {
42124
42173
  constructor(dataDir) {
@@ -42126,12 +42175,12 @@ var ServerKeyStore = class {
42126
42175
  }
42127
42176
  dataDir;
42128
42177
  filePath() {
42129
- return path39.join(this.dataDir, FILE_NAME2);
42178
+ return path40.join(this.dataDir, FILE_NAME2);
42130
42179
  }
42131
42180
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
42132
42181
  read() {
42133
42182
  try {
42134
- const raw = fs39.readFileSync(this.filePath(), "utf8");
42183
+ const raw = fs40.readFileSync(this.filePath(), "utf8");
42135
42184
  const parsed = JSON.parse(raw);
42136
42185
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
42137
42186
  return parsed.publicKeyPem;
@@ -42146,12 +42195,12 @@ var ServerKeyStore = class {
42146
42195
  publicKeyPem,
42147
42196
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
42148
42197
  };
42149
- fs39.mkdirSync(this.dataDir, { recursive: true });
42150
- fs39.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
42198
+ fs40.mkdirSync(this.dataDir, { recursive: true });
42199
+ fs40.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
42151
42200
  }
42152
42201
  clear() {
42153
42202
  try {
42154
- fs39.unlinkSync(this.filePath());
42203
+ fs40.unlinkSync(this.filePath());
42155
42204
  } catch {
42156
42205
  }
42157
42206
  }
@@ -42164,12 +42213,12 @@ init_protocol();
42164
42213
  init_protocol();
42165
42214
 
42166
42215
  // src/session/fork.ts
42167
- var import_node_fs31 = __toESM(require("fs"), 1);
42216
+ var import_node_fs32 = __toESM(require("fs"), 1);
42168
42217
  var import_node_os15 = __toESM(require("os"), 1);
42169
- var import_node_path31 = __toESM(require("path"), 1);
42218
+ var import_node_path32 = __toESM(require("path"), 1);
42170
42219
  init_claude_history();
42171
42220
  function readJsonlEntries(file) {
42172
- const raw = import_node_fs31.default.readFileSync(file, "utf8");
42221
+ const raw = import_node_fs32.default.readFileSync(file, "utf8");
42173
42222
  const out = [];
42174
42223
  for (const line of raw.split("\n")) {
42175
42224
  const t = line.trim();
@@ -42182,10 +42231,10 @@ function readJsonlEntries(file) {
42182
42231
  return out;
42183
42232
  }
42184
42233
  function forkSession(input) {
42185
- const baseDir = input.baseDir ?? import_node_path31.default.join(import_node_os15.default.homedir(), ".claude");
42186
- const projectDir = import_node_path31.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
42187
- const sourceFile = import_node_path31.default.join(projectDir, `${input.toolSessionId}.jsonl`);
42188
- if (!import_node_fs31.default.existsSync(sourceFile)) {
42234
+ const baseDir = input.baseDir ?? import_node_path32.default.join(import_node_os15.default.homedir(), ".claude");
42235
+ const projectDir = import_node_path32.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
42236
+ const sourceFile = import_node_path32.default.join(projectDir, `${input.toolSessionId}.jsonl`);
42237
+ if (!import_node_fs32.default.existsSync(sourceFile)) {
42189
42238
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
42190
42239
  }
42191
42240
  const entries = readJsonlEntries(sourceFile);
@@ -42215,9 +42264,9 @@ function forkSession(input) {
42215
42264
  }
42216
42265
  forkedLines.push(JSON.stringify(forked));
42217
42266
  }
42218
- const forkedFilePath = import_node_path31.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
42219
- import_node_fs31.default.mkdirSync(projectDir, { recursive: true });
42220
- import_node_fs31.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
42267
+ const forkedFilePath = import_node_path32.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
42268
+ import_node_fs32.default.mkdirSync(projectDir, { recursive: true });
42269
+ import_node_fs32.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
42221
42270
  return { forkedToolSessionId, forkedFilePath };
42222
42271
  }
42223
42272
 
@@ -42598,7 +42647,7 @@ function buildPermissionHandlers(deps) {
42598
42647
  }
42599
42648
 
42600
42649
  // src/handlers/history.ts
42601
- var path42 = __toESM(require("path"), 1);
42650
+ var path43 = __toESM(require("path"), 1);
42602
42651
  init_protocol();
42603
42652
 
42604
42653
  // src/session/recent-dirs.ts
@@ -42616,7 +42665,7 @@ function listRecentDirs(store, limit = 50) {
42616
42665
  }
42617
42666
 
42618
42667
  // src/permission/persona-paths.ts
42619
- var path41 = __toESM(require("path"), 1);
42668
+ var path42 = __toESM(require("path"), 1);
42620
42669
  function getAllowedPersonaIds(grants, action) {
42621
42670
  const ids = /* @__PURE__ */ new Set();
42622
42671
  for (const g2 of grants) {
@@ -42629,31 +42678,31 @@ function getAllowedPersonaIds(grants, action) {
42629
42678
  return ids;
42630
42679
  }
42631
42680
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
42632
- const target = path41.resolve(absPath);
42681
+ const target = path42.resolve(absPath);
42633
42682
  if (userWorkDir) {
42634
- const u = path41.resolve(userWorkDir);
42635
- const usep = u.endsWith(path41.sep) ? "" : path41.sep;
42683
+ const u = path42.resolve(userWorkDir);
42684
+ const usep = u.endsWith(path42.sep) ? "" : path42.sep;
42636
42685
  if (target === u || target.startsWith(u + usep)) return true;
42637
42686
  }
42638
- const root = path41.resolve(personaRoot);
42639
- const sep3 = root.endsWith(path41.sep) ? "" : path41.sep;
42687
+ const root = path42.resolve(personaRoot);
42688
+ const sep3 = root.endsWith(path42.sep) ? "" : path42.sep;
42640
42689
  if (!target.startsWith(root + sep3)) return false;
42641
- const rel = path41.relative(root, target);
42690
+ const rel = path42.relative(root, target);
42642
42691
  if (!rel || rel.startsWith("..")) return false;
42643
- const personaId = rel.split(path41.sep)[0];
42692
+ const personaId = rel.split(path42.sep)[0];
42644
42693
  if (!personaId) return false;
42645
42694
  const allowed = getAllowedPersonaIds(grants, action);
42646
42695
  if (allowed === "*") return true;
42647
42696
  return allowed.has(personaId);
42648
42697
  }
42649
42698
  function personaIdFromPath(absPath, personaRoot) {
42650
- const root = path41.resolve(personaRoot);
42651
- const target = path41.resolve(absPath);
42652
- const sep3 = root.endsWith(path41.sep) ? "" : path41.sep;
42699
+ const root = path42.resolve(personaRoot);
42700
+ const target = path42.resolve(absPath);
42701
+ const sep3 = root.endsWith(path42.sep) ? "" : path42.sep;
42653
42702
  if (!target.startsWith(root + sep3)) return null;
42654
- const rel = path41.relative(root, target);
42703
+ const rel = path42.relative(root, target);
42655
42704
  if (!rel || rel.startsWith("..")) return null;
42656
- const id = rel.split(path41.sep)[0];
42705
+ const id = rel.split(path42.sep)[0];
42657
42706
  return id || null;
42658
42707
  }
42659
42708
 
@@ -42680,7 +42729,7 @@ function buildHistoryHandlers(deps) {
42680
42729
  if (!pid) return false;
42681
42730
  return isGuestPathAllowed(
42682
42731
  ctx.grants,
42683
- path42.join(personaRoot, pid),
42732
+ path43.join(personaRoot, pid),
42684
42733
  personaRoot,
42685
42734
  "read",
42686
42735
  userWorkDir
@@ -42692,7 +42741,7 @@ function buildHistoryHandlers(deps) {
42692
42741
  };
42693
42742
  const list = async (frame, _client, ctx) => {
42694
42743
  const args = HistoryListArgs.parse(frame);
42695
- assertGuestPath(ctx, path42.resolve(args.projectPath), personaRoot, "history:list");
42744
+ assertGuestPath(ctx, path43.resolve(args.projectPath), personaRoot, "history:list");
42696
42745
  const sessions = await history.listSessions(args);
42697
42746
  return { response: { type: "history:list", sessions } };
42698
42747
  };
@@ -42724,13 +42773,13 @@ function buildHistoryHandlers(deps) {
42724
42773
  };
42725
42774
  const subagents = async (frame, _client, ctx) => {
42726
42775
  const args = HistorySubagentsArgs.parse(frame);
42727
- assertGuestPath(ctx, path42.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
42776
+ assertGuestPath(ctx, path43.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
42728
42777
  const subs = await history.listSubagents(args);
42729
42778
  return { response: { type: "history:subagents", subagents: subs } };
42730
42779
  };
42731
42780
  const subagentRead = async (frame, _client, ctx) => {
42732
42781
  const args = HistorySubagentReadArgs.parse(frame);
42733
- assertGuestPath(ctx, path42.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
42782
+ assertGuestPath(ctx, path43.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
42734
42783
  const res = await history.readSubagent(args);
42735
42784
  return { response: { type: "history:subagent-read", ...res } };
42736
42785
  };
@@ -42739,7 +42788,7 @@ function buildHistoryHandlers(deps) {
42739
42788
  if (ctx?.principal.kind === "guest" && personaRoot) {
42740
42789
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
42741
42790
  const filtered = dirs.filter(
42742
- (d) => isGuestPathAllowed(ctx.grants, path42.resolve(d.cwd), personaRoot, "read", userWorkDir)
42791
+ (d) => isGuestPathAllowed(ctx.grants, path43.resolve(d.cwd), personaRoot, "read", userWorkDir)
42743
42792
  );
42744
42793
  return { response: { type: "history:recentDirs", dirs: filtered } };
42745
42794
  }
@@ -42756,7 +42805,7 @@ function buildHistoryHandlers(deps) {
42756
42805
  }
42757
42806
 
42758
42807
  // src/handlers/workspace.ts
42759
- var path43 = __toESM(require("path"), 1);
42808
+ var path44 = __toESM(require("path"), 1);
42760
42809
  var os15 = __toESM(require("os"), 1);
42761
42810
  init_protocol();
42762
42811
  init_protocol();
@@ -42798,22 +42847,22 @@ function buildWorkspaceHandlers(deps) {
42798
42847
  const args = WorkspaceListArgs.parse(frame);
42799
42848
  const isGuest = ctx?.principal.kind === "guest";
42800
42849
  const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
42801
- const resolvedCwd = path43.resolve(args.cwd ?? fallbackCwd);
42802
- const target = args.path ? path43.resolve(resolvedCwd, args.path) : resolvedCwd;
42850
+ const resolvedCwd = path44.resolve(args.cwd ?? fallbackCwd);
42851
+ const target = args.path ? path44.resolve(resolvedCwd, args.path) : resolvedCwd;
42803
42852
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
42804
42853
  const res = workspace.list({ ...args, cwd: resolvedCwd });
42805
42854
  return { response: { type: "workspace:list", ...res } };
42806
42855
  };
42807
42856
  const read = async (frame, _client, ctx) => {
42808
42857
  const args = WorkspaceReadArgs.parse(frame);
42809
- const target = path43.isAbsolute(args.path) ? path43.resolve(args.path) : path43.resolve(args.cwd, args.path);
42858
+ const target = path44.isAbsolute(args.path) ? path44.resolve(args.path) : path44.resolve(args.cwd, args.path);
42810
42859
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
42811
42860
  const res = workspace.read(args);
42812
42861
  return { response: { type: "workspace:read", ...res } };
42813
42862
  };
42814
42863
  const skillsList = async (frame, _client, ctx) => {
42815
42864
  const args = SkillsListArgs.parse(frame);
42816
- const cwdAbs = path43.resolve(args.cwd);
42865
+ const cwdAbs = path44.resolve(args.cwd);
42817
42866
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
42818
42867
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
42819
42868
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -42825,7 +42874,7 @@ function buildWorkspaceHandlers(deps) {
42825
42874
  };
42826
42875
  const agentsList = async (frame, _client, ctx) => {
42827
42876
  const args = AgentsListArgs.parse(frame);
42828
- const cwdAbs = path43.resolve(args.cwd);
42877
+ const cwdAbs = path44.resolve(args.cwd);
42829
42878
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
42830
42879
  if (args.tool === "codex") {
42831
42880
  return { response: { type: "agents:list", agents: [] } };
@@ -42847,20 +42896,20 @@ function buildWorkspaceHandlers(deps) {
42847
42896
  }
42848
42897
 
42849
42898
  // src/handlers/git.ts
42850
- var path45 = __toESM(require("path"), 1);
42899
+ var path46 = __toESM(require("path"), 1);
42851
42900
  init_protocol();
42852
42901
  init_protocol();
42853
42902
 
42854
42903
  // src/workspace/git.ts
42855
42904
  var import_node_child_process10 = require("child_process");
42856
- var import_node_fs32 = __toESM(require("fs"), 1);
42857
- var import_node_path32 = __toESM(require("path"), 1);
42905
+ var import_node_fs33 = __toESM(require("fs"), 1);
42906
+ var import_node_path33 = __toESM(require("path"), 1);
42858
42907
  var import_node_util = require("util");
42859
42908
  var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
42860
42909
  function normalizePath(p2) {
42861
- const resolved = import_node_path32.default.resolve(p2);
42910
+ const resolved = import_node_path33.default.resolve(p2);
42862
42911
  try {
42863
- return import_node_fs32.default.realpathSync(resolved);
42912
+ return import_node_fs33.default.realpathSync(resolved);
42864
42913
  } catch {
42865
42914
  return resolved;
42866
42915
  }
@@ -42934,7 +42983,7 @@ async function listGitBranches(cwd) {
42934
42983
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
42935
42984
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
42936
42985
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
42937
- if (!isGuestPathAllowed(ctx.grants, path45.resolve(cwd), personaRoot, "read", userWorkDir)) {
42986
+ if (!isGuestPathAllowed(ctx.grants, path46.resolve(cwd), personaRoot, "read", userWorkDir)) {
42938
42987
  throw new ClawdError(
42939
42988
  ERROR_CODES.UNAUTHORIZED,
42940
42989
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -43451,7 +43500,7 @@ function buildPersonaHandlers(deps) {
43451
43500
  }
43452
43501
 
43453
43502
  // src/handlers/attachment.ts
43454
- var import_node_path33 = __toESM(require("path"), 1);
43503
+ var import_node_path34 = __toESM(require("path"), 1);
43455
43504
  init_protocol();
43456
43505
  init_protocol();
43457
43506
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -43506,12 +43555,12 @@ function buildAttachmentHandlers(deps) {
43506
43555
  `session ${args.sessionId} scope unresolved`
43507
43556
  );
43508
43557
  }
43509
- const cwdAbs = import_node_path33.default.resolve(sessionFile.cwd);
43510
- const candidateAbs = import_node_path33.default.isAbsolute(args.relPath) ? import_node_path33.default.resolve(args.relPath) : import_node_path33.default.resolve(cwdAbs, args.relPath);
43558
+ const cwdAbs = import_node_path34.default.resolve(sessionFile.cwd);
43559
+ const candidateAbs = import_node_path34.default.isAbsolute(args.relPath) ? import_node_path34.default.resolve(args.relPath) : import_node_path34.default.resolve(cwdAbs, args.relPath);
43511
43560
  assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl", deps.usersRoot);
43512
43561
  const entries = deps.groupFileStore.list(scope, args.sessionId);
43513
43562
  const entry = entries.find((e) => {
43514
- const storedAbs = import_node_path33.default.isAbsolute(e.relPath) ? import_node_path33.default.resolve(e.relPath) : import_node_path33.default.resolve(cwdAbs, e.relPath);
43563
+ const storedAbs = import_node_path34.default.isAbsolute(e.relPath) ? import_node_path34.default.resolve(e.relPath) : import_node_path34.default.resolve(cwdAbs, e.relPath);
43515
43564
  return storedAbs === candidateAbs && !e.stale;
43516
43565
  });
43517
43566
  if (!entry) {
@@ -43536,7 +43585,7 @@ function buildAttachmentHandlers(deps) {
43536
43585
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
43537
43586
  const f = deps.sessionStore.read(sessionId);
43538
43587
  if (!f) return;
43539
- assertGuestAttachmentPath(ctx, import_node_path33.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
43588
+ assertGuestAttachmentPath(ctx, import_node_path34.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
43540
43589
  }
43541
43590
  const groupAdd = async (frame, _client, ctx) => {
43542
43591
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -43608,19 +43657,19 @@ function buildAttachmentHandlers(deps) {
43608
43657
 
43609
43658
  // src/handlers/extension.ts
43610
43659
  var import_promises7 = __toESM(require("fs/promises"), 1);
43611
- var import_node_path38 = __toESM(require("path"), 1);
43660
+ var import_node_path39 = __toESM(require("path"), 1);
43612
43661
  init_protocol();
43613
43662
 
43614
43663
  // src/extension/bundle-zip.ts
43615
43664
  var import_promises4 = __toESM(require("fs/promises"), 1);
43616
- var import_node_path34 = __toESM(require("path"), 1);
43665
+ var import_node_path35 = __toESM(require("path"), 1);
43617
43666
  var import_node_crypto11 = __toESM(require("crypto"), 1);
43618
43667
  var import_jszip2 = __toESM(require_lib3(), 1);
43619
43668
  async function bundleExtensionDir(dir) {
43620
43669
  const entries = await listFilesSorted(dir);
43621
43670
  const zip = new import_jszip2.default();
43622
43671
  for (const rel of entries) {
43623
- const abs = import_node_path34.default.join(dir, rel);
43672
+ const abs = import_node_path35.default.join(dir, rel);
43624
43673
  const content = await import_promises4.default.readFile(abs);
43625
43674
  zip.file(rel, content, { date: FIXED_DATE });
43626
43675
  }
@@ -43641,7 +43690,7 @@ async function listFilesSorted(rootDir) {
43641
43690
  return out;
43642
43691
  }
43643
43692
  async function walk(absRoot, relPrefix, out) {
43644
- const dirAbs = import_node_path34.default.join(absRoot, relPrefix);
43693
+ const dirAbs = import_node_path35.default.join(absRoot, relPrefix);
43645
43694
  const entries = await import_promises4.default.readdir(dirAbs, { withFileTypes: true });
43646
43695
  for (const e of entries) {
43647
43696
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -43695,25 +43744,25 @@ function computePublishCheck(args) {
43695
43744
 
43696
43745
  // src/extension/install-flow.ts
43697
43746
  var import_promises5 = __toESM(require("fs/promises"), 1);
43698
- var import_node_path36 = __toESM(require("path"), 1);
43747
+ var import_node_path37 = __toESM(require("path"), 1);
43699
43748
  var import_node_os18 = __toESM(require("os"), 1);
43700
43749
  var import_node_crypto12 = __toESM(require("crypto"), 1);
43701
43750
  var import_jszip3 = __toESM(require_lib3(), 1);
43702
43751
 
43703
43752
  // src/extension/paths.ts
43704
43753
  var import_node_os17 = __toESM(require("os"), 1);
43705
- var import_node_path35 = __toESM(require("path"), 1);
43754
+ var import_node_path36 = __toESM(require("path"), 1);
43706
43755
  function clawdHomeRoot(override) {
43707
- return override ?? process.env.CLAWD_HOME ?? import_node_path35.default.join(import_node_os17.default.homedir(), ".clawd");
43756
+ return override ?? process.env.CLAWD_HOME ?? import_node_path36.default.join(import_node_os17.default.homedir(), ".clawd");
43708
43757
  }
43709
43758
  function extensionsRoot(override) {
43710
- return import_node_path35.default.join(clawdHomeRoot(override), "extensions");
43759
+ return import_node_path36.default.join(clawdHomeRoot(override), "extensions");
43711
43760
  }
43712
43761
  function publishedChannelsFile(override) {
43713
- return import_node_path35.default.join(clawdHomeRoot(override), "extensions-published.json");
43762
+ return import_node_path36.default.join(clawdHomeRoot(override), "extensions-published.json");
43714
43763
  }
43715
43764
  function bundleCacheRoot(override) {
43716
- return import_node_path35.default.join(clawdHomeRoot(override), "extension-bundles");
43765
+ return import_node_path36.default.join(clawdHomeRoot(override), "extension-bundles");
43717
43766
  }
43718
43767
 
43719
43768
  // src/extension/install-flow.ts
@@ -43740,7 +43789,7 @@ async function installFromChannel(args, deps) {
43740
43789
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
43741
43790
  }
43742
43791
  for (const name of Object.keys(zip.files)) {
43743
- if (name.includes("..") || name.startsWith("/") || import_node_path36.default.isAbsolute(name)) {
43792
+ if (name.includes("..") || name.startsWith("/") || import_node_path37.default.isAbsolute(name)) {
43744
43793
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
43745
43794
  }
43746
43795
  }
@@ -43772,7 +43821,7 @@ async function installFromChannel(args, deps) {
43772
43821
  );
43773
43822
  }
43774
43823
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
43775
- const destDir = import_node_path36.default.join(deps.extensionsRoot, localExtId);
43824
+ const destDir = import_node_path37.default.join(deps.extensionsRoot, localExtId);
43776
43825
  let destExists = false;
43777
43826
  try {
43778
43827
  await import_promises5.default.access(destDir);
@@ -43786,16 +43835,16 @@ async function installFromChannel(args, deps) {
43786
43835
  );
43787
43836
  }
43788
43837
  const stage = await import_promises5.default.mkdtemp(
43789
- import_node_path36.default.join(import_node_os18.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
43838
+ import_node_path37.default.join(import_node_os18.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
43790
43839
  );
43791
43840
  try {
43792
43841
  for (const [name, entry] of Object.entries(zip.files)) {
43793
- const dest = import_node_path36.default.join(stage, name);
43842
+ const dest = import_node_path37.default.join(stage, name);
43794
43843
  if (entry.dir) {
43795
43844
  await import_promises5.default.mkdir(dest, { recursive: true });
43796
43845
  continue;
43797
43846
  }
43798
- await import_promises5.default.mkdir(import_node_path36.default.dirname(dest), { recursive: true });
43847
+ await import_promises5.default.mkdir(import_node_path37.default.dirname(dest), { recursive: true });
43799
43848
  if (name === "manifest.json") {
43800
43849
  const rewritten = { ...parsed.data, id: localExtId };
43801
43850
  await import_promises5.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -43816,7 +43865,7 @@ async function installFromChannel(args, deps) {
43816
43865
 
43817
43866
  // src/extension/update-flow.ts
43818
43867
  var import_promises6 = __toESM(require("fs/promises"), 1);
43819
- var import_node_path37 = __toESM(require("path"), 1);
43868
+ var import_node_path38 = __toESM(require("path"), 1);
43820
43869
  var import_node_os19 = __toESM(require("os"), 1);
43821
43870
  var import_node_crypto13 = __toESM(require("crypto"), 1);
43822
43871
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -43833,11 +43882,11 @@ async function updateFromChannel(args, deps) {
43833
43882
  channelRef.extId,
43834
43883
  channelRef.ownerPrincipalId
43835
43884
  );
43836
- const liveDir = import_node_path37.default.join(deps.extensionsRoot, localExtId);
43885
+ const liveDir = import_node_path38.default.join(deps.extensionsRoot, localExtId);
43837
43886
  const prevDir = `${liveDir}.prev`;
43838
43887
  let existingVersion;
43839
43888
  try {
43840
- const raw = await import_promises6.default.readFile(import_node_path37.default.join(liveDir, "manifest.json"), "utf8");
43889
+ const raw = await import_promises6.default.readFile(import_node_path38.default.join(liveDir, "manifest.json"), "utf8");
43841
43890
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
43842
43891
  if (!parsed2.success) {
43843
43892
  throw new UpdateError(
@@ -43870,7 +43919,7 @@ async function updateFromChannel(args, deps) {
43870
43919
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
43871
43920
  }
43872
43921
  for (const name of Object.keys(zip.files)) {
43873
- if (name.includes("..") || name.startsWith("/") || import_node_path37.default.isAbsolute(name)) {
43922
+ if (name.includes("..") || name.startsWith("/") || import_node_path38.default.isAbsolute(name)) {
43874
43923
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
43875
43924
  }
43876
43925
  }
@@ -43905,16 +43954,16 @@ async function updateFromChannel(args, deps) {
43905
43954
  await import_promises6.default.rm(prevDir, { recursive: true, force: true });
43906
43955
  await import_promises6.default.rename(liveDir, prevDir);
43907
43956
  const stage = await import_promises6.default.mkdtemp(
43908
- import_node_path37.default.join(import_node_os19.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
43957
+ import_node_path38.default.join(import_node_os19.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
43909
43958
  );
43910
43959
  try {
43911
43960
  for (const [name, entry] of Object.entries(zip.files)) {
43912
- const dest = import_node_path37.default.join(stage, name);
43961
+ const dest = import_node_path38.default.join(stage, name);
43913
43962
  if (entry.dir) {
43914
43963
  await import_promises6.default.mkdir(dest, { recursive: true });
43915
43964
  continue;
43916
43965
  }
43917
- await import_promises6.default.mkdir(import_node_path37.default.dirname(dest), { recursive: true });
43966
+ await import_promises6.default.mkdir(import_node_path38.default.dirname(dest), { recursive: true });
43918
43967
  if (name === "manifest.json") {
43919
43968
  const rewritten = { ...parsed.data, id: localExtId };
43920
43969
  await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -44007,7 +44056,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
44007
44056
  );
44008
44057
  }
44009
44058
  }
44010
- const manifestPath = import_node_path38.default.join(root, extId, "manifest.json");
44059
+ const manifestPath = import_node_path39.default.join(root, extId, "manifest.json");
44011
44060
  const manifest = await readManifest(root, extId);
44012
44061
  const next = { ...manifest, version: newVersion };
44013
44062
  const tmp = `${manifestPath}.tmp`;
@@ -44015,7 +44064,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
44015
44064
  await import_promises7.default.rename(tmp, manifestPath);
44016
44065
  }
44017
44066
  async function readManifest(root, extId) {
44018
- const file = import_node_path38.default.join(root, extId, "manifest.json");
44067
+ const file = import_node_path39.default.join(root, extId, "manifest.json");
44019
44068
  let raw;
44020
44069
  try {
44021
44070
  raw = await import_promises7.default.readFile(file, "utf8");
@@ -44106,7 +44155,7 @@ function buildExtensionHandlers(deps) {
44106
44155
  };
44107
44156
  async function buildSnapshotMeta(extId) {
44108
44157
  const manifest = await readManifest(deps.root, extId);
44109
- const { sha256, buffer } = await bundleExtensionDir(import_node_path38.default.join(deps.root, extId));
44158
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path39.default.join(deps.root, extId));
44110
44159
  return { manifest, contentHash: sha256, buffer };
44111
44160
  }
44112
44161
  const publish = async (frame, _client, ctx) => {
@@ -44287,9 +44336,9 @@ function buildExtensionHandlers(deps) {
44287
44336
  }
44288
44337
 
44289
44338
  // src/app-builder/project-store.ts
44290
- var import_node_fs33 = require("fs");
44339
+ var import_node_fs34 = require("fs");
44291
44340
  var import_node_child_process11 = require("child_process");
44292
- var import_node_path39 = require("path");
44341
+ var import_node_path40 = require("path");
44293
44342
  init_protocol();
44294
44343
  var PROJECTS_DIR = "projects";
44295
44344
  var META_FILE = ".clawd-project.json";
@@ -44303,19 +44352,19 @@ var ProjectStore = class {
44303
44352
  root;
44304
44353
  /** projects/<name>/.clawd-project.json 路径 */
44305
44354
  metaPath(name) {
44306
- return (0, import_node_path39.join)(this.projectsRoot(), name, META_FILE);
44355
+ return (0, import_node_path40.join)(this.projectsRoot(), name, META_FILE);
44307
44356
  }
44308
44357
  /** projects/<name>/ 目录路径(cwd 用) */
44309
44358
  projectDir(name) {
44310
- return (0, import_node_path39.join)(this.projectsRoot(), name);
44359
+ return (0, import_node_path40.join)(this.projectsRoot(), name);
44311
44360
  }
44312
44361
  projectsRoot() {
44313
- return (0, import_node_path39.join)(this.root, PROJECTS_DIR);
44362
+ return (0, import_node_path40.join)(this.root, PROJECTS_DIR);
44314
44363
  }
44315
44364
  async list() {
44316
44365
  let entries;
44317
44366
  try {
44318
- entries = await import_node_fs33.promises.readdir(this.projectsRoot());
44367
+ entries = await import_node_fs34.promises.readdir(this.projectsRoot());
44319
44368
  } catch (err) {
44320
44369
  if (err.code === "ENOENT") return [];
44321
44370
  throw err;
@@ -44323,7 +44372,7 @@ var ProjectStore = class {
44323
44372
  const out = [];
44324
44373
  for (const name of entries) {
44325
44374
  try {
44326
- const raw = await import_node_fs33.promises.readFile(this.metaPath(name), "utf8");
44375
+ const raw = await import_node_fs34.promises.readFile(this.metaPath(name), "utf8");
44327
44376
  const json = JSON.parse(raw);
44328
44377
  let migrated = false;
44329
44378
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -44334,7 +44383,7 @@ var ProjectStore = class {
44334
44383
  if (parsed.success) {
44335
44384
  out.push(parsed.data);
44336
44385
  if (migrated) {
44337
- void import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
44386
+ void import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
44338
44387
  });
44339
44388
  }
44340
44389
  }
@@ -44378,8 +44427,8 @@ var ProjectStore = class {
44378
44427
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
44379
44428
  }
44380
44429
  const dir = this.projectDir(name);
44381
- await import_node_fs33.promises.mkdir(dir, { recursive: true });
44382
- await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
44430
+ await import_node_fs34.promises.mkdir(dir, { recursive: true });
44431
+ await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
44383
44432
  return meta;
44384
44433
  }
44385
44434
  /**
@@ -44422,7 +44471,7 @@ var ProjectStore = class {
44422
44471
  }
44423
44472
  async delete(name) {
44424
44473
  const dir = this.projectDir(name);
44425
- await import_node_fs33.promises.rm(dir, { recursive: true, force: true });
44474
+ await import_node_fs34.promises.rm(dir, { recursive: true, force: true });
44426
44475
  }
44427
44476
  async updatePort(name, newPort) {
44428
44477
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -44438,7 +44487,7 @@ var ProjectStore = class {
44438
44487
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
44439
44488
  }
44440
44489
  const updated = { ...target, port: newPort };
44441
- await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
44490
+ await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
44442
44491
  return updated;
44443
44492
  }
44444
44493
  /**
@@ -44455,7 +44504,7 @@ var ProjectStore = class {
44455
44504
  if (!validated.success) {
44456
44505
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
44457
44506
  }
44458
- await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44507
+ await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44459
44508
  return validated.data;
44460
44509
  }
44461
44510
  /**
@@ -44476,7 +44525,7 @@ var ProjectStore = class {
44476
44525
  if (!validated.success) {
44477
44526
  throw new Error(`invalid publishJob: ${validated.error.message}`);
44478
44527
  }
44479
- await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44528
+ await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44480
44529
  return validated.data;
44481
44530
  }
44482
44531
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -44491,7 +44540,7 @@ var ProjectStore = class {
44491
44540
  if (!validated.success) {
44492
44541
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
44493
44542
  }
44494
- await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44543
+ await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44495
44544
  return validated.data;
44496
44545
  }
44497
44546
  };
@@ -44612,8 +44661,8 @@ var PublishJobRegistry = class {
44612
44661
 
44613
44662
  // src/app-builder/publish-job-runner.ts
44614
44663
  var import_node_child_process13 = require("child_process");
44615
- var import_node_fs34 = require("fs");
44616
- var import_node_path40 = require("path");
44664
+ var import_node_fs35 = require("fs");
44665
+ var import_node_path41 = require("path");
44617
44666
 
44618
44667
  // src/app-builder/publish-stage-parser.ts
44619
44668
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -44645,10 +44694,10 @@ async function startPublishJob(deps, args) {
44645
44694
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
44646
44695
  }
44647
44696
  const projDir = projectDir(args.name);
44648
- const logPath = (0, import_node_path40.join)(projDir, ".publish.log");
44697
+ const logPath = (0, import_node_path41.join)(projDir, ".publish.log");
44649
44698
  let logStream = null;
44650
44699
  try {
44651
- logStream = (0, import_node_fs34.createWriteStream)(logPath, { flags: "w" });
44700
+ logStream = (0, import_node_fs35.createWriteStream)(logPath, { flags: "w" });
44652
44701
  } catch {
44653
44702
  logStream = null;
44654
44703
  }
@@ -44905,8 +44954,8 @@ async function recoverInterruptedJobs(deps) {
44905
44954
 
44906
44955
  // src/handlers/app-builder.ts
44907
44956
  init_protocol();
44908
- var import_node_path41 = require("path");
44909
- var import_node_fs35 = require("fs");
44957
+ var import_node_path42 = require("path");
44958
+ var import_node_fs36 = require("fs");
44910
44959
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
44911
44960
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
44912
44961
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -44987,7 +45036,7 @@ function buildAppBuilderHandlers(deps) {
44987
45036
  async function listAllUsersProjects() {
44988
45037
  if (!deps.usersRoot || !deps.getStore) return [];
44989
45038
  const getStore = deps.getStore;
44990
- const userIds = await import_node_fs35.promises.readdir(deps.usersRoot).catch(() => []);
45039
+ const userIds = await import_node_fs36.promises.readdir(deps.usersRoot).catch(() => []);
44991
45040
  const perUser = await Promise.all(
44992
45041
  userIds.map((uid) => getStore(uid).list().catch(() => []))
44993
45042
  );
@@ -45063,8 +45112,8 @@ function buildAppBuilderHandlers(deps) {
45063
45112
  const project = await userStore.create(f.name, reservedPorts);
45064
45113
  try {
45065
45114
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
45066
- const templateSrcDir = (0, import_node_path41.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
45067
- const scaffoldScript = (0, import_node_path41.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
45115
+ const templateSrcDir = (0, import_node_path42.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
45116
+ const scaffoldScript = (0, import_node_path42.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
45068
45117
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
45069
45118
  deps.logger?.info("app-builder.scaffold.done", {
45070
45119
  name: project.name,
@@ -45285,7 +45334,7 @@ function buildAppBuilderHandlers(deps) {
45285
45334
  await userStore.clearPublishJob(args.name);
45286
45335
  }
45287
45336
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
45288
- const scriptPath = (0, import_node_path41.join)(deps.deployKitRoot, "scripts", "publish.sh");
45337
+ const scriptPath = (0, import_node_path42.join)(deps.deployKitRoot, "scripts", "publish.sh");
45289
45338
  deps.logger?.info("app-builder.publish.start", {
45290
45339
  name: args.name,
45291
45340
  sessionId: boundSession.sessionId,
@@ -45381,7 +45430,7 @@ function buildAppBuilderHandlers(deps) {
45381
45430
 
45382
45431
  // src/extension/registry.ts
45383
45432
  var import_promises8 = __toESM(require("fs/promises"), 1);
45384
- var import_node_path42 = __toESM(require("path"), 1);
45433
+ var import_node_path43 = __toESM(require("path"), 1);
45385
45434
  async function loadAll(root) {
45386
45435
  let entries;
45387
45436
  try {
@@ -45394,13 +45443,13 @@ async function loadAll(root) {
45394
45443
  for (const ent of entries) {
45395
45444
  if (!ent.isDirectory()) continue;
45396
45445
  if (ent.name.startsWith(".")) continue;
45397
- records.push(await loadOne(import_node_path42.default.join(root, ent.name), ent.name));
45446
+ records.push(await loadOne(import_node_path43.default.join(root, ent.name), ent.name));
45398
45447
  }
45399
45448
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
45400
45449
  return records;
45401
45450
  }
45402
45451
  async function loadOne(dir, dirName) {
45403
- const manifestPath = import_node_path42.default.join(dir, "manifest.json");
45452
+ const manifestPath = import_node_path43.default.join(dir, "manifest.json");
45404
45453
  let raw;
45405
45454
  try {
45406
45455
  raw = await import_promises8.default.readFile(manifestPath, "utf8");
@@ -45445,7 +45494,7 @@ async function loadOne(dir, dirName) {
45445
45494
 
45446
45495
  // src/extension/uninstall.ts
45447
45496
  var import_promises9 = __toESM(require("fs/promises"), 1);
45448
- var import_node_path43 = __toESM(require("path"), 1);
45497
+ var import_node_path44 = __toESM(require("path"), 1);
45449
45498
  var UninstallError = class extends Error {
45450
45499
  constructor(code, message) {
45451
45500
  super(message);
@@ -45454,7 +45503,7 @@ var UninstallError = class extends Error {
45454
45503
  code;
45455
45504
  };
45456
45505
  async function uninstall(deps) {
45457
- const dir = import_node_path43.default.join(deps.root, deps.extId);
45506
+ const dir = import_node_path44.default.join(deps.root, deps.extId);
45458
45507
  try {
45459
45508
  await import_promises9.default.access(dir);
45460
45509
  } catch {
@@ -45965,7 +46014,7 @@ function computeGrantForFrame(method, frame) {
45965
46014
 
45966
46015
  // src/extension/runtime.ts
45967
46016
  var import_node_child_process15 = require("child_process");
45968
- var import_node_path44 = __toESM(require("path"), 1);
46017
+ var import_node_path45 = __toESM(require("path"), 1);
45969
46018
  var import_promises10 = require("timers/promises");
45970
46019
 
45971
46020
  // src/extension/port-allocator.ts
@@ -46066,7 +46115,7 @@ var Runtime = class {
46066
46115
  /\$CLAWOS_EXT_PORT/g,
46067
46116
  String(port)
46068
46117
  );
46069
- const dir = import_node_path44.default.join(this.root, extId);
46118
+ const dir = import_node_path45.default.join(this.root, extId);
46070
46119
  const env = {
46071
46120
  ...process.env,
46072
46121
  CLAWOS_EXT_PORT: String(port),
@@ -46178,7 +46227,7 @@ ${handle.stderrTail}`
46178
46227
 
46179
46228
  // src/extension/published-channels.ts
46180
46229
  var import_promises11 = __toESM(require("fs/promises"), 1);
46181
- var import_node_path45 = __toESM(require("path"), 1);
46230
+ var import_node_path46 = __toESM(require("path"), 1);
46182
46231
  init_zod();
46183
46232
  var PublishedChannelsError = class extends Error {
46184
46233
  constructor(code, message) {
@@ -46277,7 +46326,7 @@ var PublishedChannelStore = class {
46277
46326
  )
46278
46327
  };
46279
46328
  const tmp = `${this.filePath}.tmp`;
46280
- await import_promises11.default.mkdir(import_node_path45.default.dirname(this.filePath), { recursive: true });
46329
+ await import_promises11.default.mkdir(import_node_path46.default.dirname(this.filePath), { recursive: true });
46281
46330
  await import_promises11.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
46282
46331
  await import_promises11.default.rename(tmp, this.filePath);
46283
46332
  }
@@ -46285,7 +46334,7 @@ var PublishedChannelStore = class {
46285
46334
 
46286
46335
  // src/extension/bundle-cache.ts
46287
46336
  var import_promises12 = __toESM(require("fs/promises"), 1);
46288
- var import_node_path46 = __toESM(require("path"), 1);
46337
+ var import_node_path47 = __toESM(require("path"), 1);
46289
46338
  var BundleCache = class {
46290
46339
  constructor(rootDir) {
46291
46340
  this.rootDir = rootDir;
@@ -46294,14 +46343,14 @@ var BundleCache = class {
46294
46343
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
46295
46344
  async write(snapshotHash, buffer) {
46296
46345
  await import_promises12.default.mkdir(this.rootDir, { recursive: true });
46297
- const file = import_node_path46.default.join(this.rootDir, `${snapshotHash}.zip`);
46346
+ const file = import_node_path47.default.join(this.rootDir, `${snapshotHash}.zip`);
46298
46347
  const tmp = `${file}.tmp`;
46299
46348
  await import_promises12.default.writeFile(tmp, buffer, { mode: 384 });
46300
46349
  await import_promises12.default.rename(tmp, file);
46301
46350
  }
46302
46351
  /** Returns the bundle bytes, or null when the file doesn't exist. */
46303
46352
  async read(snapshotHash) {
46304
- const file = import_node_path46.default.join(this.rootDir, `${snapshotHash}.zip`);
46353
+ const file = import_node_path47.default.join(this.rootDir, `${snapshotHash}.zip`);
46305
46354
  try {
46306
46355
  return await import_promises12.default.readFile(file);
46307
46356
  } catch (e) {
@@ -46311,7 +46360,7 @@ var BundleCache = class {
46311
46360
  }
46312
46361
  /** Idempotent — missing file is not an error. */
46313
46362
  async delete(snapshotHash) {
46314
- const file = import_node_path46.default.join(this.rootDir, `${snapshotHash}.zip`);
46363
+ const file = import_node_path47.default.join(this.rootDir, `${snapshotHash}.zip`);
46315
46364
  await import_promises12.default.rm(file, { force: true });
46316
46365
  }
46317
46366
  };
@@ -46336,7 +46385,7 @@ async function startDaemon(config) {
46336
46385
  });
46337
46386
  const logger = createLogger({
46338
46387
  level: config.logLevel,
46339
- file: import_node_path47.default.join(config.dataDir, "clawd.log"),
46388
+ file: import_node_path48.default.join(config.dataDir, "clawd.log"),
46340
46389
  logClient
46341
46390
  });
46342
46391
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
@@ -46472,8 +46521,8 @@ async function startDaemon(config) {
46472
46521
  const agents = new AgentsScanner();
46473
46522
  const history = new ClaudeHistoryReader();
46474
46523
  let transport = null;
46475
- const personaStore = new PersonaStore(import_node_path47.default.join(config.dataDir, "personas"));
46476
- const usersRoot = import_node_path47.default.join(config.dataDir, "users");
46524
+ const personaStore = new PersonaStore(import_node_path48.default.join(config.dataDir, "personas"));
46525
+ const usersRoot = import_node_path48.default.join(config.dataDir, "users");
46477
46526
  const defaultsRoot = findDefaultsRoot(logger);
46478
46527
  if (defaultsRoot) {
46479
46528
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -46493,17 +46542,17 @@ async function startDaemon(config) {
46493
46542
  migrateCodexSandbox({ store: personaStore, logger });
46494
46543
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
46495
46544
  const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
46496
- const here = typeof __dirname === "string" ? __dirname : import_node_path47.default.dirname((0, import_node_url3.fileURLToPath)(import_meta5.url));
46545
+ const here = typeof __dirname === "string" ? __dirname : import_node_path48.default.dirname((0, import_node_url3.fileURLToPath)(import_meta5.url));
46497
46546
  const dispatchServerCandidates = [
46498
- import_node_path47.default.join(here, "dispatch", "mcp-server.cjs"),
46547
+ import_node_path48.default.join(here, "dispatch", "mcp-server.cjs"),
46499
46548
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
46500
- import_node_path47.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
46549
+ import_node_path48.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
46501
46550
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
46502
46551
  ];
46503
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs36.default.existsSync(p2));
46552
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs37.default.existsSync(p2));
46504
46553
  let dispatchMcpConfigPath2;
46505
46554
  if (dispatchServerScriptPath) {
46506
- const dispatchLogPath = import_node_path47.default.join(config.dataDir, "dispatch-mcp-server.log");
46555
+ const dispatchLogPath = import_node_path48.default.join(config.dataDir, "dispatch-mcp-server.log");
46507
46556
  dispatchMcpConfigPath2 = writeDispatchMcpConfig({
46508
46557
  dataDir: config.dataDir,
46509
46558
  serverScriptPath: dispatchServerScriptPath,
@@ -46519,6 +46568,29 @@ async function startDaemon(config) {
46519
46568
  tried: dispatchServerCandidates
46520
46569
  });
46521
46570
  }
46571
+ const ticketServerCandidates = [
46572
+ import_node_path48.default.join(here, "ticket", "mcp-server.cjs"),
46573
+ import_node_path48.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
46574
+ ];
46575
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs37.default.existsSync(p2));
46576
+ const ticketOwnerUnionId = feishuIdentity?.identity.unionId ?? "";
46577
+ const ticketOwnerName = feishuIdentity?.identity.displayName ?? "";
46578
+ let ticketMcpConfigPath2;
46579
+ if (ticketServerScriptPath && ticketOwnerUnionId) {
46580
+ ticketMcpConfigPath2 = writeTicketMcpConfig({
46581
+ dataDir: config.dataDir,
46582
+ serverScriptPath: ticketServerScriptPath,
46583
+ apiBaseUrl: config.clawosApi ?? DEFAULT_CLAWOS_API,
46584
+ apiKey: resolveClawdTicketsApiKey(),
46585
+ ownerUnionId: ticketOwnerUnionId,
46586
+ ownerName: ticketOwnerName
46587
+ });
46588
+ logger.info("ticket.mcp.json written", { path: ticketMcpConfigPath2 });
46589
+ } else {
46590
+ logger.warn("ticket-mcp skipped", {
46591
+ reason: !ticketOwnerUnionId ? "feishu unionId missing (login required)" : "ticket-mcp-server.cjs not found (need build)"
46592
+ });
46593
+ }
46522
46594
  const manager = new SessionManager({
46523
46595
  store,
46524
46596
  // Phase 2 (capability platform plan §1): factory 注入后 manager.storeFor 走
@@ -46528,7 +46600,7 @@ async function startDaemon(config) {
46528
46600
  getAdapter,
46529
46601
  historyReader: history,
46530
46602
  dataDir: config.dataDir,
46531
- personaRoot: import_node_path47.default.join(config.dataDir, "personas"),
46603
+ personaRoot: import_node_path48.default.join(config.dataDir, "personas"),
46532
46604
  usersRoot,
46533
46605
  personaStore,
46534
46606
  ownerDisplayName,
@@ -46546,6 +46618,7 @@ async function startDaemon(config) {
46546
46618
  // - dispatchMcpConfigPath: reducer 透传到 SpawnContext,cc spawn 加 --mcp-config flag。
46547
46619
  personaDispatchManager,
46548
46620
  dispatchMcpConfigPath: dispatchMcpConfigPath2,
46621
+ ticketMcpConfigPath: ticketMcpConfigPath2,
46549
46622
  broadcastFrame: (frame, target) => {
46550
46623
  if (target === "all") {
46551
46624
  transport?.broadcastAll(frame);
@@ -46565,10 +46638,10 @@ async function startDaemon(config) {
46565
46638
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
46566
46639
  attachmentGroup: {
46567
46640
  onFileEdit: (input) => {
46568
- const absPath = import_node_path47.default.isAbsolute(input.relPath) ? input.relPath : import_node_path47.default.join(input.cwd, input.relPath);
46641
+ const absPath = import_node_path48.default.isAbsolute(input.relPath) ? input.relPath : import_node_path48.default.join(input.cwd, input.relPath);
46569
46642
  let size = 0;
46570
46643
  try {
46571
- size = import_node_fs36.default.statSync(absPath).size;
46644
+ size = import_node_fs37.default.statSync(absPath).size;
46572
46645
  } catch (err) {
46573
46646
  logger.warn("attachment.onFileEdit stat failed", {
46574
46647
  sessionId: input.sessionId,
@@ -46754,11 +46827,11 @@ async function startDaemon(config) {
46754
46827
  // 'persona/<pid>/owner',default 走 'default'。
46755
46828
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
46756
46829
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
46757
- personaRoot: import_node_path47.default.join(config.dataDir, "personas"),
46830
+ personaRoot: import_node_path48.default.join(config.dataDir, "personas"),
46758
46831
  usersRoot
46759
46832
  },
46760
46833
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
46761
- personaRoot: import_node_path47.default.join(config.dataDir, "personas"),
46834
+ personaRoot: import_node_path48.default.join(config.dataDir, "personas"),
46762
46835
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
46763
46836
  usersRoot,
46764
46837
  // capability:list / delete handler 依赖
@@ -46865,11 +46938,11 @@ async function startDaemon(config) {
46865
46938
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
46866
46939
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
46867
46940
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
46868
- appBuilderPersonaRoot: import_node_path47.default.join(config.dataDir, "personas", "persona-app-builder"),
46941
+ appBuilderPersonaRoot: import_node_path48.default.join(config.dataDir, "personas", "persona-app-builder"),
46869
46942
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
46870
- deployKitRoot: import_node_path47.default.join(config.dataDir, "deploy-kit"),
46943
+ deployKitRoot: import_node_path48.default.join(config.dataDir, "deploy-kit"),
46871
46944
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
46872
- resolvePersonaRoot: (personaId) => import_node_path47.default.join(config.dataDir, "personas", personaId),
46945
+ resolvePersonaRoot: (personaId) => import_node_path48.default.join(config.dataDir, "personas", personaId),
46873
46946
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
46874
46947
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
46875
46948
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -46903,7 +46976,7 @@ async function startDaemon(config) {
46903
46976
  if (!sourceFile) {
46904
46977
  throw new Error(`personaDispatch:run source session not found: ${args.sourceSessionId}`);
46905
46978
  }
46906
- const sourceJsonlPath = sourceFile.toolSessionId ? import_node_path47.default.join(
46979
+ const sourceJsonlPath = sourceFile.toolSessionId ? import_node_path48.default.join(
46907
46980
  import_node_os20.default.homedir(),
46908
46981
  ".claude",
46909
46982
  "projects",
@@ -47159,8 +47232,8 @@ async function startDaemon(config) {
47159
47232
  const lines = [
47160
47233
  `Tunnel: ${r.url}`,
47161
47234
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
47162
- `Frpc config: ${import_node_path47.default.join(config.dataDir, "frpc.toml")}`,
47163
- `Frpc log: ${import_node_path47.default.join(config.dataDir, "frpc.log")}`
47235
+ `Frpc config: ${import_node_path48.default.join(config.dataDir, "frpc.toml")}`,
47236
+ `Frpc log: ${import_node_path48.default.join(config.dataDir, "frpc.log")}`
47164
47237
  ];
47165
47238
  const width = Math.max(...lines.map((l) => l.length));
47166
47239
  const bar = "\u2550".repeat(width + 4);
@@ -47173,8 +47246,8 @@ ${bar}
47173
47246
 
47174
47247
  `);
47175
47248
  try {
47176
- const connectPath = import_node_path47.default.join(config.dataDir, "connect.txt");
47177
- import_node_fs36.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
47249
+ const connectPath = import_node_path48.default.join(config.dataDir, "connect.txt");
47250
+ import_node_fs37.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
47178
47251
  } catch {
47179
47252
  }
47180
47253
  } catch (err) {
@@ -47246,9 +47319,9 @@ ${bar}
47246
47319
  };
47247
47320
  }
47248
47321
  function migrateDropPersonsDir(dataDir) {
47249
- const dir = import_node_path47.default.join(dataDir, "persons");
47322
+ const dir = import_node_path48.default.join(dataDir, "persons");
47250
47323
  try {
47251
- import_node_fs36.default.rmSync(dir, { recursive: true, force: true });
47324
+ import_node_fs37.default.rmSync(dir, { recursive: true, force: true });
47252
47325
  } catch {
47253
47326
  }
47254
47327
  }