@clawos-dev/clawd 0.2.153-beta.322.6a8336d → 0.2.154-beta.324.8c794f9

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.
Files changed (2) hide show
  1. package/dist/cli.cjs +639 -524
  2. package/package.json +1 -1
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: path59, errorMaps, issueData } = params;
724
- const fullPath = [...path59, ...issueData.path || []];
723
+ const { data, path: path60, errorMaps, issueData } = params;
724
+ const fullPath = [...path60, ...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, path59, key) {
1035
+ constructor(parent, value, path60, key) {
1036
1036
  this._cachedPath = [];
1037
1037
  this.parent = parent;
1038
1038
  this.data = value;
1039
- this._path = path59;
1039
+ this._path = path60;
1040
1040
  this._key = key;
1041
1041
  }
1042
1042
  get path() {
@@ -4451,7 +4451,11 @@ var init_attachment_schemas = __esm({
4451
4451
  /** 相对 session.cwd 的路径;允许传绝对路径,daemon 端会归一化(必须在 cwd 内) */
4452
4452
  relPath: external_exports.string().min(1),
4453
4453
  /** TTL 秒数;缺省 24h;null 走永久 URL(不带 exp 字段) */
4454
- ttlSeconds: external_exports.number().int().positive().nullable().optional()
4454
+ ttlSeconds: external_exports.number().int().positive().nullable().optional(),
4455
+ /** 视图模式:缺省 'raw' 返 /files/... 裸文件 URL;'md-rendered' 返
4456
+ * /share/md/... viewer URL(同一签名,daemon 端换前缀),外人浏览器打开就是
4457
+ * drawer 同款 ReactMarkdown 渲染。FilesDrawer 等不关心渲染的 caller 不传。 */
4458
+ view: external_exports.enum(["raw", "md-rendered"]).optional()
4455
4459
  });
4456
4460
  AttachmentSignUrlResponseSchema = external_exports.object({
4457
4461
  /** 完整 URL(含 httpBaseUrl 前缀),UI 直接 window.open / 复制到剪贴板 */
@@ -6286,8 +6290,8 @@ var require_req = __commonJS({
6286
6290
  if (req.originalUrl) {
6287
6291
  _req.url = req.originalUrl;
6288
6292
  } else {
6289
- const path59 = req.path;
6290
- _req.url = typeof path59 === "string" ? path59 : req.url ? req.url.path || req.url : void 0;
6293
+ const path60 = req.path;
6294
+ _req.url = typeof path60 === "string" ? path60 : req.url ? req.url.path || req.url : void 0;
6291
6295
  }
6292
6296
  if (req.query) {
6293
6297
  _req.query = req.query;
@@ -6452,14 +6456,14 @@ var require_redact = __commonJS({
6452
6456
  }
6453
6457
  return obj;
6454
6458
  }
6455
- function parsePath(path59) {
6459
+ function parsePath(path60) {
6456
6460
  const parts = [];
6457
6461
  let current = "";
6458
6462
  let inBrackets = false;
6459
6463
  let inQuotes = false;
6460
6464
  let quoteChar = "";
6461
- for (let i = 0; i < path59.length; i++) {
6462
- const char = path59[i];
6465
+ for (let i = 0; i < path60.length; i++) {
6466
+ const char = path60[i];
6463
6467
  if (!inBrackets && char === ".") {
6464
6468
  if (current) {
6465
6469
  parts.push(current);
@@ -6590,10 +6594,10 @@ var require_redact = __commonJS({
6590
6594
  return current;
6591
6595
  }
6592
6596
  function redactPaths(obj, paths, censor, remove = false) {
6593
- for (const path59 of paths) {
6594
- const parts = parsePath(path59);
6597
+ for (const path60 of paths) {
6598
+ const parts = parsePath(path60);
6595
6599
  if (parts.includes("*")) {
6596
- redactWildcardPath(obj, parts, censor, path59, remove);
6600
+ redactWildcardPath(obj, parts, censor, path60, remove);
6597
6601
  } else {
6598
6602
  if (remove) {
6599
6603
  removeKey(obj, parts);
@@ -6678,8 +6682,8 @@ var require_redact = __commonJS({
6678
6682
  }
6679
6683
  } else {
6680
6684
  if (afterWildcard.includes("*")) {
6681
- const wrappedCensor = typeof censor === "function" ? (value, path59) => {
6682
- const fullPath = [...pathArray.slice(0, pathLength), ...path59];
6685
+ const wrappedCensor = typeof censor === "function" ? (value, path60) => {
6686
+ const fullPath = [...pathArray.slice(0, pathLength), ...path60];
6683
6687
  return censor(value, fullPath);
6684
6688
  } : censor;
6685
6689
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -6714,8 +6718,8 @@ var require_redact = __commonJS({
6714
6718
  return null;
6715
6719
  }
6716
6720
  const pathStructure = /* @__PURE__ */ new Map();
6717
- for (const path59 of pathsToClone) {
6718
- const parts = parsePath(path59);
6721
+ for (const path60 of pathsToClone) {
6722
+ const parts = parsePath(path60);
6719
6723
  let current = pathStructure;
6720
6724
  for (let i = 0; i < parts.length; i++) {
6721
6725
  const part = parts[i];
@@ -6767,24 +6771,24 @@ var require_redact = __commonJS({
6767
6771
  }
6768
6772
  return cloneSelectively(obj, pathStructure);
6769
6773
  }
6770
- function validatePath(path59) {
6771
- if (typeof path59 !== "string") {
6774
+ function validatePath(path60) {
6775
+ if (typeof path60 !== "string") {
6772
6776
  throw new Error("Paths must be (non-empty) strings");
6773
6777
  }
6774
- if (path59 === "") {
6778
+ if (path60 === "") {
6775
6779
  throw new Error("Invalid redaction path ()");
6776
6780
  }
6777
- if (path59.includes("..")) {
6778
- throw new Error(`Invalid redaction path (${path59})`);
6781
+ if (path60.includes("..")) {
6782
+ throw new Error(`Invalid redaction path (${path60})`);
6779
6783
  }
6780
- if (path59.includes(",")) {
6781
- throw new Error(`Invalid redaction path (${path59})`);
6784
+ if (path60.includes(",")) {
6785
+ throw new Error(`Invalid redaction path (${path60})`);
6782
6786
  }
6783
6787
  let bracketCount = 0;
6784
6788
  let inQuotes = false;
6785
6789
  let quoteChar = "";
6786
- for (let i = 0; i < path59.length; i++) {
6787
- const char = path59[i];
6790
+ for (let i = 0; i < path60.length; i++) {
6791
+ const char = path60[i];
6788
6792
  if ((char === '"' || char === "'") && bracketCount > 0) {
6789
6793
  if (!inQuotes) {
6790
6794
  inQuotes = true;
@@ -6798,20 +6802,20 @@ var require_redact = __commonJS({
6798
6802
  } else if (char === "]" && !inQuotes) {
6799
6803
  bracketCount--;
6800
6804
  if (bracketCount < 0) {
6801
- throw new Error(`Invalid redaction path (${path59})`);
6805
+ throw new Error(`Invalid redaction path (${path60})`);
6802
6806
  }
6803
6807
  }
6804
6808
  }
6805
6809
  if (bracketCount !== 0) {
6806
- throw new Error(`Invalid redaction path (${path59})`);
6810
+ throw new Error(`Invalid redaction path (${path60})`);
6807
6811
  }
6808
6812
  }
6809
6813
  function validatePaths(paths) {
6810
6814
  if (!Array.isArray(paths)) {
6811
6815
  throw new TypeError("paths must be an array");
6812
6816
  }
6813
- for (const path59 of paths) {
6814
- validatePath(path59);
6817
+ for (const path60 of paths) {
6818
+ validatePath(path60);
6815
6819
  }
6816
6820
  }
6817
6821
  function slowRedact(options = {}) {
@@ -6979,8 +6983,8 @@ var require_redaction = __commonJS({
6979
6983
  if (shape[k2] === null) {
6980
6984
  o[k2] = (value) => topCensor(value, [k2]);
6981
6985
  } else {
6982
- const wrappedCensor = typeof censor === "function" ? (value, path59) => {
6983
- return censor(value, [k2, ...path59]);
6986
+ const wrappedCensor = typeof censor === "function" ? (value, path60) => {
6987
+ return censor(value, [k2, ...path60]);
6984
6988
  } : censor;
6985
6989
  o[k2] = Redact({
6986
6990
  paths: shape[k2],
@@ -7198,10 +7202,10 @@ var require_atomic_sleep = __commonJS({
7198
7202
  var require_sonic_boom = __commonJS({
7199
7203
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
7200
7204
  "use strict";
7201
- var fs52 = require("fs");
7205
+ var fs54 = require("fs");
7202
7206
  var EventEmitter3 = require("events");
7203
7207
  var inherits = require("util").inherits;
7204
- var path59 = require("path");
7208
+ var path60 = require("path");
7205
7209
  var sleep2 = require_atomic_sleep();
7206
7210
  var assert = require("assert");
7207
7211
  var BUSY_WRITE_TIMEOUT = 100;
@@ -7255,20 +7259,20 @@ var require_sonic_boom = __commonJS({
7255
7259
  const mode = sonic.mode;
7256
7260
  if (sonic.sync) {
7257
7261
  try {
7258
- if (sonic.mkdir) fs52.mkdirSync(path59.dirname(file), { recursive: true });
7259
- const fd = fs52.openSync(file, flags, mode);
7262
+ if (sonic.mkdir) fs54.mkdirSync(path60.dirname(file), { recursive: true });
7263
+ const fd = fs54.openSync(file, flags, mode);
7260
7264
  fileOpened(null, fd);
7261
7265
  } catch (err) {
7262
7266
  fileOpened(err);
7263
7267
  throw err;
7264
7268
  }
7265
7269
  } else if (sonic.mkdir) {
7266
- fs52.mkdir(path59.dirname(file), { recursive: true }, (err) => {
7270
+ fs54.mkdir(path60.dirname(file), { recursive: true }, (err) => {
7267
7271
  if (err) return fileOpened(err);
7268
- fs52.open(file, flags, mode, fileOpened);
7272
+ fs54.open(file, flags, mode, fileOpened);
7269
7273
  });
7270
7274
  } else {
7271
- fs52.open(file, flags, mode, fileOpened);
7275
+ fs54.open(file, flags, mode, fileOpened);
7272
7276
  }
7273
7277
  }
7274
7278
  function SonicBoom(opts) {
@@ -7309,8 +7313,8 @@ var require_sonic_boom = __commonJS({
7309
7313
  this.flush = flushBuffer;
7310
7314
  this.flushSync = flushBufferSync;
7311
7315
  this._actualWrite = actualWriteBuffer;
7312
- fsWriteSync = () => fs52.writeSync(this.fd, this._writingBuf);
7313
- fsWrite = () => fs52.write(this.fd, this._writingBuf, this.release);
7316
+ fsWriteSync = () => fs54.writeSync(this.fd, this._writingBuf);
7317
+ fsWrite = () => fs54.write(this.fd, this._writingBuf, this.release);
7314
7318
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
7315
7319
  this._writingBuf = "";
7316
7320
  this.write = write;
@@ -7319,15 +7323,15 @@ var require_sonic_boom = __commonJS({
7319
7323
  this._actualWrite = actualWrite;
7320
7324
  fsWriteSync = () => {
7321
7325
  if (Buffer.isBuffer(this._writingBuf)) {
7322
- return fs52.writeSync(this.fd, this._writingBuf);
7326
+ return fs54.writeSync(this.fd, this._writingBuf);
7323
7327
  }
7324
- return fs52.writeSync(this.fd, this._writingBuf, "utf8");
7328
+ return fs54.writeSync(this.fd, this._writingBuf, "utf8");
7325
7329
  };
7326
7330
  fsWrite = () => {
7327
7331
  if (Buffer.isBuffer(this._writingBuf)) {
7328
- return fs52.write(this.fd, this._writingBuf, this.release);
7332
+ return fs54.write(this.fd, this._writingBuf, this.release);
7329
7333
  }
7330
- return fs52.write(this.fd, this._writingBuf, "utf8", this.release);
7334
+ return fs54.write(this.fd, this._writingBuf, "utf8", this.release);
7331
7335
  };
7332
7336
  } else {
7333
7337
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -7384,7 +7388,7 @@ var require_sonic_boom = __commonJS({
7384
7388
  }
7385
7389
  }
7386
7390
  if (this._fsync) {
7387
- fs52.fsyncSync(this.fd);
7391
+ fs54.fsyncSync(this.fd);
7388
7392
  }
7389
7393
  const len = this._len;
7390
7394
  if (this._reopening) {
@@ -7498,7 +7502,7 @@ var require_sonic_boom = __commonJS({
7498
7502
  const onDrain = () => {
7499
7503
  if (!this._fsync) {
7500
7504
  try {
7501
- fs52.fsync(this.fd, (err) => {
7505
+ fs54.fsync(this.fd, (err) => {
7502
7506
  this._flushPending = false;
7503
7507
  cb(err);
7504
7508
  });
@@ -7600,7 +7604,7 @@ var require_sonic_boom = __commonJS({
7600
7604
  const fd = this.fd;
7601
7605
  this.once("ready", () => {
7602
7606
  if (fd !== this.fd) {
7603
- fs52.close(fd, (err) => {
7607
+ fs54.close(fd, (err) => {
7604
7608
  if (err) {
7605
7609
  return this.emit("error", err);
7606
7610
  }
@@ -7649,7 +7653,7 @@ var require_sonic_boom = __commonJS({
7649
7653
  buf = this._bufs[0];
7650
7654
  }
7651
7655
  try {
7652
- const n = Buffer.isBuffer(buf) ? fs52.writeSync(this.fd, buf) : fs52.writeSync(this.fd, buf, "utf8");
7656
+ const n = Buffer.isBuffer(buf) ? fs54.writeSync(this.fd, buf) : fs54.writeSync(this.fd, buf, "utf8");
7653
7657
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
7654
7658
  buf = releasedBufObj.writingBuf;
7655
7659
  this._len = releasedBufObj.len;
@@ -7665,7 +7669,7 @@ var require_sonic_boom = __commonJS({
7665
7669
  }
7666
7670
  }
7667
7671
  try {
7668
- fs52.fsyncSync(this.fd);
7672
+ fs54.fsyncSync(this.fd);
7669
7673
  } catch {
7670
7674
  }
7671
7675
  }
@@ -7686,7 +7690,7 @@ var require_sonic_boom = __commonJS({
7686
7690
  buf = mergeBuf(this._bufs[0], this._lens[0]);
7687
7691
  }
7688
7692
  try {
7689
- const n = fs52.writeSync(this.fd, buf);
7693
+ const n = fs54.writeSync(this.fd, buf);
7690
7694
  buf = buf.subarray(n);
7691
7695
  this._len = Math.max(this._len - n, 0);
7692
7696
  if (buf.length <= 0) {
@@ -7714,13 +7718,13 @@ var require_sonic_boom = __commonJS({
7714
7718
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
7715
7719
  if (this.sync) {
7716
7720
  try {
7717
- const written = Buffer.isBuffer(this._writingBuf) ? fs52.writeSync(this.fd, this._writingBuf) : fs52.writeSync(this.fd, this._writingBuf, "utf8");
7721
+ const written = Buffer.isBuffer(this._writingBuf) ? fs54.writeSync(this.fd, this._writingBuf) : fs54.writeSync(this.fd, this._writingBuf, "utf8");
7718
7722
  release(null, written);
7719
7723
  } catch (err) {
7720
7724
  release(err);
7721
7725
  }
7722
7726
  } else {
7723
- fs52.write(this.fd, this._writingBuf, release);
7727
+ fs54.write(this.fd, this._writingBuf, release);
7724
7728
  }
7725
7729
  }
7726
7730
  function actualWriteBuffer() {
@@ -7729,7 +7733,7 @@ var require_sonic_boom = __commonJS({
7729
7733
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
7730
7734
  if (this.sync) {
7731
7735
  try {
7732
- const written = fs52.writeSync(this.fd, this._writingBuf);
7736
+ const written = fs54.writeSync(this.fd, this._writingBuf);
7733
7737
  release(null, written);
7734
7738
  } catch (err) {
7735
7739
  release(err);
@@ -7738,7 +7742,7 @@ var require_sonic_boom = __commonJS({
7738
7742
  if (kCopyBuffer) {
7739
7743
  this._writingBuf = Buffer.from(this._writingBuf);
7740
7744
  }
7741
- fs52.write(this.fd, this._writingBuf, release);
7745
+ fs54.write(this.fd, this._writingBuf, release);
7742
7746
  }
7743
7747
  }
7744
7748
  function actualClose(sonic) {
@@ -7754,12 +7758,12 @@ var require_sonic_boom = __commonJS({
7754
7758
  sonic._lens = [];
7755
7759
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
7756
7760
  try {
7757
- fs52.fsync(sonic.fd, closeWrapped);
7761
+ fs54.fsync(sonic.fd, closeWrapped);
7758
7762
  } catch {
7759
7763
  }
7760
7764
  function closeWrapped() {
7761
7765
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7762
- fs52.close(sonic.fd, done);
7766
+ fs54.close(sonic.fd, done);
7763
7767
  } else {
7764
7768
  done();
7765
7769
  }
@@ -10894,11 +10898,11 @@ var init_lib = __esm({
10894
10898
  }
10895
10899
  }
10896
10900
  },
10897
- addToPath: function addToPath(path59, added, removed, oldPosInc, options) {
10898
- var last = path59.lastComponent;
10901
+ addToPath: function addToPath(path60, added, removed, oldPosInc, options) {
10902
+ var last = path60.lastComponent;
10899
10903
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
10900
10904
  return {
10901
- oldPos: path59.oldPos + oldPosInc,
10905
+ oldPos: path60.oldPos + oldPosInc,
10902
10906
  lastComponent: {
10903
10907
  count: last.count + 1,
10904
10908
  added,
@@ -10908,7 +10912,7 @@ var init_lib = __esm({
10908
10912
  };
10909
10913
  } else {
10910
10914
  return {
10911
- oldPos: path59.oldPos + oldPosInc,
10915
+ oldPos: path60.oldPos + oldPosInc,
10912
10916
  lastComponent: {
10913
10917
  count: 1,
10914
10918
  added,
@@ -11154,7 +11158,7 @@ function hashDirToCwd(hash) {
11154
11158
  }
11155
11159
  function safeStatMtime(p2) {
11156
11160
  try {
11157
- return import_node_fs8.default.statSync(p2).mtimeMs;
11161
+ return import_node_fs10.default.statSync(p2).mtimeMs;
11158
11162
  } catch {
11159
11163
  return 0;
11160
11164
  }
@@ -11162,7 +11166,7 @@ function safeStatMtime(p2) {
11162
11166
  function readJsonlLines(file) {
11163
11167
  let raw;
11164
11168
  try {
11165
- raw = import_node_fs8.default.readFileSync(file, "utf8");
11169
+ raw = import_node_fs10.default.readFileSync(file, "utf8");
11166
11170
  } catch (err) {
11167
11171
  if (err.code === "ENOENT") return [];
11168
11172
  throw err;
@@ -11354,10 +11358,10 @@ function attachmentToHistoryMessage(o, ts) {
11354
11358
  const memories = raw.map((m2) => {
11355
11359
  if (!m2 || typeof m2 !== "object") return null;
11356
11360
  const rec3 = m2;
11357
- const path59 = typeof rec3.path === "string" ? rec3.path : null;
11361
+ const path60 = typeof rec3.path === "string" ? rec3.path : null;
11358
11362
  const content = typeof rec3.content === "string" ? rec3.content : null;
11359
- if (!path59 || content == null) return null;
11360
- const entry = { path: path59, content };
11363
+ if (!path60 || content == null) return null;
11364
+ const entry = { path: path60, content };
11361
11365
  if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
11362
11366
  return entry;
11363
11367
  }).filter((m2) => m2 !== null);
@@ -11393,8 +11397,8 @@ function attachmentDeferredToolsText(a) {
11393
11397
  function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
11394
11398
  if (backupFileName === null) return null;
11395
11399
  try {
11396
- return import_node_fs8.default.readFileSync(
11397
- import_node_path8.default.join(fileHistoryRoot, toolSessionId, backupFileName),
11400
+ return import_node_fs10.default.readFileSync(
11401
+ import_node_path9.default.join(fileHistoryRoot, toolSessionId, backupFileName),
11398
11402
  "utf8"
11399
11403
  );
11400
11404
  } catch {
@@ -11403,19 +11407,19 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
11403
11407
  }
11404
11408
  function readCurrentContent(filePath) {
11405
11409
  try {
11406
- return import_node_fs8.default.readFileSync(filePath, "utf8");
11410
+ return import_node_fs10.default.readFileSync(filePath, "utf8");
11407
11411
  } catch (err) {
11408
11412
  if (err.code === "ENOENT") return null;
11409
11413
  return null;
11410
11414
  }
11411
11415
  }
11412
- var import_node_fs8, import_node_os5, import_node_path8, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11416
+ var import_node_fs10, import_node_os5, import_node_path9, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11413
11417
  var init_claude_history = __esm({
11414
11418
  "src/tools/claude-history.ts"() {
11415
11419
  "use strict";
11416
- import_node_fs8 = __toESM(require("fs"), 1);
11420
+ import_node_fs10 = __toESM(require("fs"), 1);
11417
11421
  import_node_os5 = __toESM(require("os"), 1);
11418
- import_node_path8 = __toESM(require("path"), 1);
11422
+ import_node_path9 = __toESM(require("path"), 1);
11419
11423
  init_lib();
11420
11424
  init_tool_result_extra();
11421
11425
  TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
@@ -11439,14 +11443,14 @@ var init_claude_history = __esm({
11439
11443
  // 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
11440
11444
  fileHistoryRoot;
11441
11445
  constructor(opts = {}) {
11442
- const base = opts.baseDir ?? import_node_path8.default.join(import_node_os5.default.homedir(), ".claude");
11443
- this.projectsRoot = import_node_path8.default.join(base, "projects");
11444
- this.fileHistoryRoot = import_node_path8.default.join(base, "file-history");
11446
+ const base = opts.baseDir ?? import_node_path9.default.join(import_node_os5.default.homedir(), ".claude");
11447
+ this.projectsRoot = import_node_path9.default.join(base, "projects");
11448
+ this.fileHistoryRoot = import_node_path9.default.join(base, "file-history");
11445
11449
  }
11446
11450
  async listProjects() {
11447
11451
  let entries;
11448
11452
  try {
11449
- entries = import_node_fs8.default.readdirSync(this.projectsRoot, { withFileTypes: true });
11453
+ entries = import_node_fs10.default.readdirSync(this.projectsRoot, { withFileTypes: true });
11450
11454
  } catch (err) {
11451
11455
  if (err.code === "ENOENT") return [];
11452
11456
  throw err;
@@ -11454,9 +11458,9 @@ var init_claude_history = __esm({
11454
11458
  const out = [];
11455
11459
  for (const ent of entries) {
11456
11460
  if (!ent.isDirectory()) continue;
11457
- const dir = import_node_path8.default.join(this.projectsRoot, ent.name);
11458
- const files = import_node_fs8.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11459
- const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path8.default.join(dir, f))), 0);
11461
+ const dir = import_node_path9.default.join(this.projectsRoot, ent.name);
11462
+ const files = import_node_fs10.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11463
+ const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path9.default.join(dir, f))), 0);
11460
11464
  out.push({
11461
11465
  projectPath: hashDirToCwd(ent.name),
11462
11466
  hashDir: ent.name,
@@ -11468,17 +11472,17 @@ var init_claude_history = __esm({
11468
11472
  return out;
11469
11473
  }
11470
11474
  async listSessions(args) {
11471
- const dir = import_node_path8.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
11475
+ const dir = import_node_path9.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
11472
11476
  let files;
11473
11477
  try {
11474
- files = import_node_fs8.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11478
+ files = import_node_fs10.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11475
11479
  } catch (err) {
11476
11480
  if (err.code === "ENOENT") return [];
11477
11481
  throw err;
11478
11482
  }
11479
11483
  const out = [];
11480
11484
  for (const f of files) {
11481
- const full = import_node_path8.default.join(dir, f);
11485
+ const full = import_node_path9.default.join(dir, f);
11482
11486
  const toolSessionId = f.slice(0, -".jsonl".length);
11483
11487
  const lines = readJsonlLines(full);
11484
11488
  let summary = "";
@@ -11533,7 +11537,7 @@ var init_claude_history = __esm({
11533
11537
  return out;
11534
11538
  }
11535
11539
  async read(args) {
11536
- const file = import_node_path8.default.join(
11540
+ const file = import_node_path9.default.join(
11537
11541
  this.projectsRoot,
11538
11542
  cwdToHashDir(args.cwd),
11539
11543
  `${args.toolSessionId}.jsonl`
@@ -11570,7 +11574,7 @@ var init_claude_history = __esm({
11570
11574
  // 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
11571
11575
  // 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
11572
11576
  listSubagentsFromDirectory(cwd, toolSessionId) {
11573
- const dir = import_node_path8.default.join(
11577
+ const dir = import_node_path9.default.join(
11574
11578
  this.projectsRoot,
11575
11579
  cwdToHashDir(cwd),
11576
11580
  toolSessionId,
@@ -11578,7 +11582,7 @@ var init_claude_history = __esm({
11578
11582
  );
11579
11583
  let entries;
11580
11584
  try {
11581
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
11585
+ entries = import_node_fs10.default.readdirSync(dir, { withFileTypes: true });
11582
11586
  } catch (err) {
11583
11587
  if (err.code === "ENOENT") return null;
11584
11588
  return null;
@@ -11588,7 +11592,7 @@ var init_claude_history = __esm({
11588
11592
  if (!e.isFile()) continue;
11589
11593
  if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
11590
11594
  const subagentId = e.name.slice("agent-".length, -".jsonl".length);
11591
- const filePath = import_node_path8.default.join(dir, e.name);
11595
+ const filePath = import_node_path9.default.join(dir, e.name);
11592
11596
  const lines = readJsonlLines(filePath);
11593
11597
  let firstText = "";
11594
11598
  let messageCount = 0;
@@ -11605,7 +11609,7 @@ var init_claude_history = __esm({
11605
11609
  return out;
11606
11610
  }
11607
11611
  listSubagentsFromMainJsonl(cwd, toolSessionId) {
11608
- const file = import_node_path8.default.join(
11612
+ const file = import_node_path9.default.join(
11609
11613
  this.projectsRoot,
11610
11614
  cwdToHashDir(cwd),
11611
11615
  `${toolSessionId}.jsonl`
@@ -11640,7 +11644,7 @@ var init_claude_history = __esm({
11640
11644
  }
11641
11645
  // 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
11642
11646
  readSubagentFromFile(cwd, toolSessionId, subagentId) {
11643
- const file = import_node_path8.default.join(
11647
+ const file = import_node_path9.default.join(
11644
11648
  this.projectsRoot,
11645
11649
  cwdToHashDir(cwd),
11646
11650
  toolSessionId,
@@ -11649,7 +11653,7 @@ var init_claude_history = __esm({
11649
11653
  );
11650
11654
  let exists = false;
11651
11655
  try {
11652
- exists = import_node_fs8.default.statSync(file).isFile();
11656
+ exists = import_node_fs10.default.statSync(file).isFile();
11653
11657
  } catch {
11654
11658
  return null;
11655
11659
  }
@@ -11668,7 +11672,7 @@ var init_claude_history = __esm({
11668
11672
  * "那一刻每个 tracked 文件对应的 backup 文件名"
11669
11673
  */
11670
11674
  readFileHistorySnapshots(args) {
11671
- const file = import_node_path8.default.join(
11675
+ const file = import_node_path9.default.join(
11672
11676
  this.projectsRoot,
11673
11677
  cwdToHashDir(args.cwd),
11674
11678
  `${args.toolSessionId}.jsonl`
@@ -11713,7 +11717,7 @@ var init_claude_history = __esm({
11713
11717
  for (const [anchorId, target] of snapshots) {
11714
11718
  let hasAny = false;
11715
11719
  for (const [rawPath, backup] of Object.entries(target)) {
11716
- const absPath = import_node_path8.default.isAbsolute(rawPath) ? rawPath : import_node_path8.default.join(args.cwd, rawPath);
11720
+ const absPath = import_node_path9.default.isAbsolute(rawPath) ? rawPath : import_node_path9.default.join(args.cwd, rawPath);
11717
11721
  const backupContent = readBackupContent(
11718
11722
  this.fileHistoryRoot,
11719
11723
  args.toolSessionId,
@@ -11753,7 +11757,7 @@ var init_claude_history = __esm({
11753
11757
  let totalInsertions = 0;
11754
11758
  let totalDeletions = 0;
11755
11759
  for (const [rawPath, backup] of Object.entries(target)) {
11756
- const absPath = import_node_path8.default.isAbsolute(rawPath) ? rawPath : import_node_path8.default.join(args.cwd, rawPath);
11760
+ const absPath = import_node_path9.default.isAbsolute(rawPath) ? rawPath : import_node_path9.default.join(args.cwd, rawPath);
11757
11761
  const backupContent = readBackupContent(
11758
11762
  this.fileHistoryRoot,
11759
11763
  args.toolSessionId,
@@ -11800,7 +11804,7 @@ var init_claude_history = __esm({
11800
11804
  };
11801
11805
  }
11802
11806
  readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
11803
- const file = import_node_path8.default.join(
11807
+ const file = import_node_path9.default.join(
11804
11808
  this.projectsRoot,
11805
11809
  cwdToHashDir(cwd),
11806
11810
  `${toolSessionId}.jsonl`
@@ -11825,13 +11829,13 @@ var init_claude_history = __esm({
11825
11829
  function probeViaWhich() {
11826
11830
  try {
11827
11831
  const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
11828
- if (out && import_node_fs9.default.existsSync(out)) return out;
11832
+ if (out && import_node_fs11.default.existsSync(out)) return out;
11829
11833
  } catch {
11830
11834
  }
11831
11835
  return null;
11832
11836
  }
11833
11837
  async function probeClaude(env = process.env) {
11834
- if (env.CLAUDE_BIN && import_node_fs9.default.existsSync(env.CLAUDE_BIN)) {
11838
+ if (env.CLAUDE_BIN && import_node_fs11.default.existsSync(env.CLAUDE_BIN)) {
11835
11839
  return { available: true, path: env.CLAUDE_BIN };
11836
11840
  }
11837
11841
  const w2 = probeViaWhich();
@@ -12159,10 +12163,10 @@ function parseAttachment(obj) {
12159
12163
  const memories = raw.map((m2) => {
12160
12164
  if (!m2 || typeof m2 !== "object") return null;
12161
12165
  const rec3 = m2;
12162
- const path59 = typeof rec3.path === "string" ? rec3.path : null;
12166
+ const path60 = typeof rec3.path === "string" ? rec3.path : null;
12163
12167
  const content = typeof rec3.content === "string" ? rec3.content : null;
12164
- if (!path59 || content == null) return null;
12165
- const out = { path: path59, content };
12168
+ if (!path60 || content == null) return null;
12169
+ const out = { path: path60, content };
12166
12170
  if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
12167
12171
  return out;
12168
12172
  }).filter((m2) => m2 !== null);
@@ -12266,13 +12270,13 @@ function encodeClaudeStdin(text) {
12266
12270
  };
12267
12271
  return JSON.stringify(frame) + "\n";
12268
12272
  }
12269
- var import_node_child_process, import_node_child_process2, import_node_fs9, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
12273
+ var import_node_child_process, import_node_child_process2, import_node_fs11, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
12270
12274
  var init_claude = __esm({
12271
12275
  "src/tools/claude.ts"() {
12272
12276
  "use strict";
12273
12277
  import_node_child_process = require("child_process");
12274
12278
  import_node_child_process2 = require("child_process");
12275
- import_node_fs9 = __toESM(require("fs"), 1);
12279
+ import_node_fs11 = __toESM(require("fs"), 1);
12276
12280
  init_protocol();
12277
12281
  init_claude_history();
12278
12282
  init_tool_result_extra();
@@ -23949,8 +23953,8 @@ var require_utils = __commonJS({
23949
23953
  var result = transform[inputType][outputType](input);
23950
23954
  return result;
23951
23955
  };
23952
- exports2.resolve = function(path59) {
23953
- var parts = path59.split("/");
23956
+ exports2.resolve = function(path60) {
23957
+ var parts = path60.split("/");
23954
23958
  var result = [];
23955
23959
  for (var index = 0; index < parts.length; index++) {
23956
23960
  var part = parts[index];
@@ -29803,18 +29807,18 @@ var require_object = __commonJS({
29803
29807
  var object = new ZipObject(name, zipObjectContent, o);
29804
29808
  this.files[name] = object;
29805
29809
  };
29806
- var parentFolder = function(path59) {
29807
- if (path59.slice(-1) === "/") {
29808
- path59 = path59.substring(0, path59.length - 1);
29810
+ var parentFolder = function(path60) {
29811
+ if (path60.slice(-1) === "/") {
29812
+ path60 = path60.substring(0, path60.length - 1);
29809
29813
  }
29810
- var lastSlash = path59.lastIndexOf("/");
29811
- return lastSlash > 0 ? path59.substring(0, lastSlash) : "";
29814
+ var lastSlash = path60.lastIndexOf("/");
29815
+ return lastSlash > 0 ? path60.substring(0, lastSlash) : "";
29812
29816
  };
29813
- var forceTrailingSlash = function(path59) {
29814
- if (path59.slice(-1) !== "/") {
29815
- path59 += "/";
29817
+ var forceTrailingSlash = function(path60) {
29818
+ if (path60.slice(-1) !== "/") {
29819
+ path60 += "/";
29816
29820
  }
29817
- return path59;
29821
+ return path60;
29818
29822
  };
29819
29823
  var folderAdd = function(name, createFolders) {
29820
29824
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -30816,7 +30820,7 @@ var require_lib3 = __commonJS({
30816
30820
  // src/run-case/recorder.ts
30817
30821
  function startRunCaseRecorder(opts) {
30818
30822
  const now = opts.now ?? Date.now;
30819
- const dir = import_node_path47.default.dirname(opts.recordPath);
30823
+ const dir = import_node_path48.default.dirname(opts.recordPath);
30820
30824
  let stream = null;
30821
30825
  let closing = false;
30822
30826
  let closedSettled = false;
@@ -30830,8 +30834,8 @@ function startRunCaseRecorder(opts) {
30830
30834
  });
30831
30835
  const ensureStream = () => {
30832
30836
  if (stream) return stream;
30833
- import_node_fs35.default.mkdirSync(dir, { recursive: true });
30834
- stream = import_node_fs35.default.createWriteStream(opts.recordPath, { flags: "a" });
30837
+ import_node_fs37.default.mkdirSync(dir, { recursive: true });
30838
+ stream = import_node_fs37.default.createWriteStream(opts.recordPath, { flags: "a" });
30835
30839
  stream.on("close", () => closedResolve());
30836
30840
  return stream;
30837
30841
  };
@@ -30856,12 +30860,12 @@ function startRunCaseRecorder(opts) {
30856
30860
  };
30857
30861
  return { tap, close, closed };
30858
30862
  }
30859
- var import_node_fs35, import_node_path47;
30863
+ var import_node_fs37, import_node_path48;
30860
30864
  var init_recorder = __esm({
30861
30865
  "src/run-case/recorder.ts"() {
30862
30866
  "use strict";
30863
- import_node_fs35 = __toESM(require("fs"), 1);
30864
- import_node_path47 = __toESM(require("path"), 1);
30867
+ import_node_fs37 = __toESM(require("fs"), 1);
30868
+ import_node_path48 = __toESM(require("path"), 1);
30865
30869
  }
30866
30870
  });
30867
30871
 
@@ -30904,7 +30908,7 @@ var init_wire = __esm({
30904
30908
  // src/run-case/controller.ts
30905
30909
  async function runController(opts) {
30906
30910
  const now = opts.now ?? Date.now;
30907
- const cwd = opts.cwd ?? (0, import_node_fs36.mkdtempSync)(import_node_path48.default.join(import_node_os21.default.tmpdir(), "clawd-runcase-"));
30911
+ const cwd = opts.cwd ?? (0, import_node_fs38.mkdtempSync)(import_node_path49.default.join(import_node_os21.default.tmpdir(), "clawd-runcase-"));
30908
30912
  const ownsCwd = opts.cwd === void 0;
30909
30913
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
30910
30914
  const spawnCtx = { cwd };
@@ -31065,19 +31069,19 @@ async function runController(opts) {
31065
31069
  if (sigintHandler) process.off("SIGINT", sigintHandler);
31066
31070
  if (ownsCwd) {
31067
31071
  try {
31068
- (0, import_node_fs36.rmSync)(cwd, { recursive: true, force: true });
31072
+ (0, import_node_fs38.rmSync)(cwd, { recursive: true, force: true });
31069
31073
  } catch {
31070
31074
  }
31071
31075
  }
31072
31076
  return exitCode ?? 0;
31073
31077
  }
31074
- var import_node_fs36, import_node_os21, import_node_path48;
31078
+ var import_node_fs38, import_node_os21, import_node_path49;
31075
31079
  var init_controller = __esm({
31076
31080
  "src/run-case/controller.ts"() {
31077
31081
  "use strict";
31078
- import_node_fs36 = require("fs");
31082
+ import_node_fs38 = require("fs");
31079
31083
  import_node_os21 = __toESM(require("os"), 1);
31080
- import_node_path48 = __toESM(require("path"), 1);
31084
+ import_node_path49 = __toESM(require("path"), 1);
31081
31085
  init_claude();
31082
31086
  init_stdout_splitter();
31083
31087
  init_permission_stdio();
@@ -31339,8 +31343,8 @@ Env (advanced):
31339
31343
  `;
31340
31344
 
31341
31345
  // src/index.ts
31342
- var import_node_path46 = __toESM(require("path"), 1);
31343
- var import_node_fs34 = __toESM(require("fs"), 1);
31346
+ var import_node_path47 = __toESM(require("path"), 1);
31347
+ var import_node_fs36 = __toESM(require("fs"), 1);
31344
31348
  var import_node_os20 = __toESM(require("os"), 1);
31345
31349
 
31346
31350
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
@@ -31391,7 +31395,7 @@ function v4(options, buf, offset) {
31391
31395
  var v4_default = v4;
31392
31396
 
31393
31397
  // src/index.ts
31394
- var import_node_url2 = require("url");
31398
+ var import_node_url3 = require("url");
31395
31399
 
31396
31400
  // src/logger.ts
31397
31401
  var import_node_fs2 = __toESM(require("fs"), 1);
@@ -35955,12 +35959,77 @@ function refreshDeployKit(args) {
35955
35959
  args.logger.info("deploy-kit.refresh.done", { dst });
35956
35960
  }
35957
35961
 
35962
+ // src/share-md-viewer/load.ts
35963
+ var import_node_fs9 = __toESM(require("fs"), 1);
35964
+ var import_node_path8 = __toESM(require("path"), 1);
35965
+ var import_node_url2 = require("url");
35966
+
35967
+ // src/share-md-viewer/asset-loader.ts
35968
+ var import_node_fs8 = __toESM(require("fs"), 1);
35969
+ function htmlEscape(s) {
35970
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
35971
+ }
35972
+ function createViewerAssetLoader(opts) {
35973
+ let viewerTemplate;
35974
+ let errorTemplate;
35975
+ try {
35976
+ viewerTemplate = import_node_fs8.default.readFileSync(opts.viewerHtmlPath, "utf8");
35977
+ } catch (err) {
35978
+ throw new Error(`viewer asset not found at ${opts.viewerHtmlPath}: ${err.message}`);
35979
+ }
35980
+ try {
35981
+ errorTemplate = import_node_fs8.default.readFileSync(opts.errorHtmlPath, "utf8");
35982
+ } catch (err) {
35983
+ throw new Error(`viewer error asset not found at ${opts.errorHtmlPath}: ${err.message}`);
35984
+ }
35985
+ return {
35986
+ renderViewerHtml(basename) {
35987
+ return viewerTemplate.replace(/\{\{TITLE\}\}/g, htmlEscape(basename));
35988
+ },
35989
+ renderErrorHtml(code, message) {
35990
+ return errorTemplate.replace(/\{\{ERROR_CODE\}\}/g, htmlEscape(code)).replace(/\{\{ERROR_MESSAGE\}\}/g, htmlEscape(message));
35991
+ }
35992
+ };
35993
+ }
35994
+
35995
+ // src/share-md-viewer/load.ts
35996
+ var import_meta2 = {};
35997
+ function tryLoadViewerAssets(logger) {
35998
+ const candidates = [];
35999
+ try {
36000
+ const here = import_node_path8.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
36001
+ candidates.push(here);
36002
+ candidates.push(import_node_path8.default.resolve(here, ".."));
36003
+ candidates.push(import_node_path8.default.resolve(here, "..", "..", "dist"));
36004
+ } catch {
36005
+ }
36006
+ if (process.argv[1]) {
36007
+ candidates.push(import_node_path8.default.dirname(process.argv[1]));
36008
+ }
36009
+ for (const root of candidates) {
36010
+ const viewerHtmlPath = import_node_path8.default.join(root, "share-md-viewer.html");
36011
+ const errorHtmlPath = import_node_path8.default.join(root, "share-md-viewer-error.html");
36012
+ try {
36013
+ if (import_node_fs9.default.statSync(viewerHtmlPath).isFile() && import_node_fs9.default.statSync(errorHtmlPath).isFile()) {
36014
+ logger?.info("share-md-viewer.assets-root.resolved", { root });
36015
+ return createViewerAssetLoader({ viewerHtmlPath, errorHtmlPath });
36016
+ }
36017
+ } catch {
36018
+ }
36019
+ }
36020
+ logger?.warn("share-md-viewer.assets-not-found", {
36021
+ candidates,
36022
+ hint: "run `pnpm -F @clawos/ext-clawd-ui build && pnpm -F @clawos-dev/clawd build`"
36023
+ });
36024
+ return null;
36025
+ }
36026
+
35958
36027
  // src/index.ts
35959
36028
  init_claude();
35960
36029
 
35961
36030
  // src/tools/codex.ts
35962
36031
  var import_node_child_process4 = require("child_process");
35963
- var import_node_fs10 = __toESM(require("fs"), 1);
36032
+ var import_node_fs12 = __toESM(require("fs"), 1);
35964
36033
 
35965
36034
  // src/tools/codex-session.ts
35966
36035
  var import_node_child_process3 = require("child_process");
@@ -36208,8 +36277,8 @@ function turnStartInput(text) {
36208
36277
  const items = [];
36209
36278
  let leftover = text;
36210
36279
  for (const m2 of text.matchAll(SKILL_RE)) {
36211
- const [marker, name, path59] = m2;
36212
- items.push({ type: "skill", name, path: path59 });
36280
+ const [marker, name, path60] = m2;
36281
+ items.push({ type: "skill", name, path: path60 });
36213
36282
  leftover = leftover.replace(marker, "");
36214
36283
  }
36215
36284
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -36393,10 +36462,10 @@ function sanitizeCodexModel(model) {
36393
36462
  return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
36394
36463
  }
36395
36464
  async function probeCodex(env = process.env) {
36396
- if (env.CODEX_BIN && import_node_fs10.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
36465
+ if (env.CODEX_BIN && import_node_fs12.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
36397
36466
  try {
36398
36467
  const out = (0, import_node_child_process4.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
36399
- if (out && import_node_fs10.default.existsSync(out)) return { available: true, path: out };
36468
+ if (out && import_node_fs12.default.existsSync(out)) return { available: true, path: out };
36400
36469
  } catch {
36401
36470
  }
36402
36471
  return { available: false };
@@ -36441,9 +36510,9 @@ var CodexAdapter = class {
36441
36510
  };
36442
36511
 
36443
36512
  // src/tools/claude-tui.ts
36444
- var import_node_fs11 = __toESM(require("fs"), 1);
36513
+ var import_node_fs13 = __toESM(require("fs"), 1);
36445
36514
  var import_node_os6 = __toESM(require("os"), 1);
36446
- var import_node_path9 = __toESM(require("path"), 1);
36515
+ var import_node_path10 = __toESM(require("path"), 1);
36447
36516
  var import_headless = __toESM(require_xterm_headless(), 1);
36448
36517
 
36449
36518
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -37509,9 +37578,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
37509
37578
  function jsonlExistsForCtx(ctx) {
37510
37579
  if (!ctx.toolSessionId) return false;
37511
37580
  const home = import_node_os6.default.homedir();
37512
- const file = import_node_path9.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
37581
+ const file = import_node_path10.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
37513
37582
  try {
37514
- return import_node_fs11.default.statSync(file).isFile();
37583
+ return import_node_fs13.default.statSync(file).isFile();
37515
37584
  } catch {
37516
37585
  return false;
37517
37586
  }
@@ -37580,10 +37649,10 @@ var PersonaDispatchManager = class {
37580
37649
  };
37581
37650
 
37582
37651
  // src/dispatch/mcp-config.ts
37583
- var import_node_fs12 = __toESM(require("fs"), 1);
37584
- var import_node_path10 = __toESM(require("path"), 1);
37652
+ var import_node_fs14 = __toESM(require("fs"), 1);
37653
+ var import_node_path11 = __toESM(require("path"), 1);
37585
37654
  function dispatchMcpConfigPath(dataDir) {
37586
- return import_node_path10.default.join(dataDir, "dispatch.mcp.json");
37655
+ return import_node_path11.default.join(dataDir, "dispatch.mcp.json");
37587
37656
  }
37588
37657
  function writeDispatchMcpConfig(args) {
37589
37658
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -37598,8 +37667,8 @@ function writeDispatchMcpConfig(args) {
37598
37667
  }
37599
37668
  }
37600
37669
  };
37601
- import_node_fs12.default.mkdirSync(args.dataDir, { recursive: true });
37602
- import_node_fs12.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
37670
+ import_node_fs14.default.mkdirSync(args.dataDir, { recursive: true });
37671
+ import_node_fs14.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
37603
37672
  return cfgPath;
37604
37673
  }
37605
37674
 
@@ -37855,13 +37924,13 @@ function mapSkillsListResponse(res) {
37855
37924
  const r = s ?? {};
37856
37925
  const name = str3(r.name);
37857
37926
  if (!name) continue;
37858
- const path59 = str3(r.path);
37927
+ const path60 = str3(r.path);
37859
37928
  const description = str3(r.description);
37860
37929
  const isPlugin = name.includes(":");
37861
37930
  out.push({
37862
37931
  name,
37863
37932
  source: isPlugin ? "plugin" : "project",
37864
- ...path59 ? { path: path59 } : {},
37933
+ ...path60 ? { path: path60 } : {},
37865
37934
  ...description ? { description } : {},
37866
37935
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
37867
37936
  });
@@ -37900,23 +37969,23 @@ async function listCodexSkills(cwd, deps = {}) {
37900
37969
  }
37901
37970
 
37902
37971
  // src/workspace/browser.ts
37903
- var import_node_fs13 = __toESM(require("fs"), 1);
37972
+ var import_node_fs15 = __toESM(require("fs"), 1);
37904
37973
  var import_node_os7 = __toESM(require("os"), 1);
37905
- var import_node_path11 = __toESM(require("path"), 1);
37974
+ var import_node_path12 = __toESM(require("path"), 1);
37906
37975
  init_protocol();
37907
37976
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
37908
37977
  function resolveInsideCwd(cwd, subpath) {
37909
- const absCwd = import_node_path11.default.resolve(cwd);
37910
- const joined = import_node_path11.default.resolve(absCwd, subpath ?? ".");
37911
- const rel = import_node_path11.default.relative(absCwd, joined);
37912
- if (rel.startsWith("..") || import_node_path11.default.isAbsolute(rel)) {
37978
+ const absCwd = import_node_path12.default.resolve(cwd);
37979
+ const joined = import_node_path12.default.resolve(absCwd, subpath ?? ".");
37980
+ const rel = import_node_path12.default.relative(absCwd, joined);
37981
+ if (rel.startsWith("..") || import_node_path12.default.isAbsolute(rel)) {
37913
37982
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
37914
37983
  }
37915
37984
  return joined;
37916
37985
  }
37917
37986
  function ensureCwd(cwd) {
37918
37987
  try {
37919
- const stat = import_node_fs13.default.statSync(cwd);
37988
+ const stat = import_node_fs15.default.statSync(cwd);
37920
37989
  if (!stat.isDirectory()) {
37921
37990
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
37922
37991
  }
@@ -37930,7 +37999,7 @@ var WorkspaceBrowser = class {
37930
37999
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os7.default.homedir();
37931
38000
  ensureCwd(cwd);
37932
38001
  const full = resolveInsideCwd(cwd, args.path);
37933
- const dirents = import_node_fs13.default.readdirSync(full, { withFileTypes: true });
38002
+ const dirents = import_node_fs15.default.readdirSync(full, { withFileTypes: true });
37934
38003
  const entries = [];
37935
38004
  for (const d of dirents) {
37936
38005
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -37940,7 +38009,7 @@ var WorkspaceBrowser = class {
37940
38009
  mtime: ""
37941
38010
  };
37942
38011
  try {
37943
- const st = import_node_fs13.default.statSync(import_node_path11.default.join(full, d.name));
38012
+ const st = import_node_fs15.default.statSync(import_node_path12.default.join(full, d.name));
37944
38013
  entry.mtime = new Date(st.mtimeMs).toISOString();
37945
38014
  if (d.isFile()) entry.size = st.size;
37946
38015
  } catch {
@@ -37956,14 +38025,14 @@ var WorkspaceBrowser = class {
37956
38025
  read(args) {
37957
38026
  ensureCwd(args.cwd);
37958
38027
  const full = resolveInsideCwd(args.cwd, args.path);
37959
- const st = import_node_fs13.default.statSync(full);
38028
+ const st = import_node_fs15.default.statSync(full);
37960
38029
  if (!st.isFile()) {
37961
38030
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
37962
38031
  }
37963
38032
  if (st.size > MAX_FILE_BYTES) {
37964
38033
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
37965
38034
  }
37966
- const buf = import_node_fs13.default.readFileSync(full);
38035
+ const buf = import_node_fs15.default.readFileSync(full);
37967
38036
  const isBinary = buf.includes(0);
37968
38037
  if (isBinary) {
37969
38038
  return {
@@ -37985,20 +38054,20 @@ var WorkspaceBrowser = class {
37985
38054
  };
37986
38055
 
37987
38056
  // src/skills/agents-scanner.ts
37988
- var import_node_fs14 = __toESM(require("fs"), 1);
38057
+ var import_node_fs16 = __toESM(require("fs"), 1);
37989
38058
  var import_node_os8 = __toESM(require("os"), 1);
37990
- var import_node_path12 = __toESM(require("path"), 1);
38059
+ var import_node_path13 = __toESM(require("path"), 1);
37991
38060
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
37992
38061
  function isDirLikeSync2(p2) {
37993
38062
  try {
37994
- return import_node_fs14.default.statSync(p2).isDirectory();
38063
+ return import_node_fs16.default.statSync(p2).isDirectory();
37995
38064
  } catch {
37996
38065
  return false;
37997
38066
  }
37998
38067
  }
37999
38068
  function fileExistsSync(p2) {
38000
38069
  try {
38001
- return import_node_fs14.default.statSync(p2).isFile();
38070
+ return import_node_fs16.default.statSync(p2).isFile();
38002
38071
  } catch {
38003
38072
  return false;
38004
38073
  }
@@ -38006,7 +38075,7 @@ function fileExistsSync(p2) {
38006
38075
  function parseAgentFile(filePath) {
38007
38076
  let content;
38008
38077
  try {
38009
- content = import_node_fs14.default.readFileSync(filePath, "utf8");
38078
+ content = import_node_fs16.default.readFileSync(filePath, "utf8");
38010
38079
  } catch {
38011
38080
  return {};
38012
38081
  }
@@ -38019,16 +38088,16 @@ function parseAgentFile(filePath) {
38019
38088
  function scanAgentsDir(dir, source, seen, out) {
38020
38089
  let entries;
38021
38090
  try {
38022
- entries = import_node_fs14.default.readdirSync(dir, { withFileTypes: true });
38091
+ entries = import_node_fs16.default.readdirSync(dir, { withFileTypes: true });
38023
38092
  } catch {
38024
38093
  return;
38025
38094
  }
38026
38095
  for (const ent of entries) {
38027
38096
  if (!ent.name.endsWith(".md")) continue;
38028
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path12.default.join(dir, ent.name)))) {
38097
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path13.default.join(dir, ent.name)))) {
38029
38098
  continue;
38030
38099
  }
38031
- const filePath = import_node_path12.default.join(dir, ent.name);
38100
+ const filePath = import_node_path13.default.join(dir, ent.name);
38032
38101
  const baseName = ent.name.replace(/\.md$/, "");
38033
38102
  if (seen.has(baseName)) continue;
38034
38103
  seen.add(baseName);
@@ -38046,12 +38115,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
38046
38115
  function walk2(dir, namespaces) {
38047
38116
  let entries;
38048
38117
  try {
38049
- entries = import_node_fs14.default.readdirSync(dir, { withFileTypes: true });
38118
+ entries = import_node_fs16.default.readdirSync(dir, { withFileTypes: true });
38050
38119
  } catch {
38051
38120
  return;
38052
38121
  }
38053
38122
  for (const ent of entries) {
38054
- const childPath = import_node_path12.default.join(dir, ent.name);
38123
+ const childPath = import_node_path13.default.join(dir, ent.name);
38055
38124
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
38056
38125
  walk2(childPath, [...namespaces, ent.name]);
38057
38126
  continue;
@@ -38076,13 +38145,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
38076
38145
  walk2(root, []);
38077
38146
  }
38078
38147
  function readInstalledPlugins2(home) {
38079
- const pluginsDir = import_node_path12.default.join(home, ".claude", "plugins");
38080
- const v2 = import_node_path12.default.join(pluginsDir, "installed_plugins_v2.json");
38081
- const v1 = import_node_path12.default.join(pluginsDir, "installed_plugins.json");
38148
+ const pluginsDir = import_node_path13.default.join(home, ".claude", "plugins");
38149
+ const v2 = import_node_path13.default.join(pluginsDir, "installed_plugins_v2.json");
38150
+ const v1 = import_node_path13.default.join(pluginsDir, "installed_plugins.json");
38082
38151
  let raw = null;
38083
38152
  for (const candidate of [v2, v1]) {
38084
38153
  try {
38085
- raw = import_node_fs14.default.readFileSync(candidate, "utf8");
38154
+ raw = import_node_fs16.default.readFileSync(candidate, "utf8");
38086
38155
  break;
38087
38156
  } catch {
38088
38157
  }
@@ -38107,19 +38176,19 @@ function readInstalledPlugins2(home) {
38107
38176
  return out;
38108
38177
  }
38109
38178
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
38110
- let cur = import_node_path12.default.resolve(startCwd);
38111
- const fsRoot = import_node_path12.default.parse(cur).root;
38179
+ let cur = import_node_path13.default.resolve(startCwd);
38180
+ const fsRoot = import_node_path13.default.parse(cur).root;
38112
38181
  while (true) {
38113
- scanAgentsDir(import_node_path12.default.join(cur, ".claude", "agents"), "project", seen, out);
38182
+ scanAgentsDir(import_node_path13.default.join(cur, ".claude", "agents"), "project", seen, out);
38114
38183
  let hasGit = false;
38115
38184
  try {
38116
- hasGit = import_node_fs14.default.existsSync(import_node_path12.default.join(cur, ".git"));
38185
+ hasGit = import_node_fs16.default.existsSync(import_node_path13.default.join(cur, ".git"));
38117
38186
  } catch {
38118
38187
  }
38119
38188
  if (hasGit) return;
38120
38189
  if (cur === home) return;
38121
38190
  if (cur === fsRoot) return;
38122
- const parent = import_node_path12.default.dirname(cur);
38191
+ const parent = import_node_path13.default.dirname(cur);
38123
38192
  if (parent === cur) return;
38124
38193
  cur = parent;
38125
38194
  }
@@ -38154,7 +38223,7 @@ var AgentsScanner = class {
38154
38223
  }
38155
38224
  const fsBlock = [];
38156
38225
  scanAgentsDir(
38157
- import_node_path12.default.join(this.home, ".claude", "agents"),
38226
+ import_node_path13.default.join(this.home, ".claude", "agents"),
38158
38227
  "global",
38159
38228
  seen,
38160
38229
  fsBlock
@@ -38168,7 +38237,7 @@ var AgentsScanner = class {
38168
38237
  ...this.extraPluginRoots
38169
38238
  ];
38170
38239
  for (const { name, root } of plugins) {
38171
- const agentsRoot = import_node_path12.default.join(root, "agents");
38240
+ const agentsRoot = import_node_path13.default.join(root, "agents");
38172
38241
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
38173
38242
  }
38174
38243
  return [...builtinBlock, ...fsBlock];
@@ -38176,15 +38245,15 @@ var AgentsScanner = class {
38176
38245
  };
38177
38246
 
38178
38247
  // src/observer/session-observer.ts
38179
- var import_node_fs16 = __toESM(require("fs"), 1);
38248
+ var import_node_fs18 = __toESM(require("fs"), 1);
38180
38249
  var import_node_os10 = __toESM(require("os"), 1);
38181
- var import_node_path14 = __toESM(require("path"), 1);
38250
+ var import_node_path15 = __toESM(require("path"), 1);
38182
38251
  init_claude_history();
38183
38252
 
38184
38253
  // src/observer/subagent-meta-observer.ts
38185
- var import_node_fs15 = __toESM(require("fs"), 1);
38254
+ var import_node_fs17 = __toESM(require("fs"), 1);
38186
38255
  var import_node_os9 = __toESM(require("os"), 1);
38187
- var import_node_path13 = __toESM(require("path"), 1);
38256
+ var import_node_path14 = __toESM(require("path"), 1);
38188
38257
  init_claude_history();
38189
38258
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
38190
38259
  var SubagentMetaObserver = class {
@@ -38197,7 +38266,7 @@ var SubagentMetaObserver = class {
38197
38266
  watches = /* @__PURE__ */ new Map();
38198
38267
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
38199
38268
  resolveSubagentDir(cwd, toolSessionId) {
38200
- return import_node_path13.default.join(
38269
+ return import_node_path14.default.join(
38201
38270
  this.home,
38202
38271
  ".claude",
38203
38272
  "projects",
@@ -38227,7 +38296,7 @@ var SubagentMetaObserver = class {
38227
38296
  attachWatcher(w2) {
38228
38297
  if (w2.watcher) return;
38229
38298
  try {
38230
- w2.watcher = import_node_fs15.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
38299
+ w2.watcher = import_node_fs17.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
38231
38300
  if (!name) return;
38232
38301
  const m2 = META_RE.exec(String(name));
38233
38302
  if (!m2) return;
@@ -38239,7 +38308,7 @@ var SubagentMetaObserver = class {
38239
38308
  scan(w2) {
38240
38309
  let entries;
38241
38310
  try {
38242
- entries = import_node_fs15.default.readdirSync(w2.dirPath);
38311
+ entries = import_node_fs17.default.readdirSync(w2.dirPath);
38243
38312
  } catch {
38244
38313
  return;
38245
38314
  }
@@ -38253,10 +38322,10 @@ var SubagentMetaObserver = class {
38253
38322
  if (!m2) return;
38254
38323
  const agentId = m2[1];
38255
38324
  if (w2.emitted.has(agentId)) return;
38256
- const file = import_node_path13.default.join(w2.dirPath, name);
38325
+ const file = import_node_path14.default.join(w2.dirPath, name);
38257
38326
  let raw;
38258
38327
  try {
38259
- raw = import_node_fs15.default.readFileSync(file, "utf8");
38328
+ raw = import_node_fs17.default.readFileSync(file, "utf8");
38260
38329
  } catch {
38261
38330
  return;
38262
38331
  }
@@ -38313,14 +38382,14 @@ var SessionObserver = class {
38313
38382
  metaObserver;
38314
38383
  resolveJsonlPath(cwd, toolSessionId, override) {
38315
38384
  if (override) return override;
38316
- return import_node_path14.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
38385
+ return import_node_path15.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
38317
38386
  }
38318
38387
  start(args) {
38319
38388
  this.stop(args.sessionId);
38320
38389
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
38321
38390
  let size = 0;
38322
38391
  try {
38323
- size = import_node_fs16.default.statSync(filePath).size;
38392
+ size = import_node_fs18.default.statSync(filePath).size;
38324
38393
  } catch {
38325
38394
  }
38326
38395
  const w2 = {
@@ -38334,10 +38403,10 @@ var SessionObserver = class {
38334
38403
  prevIsRejectSentinel: false
38335
38404
  };
38336
38405
  try {
38337
- import_node_fs16.default.mkdirSync(import_node_path14.default.dirname(filePath), { recursive: true });
38406
+ import_node_fs18.default.mkdirSync(import_node_path15.default.dirname(filePath), { recursive: true });
38338
38407
  } catch {
38339
38408
  }
38340
- w2.watcher = import_node_fs16.default.watch(import_node_path14.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
38409
+ w2.watcher = import_node_fs18.default.watch(import_node_path15.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
38341
38410
  if (!changedName || !filePath.endsWith(changedName)) return;
38342
38411
  this.poll(w2);
38343
38412
  });
@@ -38360,7 +38429,7 @@ var SessionObserver = class {
38360
38429
  // 异常静默吞,不阻塞 watcher 启动
38361
38430
  hydrateMetaTail(w2, maxLines = 200) {
38362
38431
  try {
38363
- const raw = import_node_fs16.default.readFileSync(w2.filePath, "utf8");
38432
+ const raw = import_node_fs18.default.readFileSync(w2.filePath, "utf8");
38364
38433
  if (!raw) return;
38365
38434
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
38366
38435
  if (allLines.length === 0) return;
@@ -38384,7 +38453,7 @@ var SessionObserver = class {
38384
38453
  poll(w2) {
38385
38454
  let size = 0;
38386
38455
  try {
38387
- size = import_node_fs16.default.statSync(w2.filePath).size;
38456
+ size = import_node_fs18.default.statSync(w2.filePath).size;
38388
38457
  } catch {
38389
38458
  return;
38390
38459
  }
@@ -38393,11 +38462,11 @@ var SessionObserver = class {
38393
38462
  w2.buf = "";
38394
38463
  }
38395
38464
  if (size === w2.lastSize) return;
38396
- const fd = import_node_fs16.default.openSync(w2.filePath, "r");
38465
+ const fd = import_node_fs18.default.openSync(w2.filePath, "r");
38397
38466
  try {
38398
38467
  const len = size - w2.lastSize;
38399
38468
  const buf = Buffer.alloc(len);
38400
- import_node_fs16.default.readSync(fd, buf, 0, len, w2.lastSize);
38469
+ import_node_fs18.default.readSync(fd, buf, 0, len, w2.lastSize);
38401
38470
  w2.lastSize = size;
38402
38471
  w2.buf += buf.toString("utf8");
38403
38472
  let newlineIndex;
@@ -38420,7 +38489,7 @@ var SessionObserver = class {
38420
38489
  }
38421
38490
  }
38422
38491
  } finally {
38423
- import_node_fs16.default.closeSync(fd);
38492
+ import_node_fs18.default.closeSync(fd);
38424
38493
  }
38425
38494
  }
38426
38495
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -39143,14 +39212,14 @@ async function authenticate(token, deps) {
39143
39212
  }
39144
39213
 
39145
39214
  // src/permission/capability-store.ts
39146
- var fs19 = __toESM(require("fs"), 1);
39147
- var path19 = __toESM(require("path"), 1);
39215
+ var fs21 = __toESM(require("fs"), 1);
39216
+ var path20 = __toESM(require("path"), 1);
39148
39217
  var CAPABILITIES_FILE_NAME = "capabilities.json";
39149
39218
  var FILE_VERSION = 1;
39150
39219
  var CapabilityStore = class {
39151
39220
  constructor(dataDir) {
39152
39221
  this.dataDir = dataDir;
39153
- fs19.mkdirSync(dataDir, { recursive: true });
39222
+ fs21.mkdirSync(dataDir, { recursive: true });
39154
39223
  this.cache = this.readFromDisk();
39155
39224
  }
39156
39225
  dataDir;
@@ -39174,13 +39243,13 @@ var CapabilityStore = class {
39174
39243
  this.flush();
39175
39244
  }
39176
39245
  filePath() {
39177
- return path19.join(this.dataDir, CAPABILITIES_FILE_NAME);
39246
+ return path20.join(this.dataDir, CAPABILITIES_FILE_NAME);
39178
39247
  }
39179
39248
  readFromDisk() {
39180
39249
  const file = this.filePath();
39181
39250
  let raw;
39182
39251
  try {
39183
- raw = fs19.readFileSync(file, "utf8");
39252
+ raw = fs21.readFileSync(file, "utf8");
39184
39253
  } catch (err) {
39185
39254
  if (err?.code === "ENOENT") return [];
39186
39255
  return [];
@@ -39208,10 +39277,10 @@ var CapabilityStore = class {
39208
39277
  }
39209
39278
  atomicWrite(file, content) {
39210
39279
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
39211
- fs19.writeFileSync(tmp, content, { mode: 384 });
39212
- fs19.renameSync(tmp, file);
39280
+ fs21.writeFileSync(tmp, content, { mode: 384 });
39281
+ fs21.renameSync(tmp, file);
39213
39282
  try {
39214
- fs19.chmodSync(file, 384);
39283
+ fs21.chmodSync(file, 384);
39215
39284
  } catch {
39216
39285
  }
39217
39286
  }
@@ -39304,14 +39373,14 @@ var CapabilityManager = class {
39304
39373
  };
39305
39374
 
39306
39375
  // src/permission/cleanup.ts
39307
- var fs20 = __toESM(require("fs"), 1);
39376
+ var fs22 = __toESM(require("fs"), 1);
39308
39377
  function cleanupGuestSessionsForCapability(cap, factory) {
39309
39378
  const removed = [];
39310
39379
  for (const g2 of cap.grants) {
39311
39380
  if (g2.resource.type !== "persona") continue;
39312
39381
  const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
39313
39382
  try {
39314
- fs20.rmSync(dir, { recursive: true, force: true });
39383
+ fs22.rmSync(dir, { recursive: true, force: true });
39315
39384
  removed.push(dir);
39316
39385
  } catch {
39317
39386
  }
@@ -39320,13 +39389,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
39320
39389
  }
39321
39390
 
39322
39391
  // src/inbox/inbox-store.ts
39323
- var fs21 = __toESM(require("fs"), 1);
39324
- var path20 = __toESM(require("path"), 1);
39392
+ var fs23 = __toESM(require("fs"), 1);
39393
+ var path21 = __toESM(require("path"), 1);
39325
39394
  var INBOX_SUBDIR = "inbox";
39326
39395
  var InboxStore = class {
39327
39396
  constructor(dataDir) {
39328
39397
  this.dataDir = dataDir;
39329
- fs21.mkdirSync(this.dirPath(), { recursive: true });
39398
+ fs23.mkdirSync(this.dirPath(), { recursive: true });
39330
39399
  }
39331
39400
  dataDir;
39332
39401
  /**
@@ -39338,7 +39407,7 @@ var InboxStore = class {
39338
39407
  const file = this.filePath(peerDeviceId);
39339
39408
  let raw;
39340
39409
  try {
39341
- raw = fs21.readFileSync(file, "utf8");
39410
+ raw = fs23.readFileSync(file, "utf8");
39342
39411
  } catch (err) {
39343
39412
  if (err?.code === "ENOENT") return [];
39344
39413
  return [];
@@ -39354,7 +39423,7 @@ var InboxStore = class {
39354
39423
  const dir = this.dirPath();
39355
39424
  let entries;
39356
39425
  try {
39357
- entries = fs21.readdirSync(dir);
39426
+ entries = fs23.readdirSync(dir);
39358
39427
  } catch (err) {
39359
39428
  if (err?.code === "ENOENT") return [];
39360
39429
  return [];
@@ -39370,9 +39439,9 @@ var InboxStore = class {
39370
39439
  if (existing.some((m2) => m2.id === message.id)) return;
39371
39440
  const file = this.filePath(message.peerDeviceId);
39372
39441
  const line = JSON.stringify(message) + "\n";
39373
- fs21.appendFileSync(file, line, { mode: 384 });
39442
+ fs23.appendFileSync(file, line, { mode: 384 });
39374
39443
  try {
39375
- fs21.chmodSync(file, 384);
39444
+ fs23.chmodSync(file, 384);
39376
39445
  } catch {
39377
39446
  }
39378
39447
  }
@@ -39402,7 +39471,7 @@ var InboxStore = class {
39402
39471
  removeByPeerDeviceId(peerDeviceId) {
39403
39472
  const file = this.filePath(peerDeviceId);
39404
39473
  try {
39405
- fs21.unlinkSync(file);
39474
+ fs23.unlinkSync(file);
39406
39475
  } catch (err) {
39407
39476
  if (err?.code === "ENOENT") return;
39408
39477
  }
@@ -39411,18 +39480,18 @@ var InboxStore = class {
39411
39480
  const file = this.filePath(peerDeviceId);
39412
39481
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
39413
39482
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
39414
- fs21.writeFileSync(tmp, content, { mode: 384 });
39415
- fs21.renameSync(tmp, file);
39483
+ fs23.writeFileSync(tmp, content, { mode: 384 });
39484
+ fs23.renameSync(tmp, file);
39416
39485
  try {
39417
- fs21.chmodSync(file, 384);
39486
+ fs23.chmodSync(file, 384);
39418
39487
  } catch {
39419
39488
  }
39420
39489
  }
39421
39490
  dirPath() {
39422
- return path20.join(this.dataDir, INBOX_SUBDIR);
39491
+ return path21.join(this.dataDir, INBOX_SUBDIR);
39423
39492
  }
39424
39493
  filePath(peerDeviceId) {
39425
- return path20.join(this.dirPath(), `${peerDeviceId}.jsonl`);
39494
+ return path21.join(this.dirPath(), `${peerDeviceId}.jsonl`);
39426
39495
  }
39427
39496
  };
39428
39497
  function parseAllLines(raw) {
@@ -39509,8 +39578,8 @@ var InboxManager = class {
39509
39578
  };
39510
39579
 
39511
39580
  // src/state/contact-store.ts
39512
- var fs22 = __toESM(require("fs"), 1);
39513
- var path21 = __toESM(require("path"), 1);
39581
+ var fs24 = __toESM(require("fs"), 1);
39582
+ var path22 = __toESM(require("path"), 1);
39514
39583
  var FILE_NAME = "contacts.json";
39515
39584
  var ContactStore = class {
39516
39585
  constructor(dataDir) {
@@ -39520,10 +39589,10 @@ var ContactStore = class {
39520
39589
  contacts = /* @__PURE__ */ new Map();
39521
39590
  load() {
39522
39591
  this.contacts.clear();
39523
- const file = path21.join(this.dataDir, FILE_NAME);
39592
+ const file = path22.join(this.dataDir, FILE_NAME);
39524
39593
  let raw;
39525
39594
  try {
39526
- raw = fs22.readFileSync(file, "utf8");
39595
+ raw = fs24.readFileSync(file, "utf8");
39527
39596
  } catch (err) {
39528
39597
  if (err?.code !== "ENOENT") this.renameBak(file);
39529
39598
  return;
@@ -39566,20 +39635,20 @@ var ContactStore = class {
39566
39635
  return existed;
39567
39636
  }
39568
39637
  flush() {
39569
- const file = path21.join(this.dataDir, FILE_NAME);
39638
+ const file = path22.join(this.dataDir, FILE_NAME);
39570
39639
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
39571
39640
  const content = JSON.stringify(
39572
39641
  { contacts: Array.from(this.contacts.values()) },
39573
39642
  null,
39574
39643
  2
39575
39644
  );
39576
- fs22.mkdirSync(this.dataDir, { recursive: true });
39577
- fs22.writeFileSync(tmp, content, { mode: 384 });
39578
- fs22.renameSync(tmp, file);
39645
+ fs24.mkdirSync(this.dataDir, { recursive: true });
39646
+ fs24.writeFileSync(tmp, content, { mode: 384 });
39647
+ fs24.renameSync(tmp, file);
39579
39648
  }
39580
39649
  renameBak(file) {
39581
39650
  try {
39582
- fs22.renameSync(file, `${file}.bak`);
39651
+ fs24.renameSync(file, `${file}.bak`);
39583
39652
  } catch {
39584
39653
  }
39585
39654
  }
@@ -39729,61 +39798,61 @@ async function autoReverseContact(args) {
39729
39798
  }
39730
39799
 
39731
39800
  // src/migrations/2026-05-20-flatten-sessions.ts
39732
- var fs23 = __toESM(require("fs"), 1);
39733
- var path22 = __toESM(require("path"), 1);
39801
+ var fs25 = __toESM(require("fs"), 1);
39802
+ var path23 = __toESM(require("path"), 1);
39734
39803
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
39735
39804
  function migrateFlattenSessions(opts) {
39736
39805
  const dataDir = opts.dataDir;
39737
39806
  const now = opts.now ?? Date.now;
39738
- const sessionsDir = path22.join(dataDir, "sessions");
39739
- const flagPath = path22.join(sessionsDir, MIGRATION_FLAG_NAME);
39807
+ const sessionsDir = path23.join(dataDir, "sessions");
39808
+ const flagPath = path23.join(sessionsDir, MIGRATION_FLAG_NAME);
39740
39809
  if (existsSync3(flagPath)) {
39741
39810
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
39742
39811
  }
39743
39812
  let movedBare = 0;
39744
39813
  let movedVmOwner = 0;
39745
39814
  let archivedListener = 0;
39746
- const defaultDir = path22.join(sessionsDir, "default");
39815
+ const defaultDir = path23.join(sessionsDir, "default");
39747
39816
  if (existsSync3(defaultDir)) {
39748
39817
  for (const entry of readdirSafe(defaultDir)) {
39749
39818
  if (!entry.endsWith(".json")) continue;
39750
- const src = path22.join(defaultDir, entry);
39751
- const dst = path22.join(sessionsDir, entry);
39752
- fs23.renameSync(src, dst);
39819
+ const src = path23.join(defaultDir, entry);
39820
+ const dst = path23.join(sessionsDir, entry);
39821
+ fs25.renameSync(src, dst);
39753
39822
  movedBare += 1;
39754
39823
  }
39755
39824
  rmdirIfEmpty(defaultDir);
39756
39825
  }
39757
39826
  for (const pid of readdirSafe(sessionsDir)) {
39758
- const personaDir = path22.join(sessionsDir, pid);
39827
+ const personaDir = path23.join(sessionsDir, pid);
39759
39828
  if (!isDir(personaDir)) continue;
39760
39829
  if (pid === "default") continue;
39761
- const ownerSrc = path22.join(personaDir, "owner");
39830
+ const ownerSrc = path23.join(personaDir, "owner");
39762
39831
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
39763
- const ownerDst = path22.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
39764
- fs23.mkdirSync(ownerDst, { recursive: true });
39832
+ const ownerDst = path23.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
39833
+ fs25.mkdirSync(ownerDst, { recursive: true });
39765
39834
  for (const file of readdirSafe(ownerSrc)) {
39766
39835
  if (!file.endsWith(".json")) continue;
39767
- fs23.renameSync(path22.join(ownerSrc, file), path22.join(ownerDst, file));
39836
+ fs25.renameSync(path23.join(ownerSrc, file), path23.join(ownerDst, file));
39768
39837
  movedVmOwner += 1;
39769
39838
  }
39770
39839
  rmdirIfEmpty(ownerSrc);
39771
39840
  }
39772
- const listenerSrc = path22.join(personaDir, "listener");
39841
+ const listenerSrc = path23.join(personaDir, "listener");
39773
39842
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
39774
- const archiveDst = path22.join(dataDir, ".legacy", `listener-${pid}`);
39775
- fs23.mkdirSync(archiveDst, { recursive: true });
39843
+ const archiveDst = path23.join(dataDir, ".legacy", `listener-${pid}`);
39844
+ fs25.mkdirSync(archiveDst, { recursive: true });
39776
39845
  for (const file of readdirSafe(listenerSrc)) {
39777
39846
  if (!file.endsWith(".json")) continue;
39778
- fs23.renameSync(path22.join(listenerSrc, file), path22.join(archiveDst, file));
39847
+ fs25.renameSync(path23.join(listenerSrc, file), path23.join(archiveDst, file));
39779
39848
  archivedListener += 1;
39780
39849
  }
39781
39850
  rmdirIfEmpty(listenerSrc);
39782
39851
  }
39783
39852
  rmdirIfEmpty(personaDir);
39784
39853
  }
39785
- fs23.mkdirSync(sessionsDir, { recursive: true });
39786
- fs23.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
39854
+ fs25.mkdirSync(sessionsDir, { recursive: true });
39855
+ fs25.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
39787
39856
  return {
39788
39857
  skipped: false,
39789
39858
  flagWritten: true,
@@ -39794,7 +39863,7 @@ function migrateFlattenSessions(opts) {
39794
39863
  }
39795
39864
  function existsSync3(p2) {
39796
39865
  try {
39797
- fs23.statSync(p2);
39866
+ fs25.statSync(p2);
39798
39867
  return true;
39799
39868
  } catch {
39800
39869
  return false;
@@ -39802,31 +39871,31 @@ function existsSync3(p2) {
39802
39871
  }
39803
39872
  function isDir(p2) {
39804
39873
  try {
39805
- return fs23.statSync(p2).isDirectory();
39874
+ return fs25.statSync(p2).isDirectory();
39806
39875
  } catch {
39807
39876
  return false;
39808
39877
  }
39809
39878
  }
39810
39879
  function readdirSafe(p2) {
39811
39880
  try {
39812
- return fs23.readdirSync(p2);
39881
+ return fs25.readdirSync(p2);
39813
39882
  } catch {
39814
39883
  return [];
39815
39884
  }
39816
39885
  }
39817
39886
  function rmdirIfEmpty(p2) {
39818
39887
  try {
39819
- fs23.rmdirSync(p2);
39888
+ fs25.rmdirSync(p2);
39820
39889
  } catch {
39821
39890
  }
39822
39891
  }
39823
39892
 
39824
39893
  // src/transport/http-router.ts
39825
- var import_node_fs18 = __toESM(require("fs"), 1);
39826
- var import_node_path18 = __toESM(require("path"), 1);
39894
+ var import_node_fs20 = __toESM(require("fs"), 1);
39895
+ var import_node_path19 = __toESM(require("path"), 1);
39827
39896
 
39828
39897
  // src/attachment/mime.ts
39829
- var import_node_path15 = __toESM(require("path"), 1);
39898
+ var import_node_path16 = __toESM(require("path"), 1);
39830
39899
  var TEXT_PLAIN = "text/plain; charset=utf-8";
39831
39900
  var EXT_TO_NATIVE_MIME = {
39832
39901
  // 图片
@@ -39933,7 +40002,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
39933
40002
  ".mk"
39934
40003
  ]);
39935
40004
  function lookupMime(filePathOrName) {
39936
- const ext = import_node_path15.default.extname(filePathOrName).toLowerCase();
40005
+ const ext = import_node_path16.default.extname(filePathOrName).toLowerCase();
39937
40006
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
39938
40007
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
39939
40008
  return "application/octet-stream";
@@ -39964,11 +40033,11 @@ function signUrlParts(secret, absPath, ttlSeconds, now = Date.now) {
39964
40033
  const s = base64urlEncode(computeSig(secret, absPath, e));
39965
40034
  return { absPath, e, s };
39966
40035
  }
39967
- function buildSignedFileUrl(httpBaseUrl, parts) {
40036
+ function buildSignedFileUrl(httpBaseUrl, parts, prefix = "/files") {
39968
40037
  const encodedPath = encodeAbsPathForUrl(parts.absPath);
39969
40038
  const query = parts.e === null ? `s=${encodeURIComponent(parts.s)}` : `e=${parts.e}&s=${encodeURIComponent(parts.s)}`;
39970
40039
  const base = httpBaseUrl.endsWith("/") ? httpBaseUrl.slice(0, -1) : httpBaseUrl;
39971
- return `${base}/files${encodedPath}?${query}`;
40040
+ return `${base}${prefix}${encodedPath}?${query}`;
39972
40041
  }
39973
40042
  function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
39974
40043
  let e;
@@ -40002,8 +40071,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
40002
40071
  }
40003
40072
 
40004
40073
  // src/attachment/upload.ts
40005
- var import_node_fs17 = __toESM(require("fs"), 1);
40006
- var import_node_path16 = __toESM(require("path"), 1);
40074
+ var import_node_fs19 = __toESM(require("fs"), 1);
40075
+ var import_node_path17 = __toESM(require("path"), 1);
40007
40076
  var import_node_crypto5 = __toESM(require("crypto"), 1);
40008
40077
  var import_promises = require("stream/promises");
40009
40078
  var UploadError = class extends Error {
@@ -40015,22 +40084,22 @@ var UploadError = class extends Error {
40015
40084
  code;
40016
40085
  };
40017
40086
  function assertValidFileName(fileName) {
40018
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path16.default.basename(fileName)) {
40087
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path17.default.basename(fileName)) {
40019
40088
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
40020
40089
  }
40021
40090
  }
40022
40091
  var HASH_PREFIX_LEN = 16;
40023
40092
  async function writeUploadedAttachment(args) {
40024
40093
  assertValidFileName(args.fileName);
40025
- const attachmentsRoot = import_node_path16.default.join(args.sessionDir, ".attachments");
40094
+ const attachmentsRoot = import_node_path17.default.join(args.sessionDir, ".attachments");
40026
40095
  try {
40027
- import_node_fs17.default.mkdirSync(attachmentsRoot, { recursive: true });
40096
+ import_node_fs19.default.mkdirSync(attachmentsRoot, { recursive: true });
40028
40097
  } catch (err) {
40029
40098
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
40030
40099
  }
40031
40100
  const hasher = import_node_crypto5.default.createHash("sha256");
40032
40101
  let actualSize = 0;
40033
- const tmpPath = import_node_path16.default.join(
40102
+ const tmpPath = import_node_path17.default.join(
40034
40103
  attachmentsRoot,
40035
40104
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto5.default.randomBytes(4).toString("hex")}`
40036
40105
  );
@@ -40045,18 +40114,18 @@ async function writeUploadedAttachment(args) {
40045
40114
  yield buf;
40046
40115
  }
40047
40116
  },
40048
- import_node_fs17.default.createWriteStream(tmpPath, { mode: 384 })
40117
+ import_node_fs19.default.createWriteStream(tmpPath, { mode: 384 })
40049
40118
  );
40050
40119
  } catch (err) {
40051
40120
  try {
40052
- import_node_fs17.default.unlinkSync(tmpPath);
40121
+ import_node_fs19.default.unlinkSync(tmpPath);
40053
40122
  } catch {
40054
40123
  }
40055
40124
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
40056
40125
  }
40057
40126
  if (actualSize !== args.contentLength) {
40058
40127
  try {
40059
- import_node_fs17.default.unlinkSync(tmpPath);
40128
+ import_node_fs19.default.unlinkSync(tmpPath);
40060
40129
  } catch {
40061
40130
  }
40062
40131
  throw new UploadError(
@@ -40065,35 +40134,35 @@ async function writeUploadedAttachment(args) {
40065
40134
  );
40066
40135
  }
40067
40136
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
40068
- const hashDir = import_node_path16.default.join(attachmentsRoot, attachmentId);
40137
+ const hashDir = import_node_path17.default.join(attachmentsRoot, attachmentId);
40069
40138
  let finalFileName;
40070
40139
  let hashDirExists = false;
40071
40140
  try {
40072
- hashDirExists = import_node_fs17.default.statSync(hashDir).isDirectory();
40141
+ hashDirExists = import_node_fs19.default.statSync(hashDir).isDirectory();
40073
40142
  } catch {
40074
40143
  }
40075
40144
  if (hashDirExists) {
40076
- const existing = import_node_fs17.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
40145
+ const existing = import_node_fs19.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
40077
40146
  finalFileName = existing[0] ?? args.fileName;
40078
40147
  try {
40079
- import_node_fs17.default.unlinkSync(tmpPath);
40148
+ import_node_fs19.default.unlinkSync(tmpPath);
40080
40149
  } catch {
40081
40150
  }
40082
40151
  } else {
40083
40152
  try {
40084
- import_node_fs17.default.mkdirSync(hashDir, { recursive: true });
40153
+ import_node_fs19.default.mkdirSync(hashDir, { recursive: true });
40085
40154
  finalFileName = args.fileName;
40086
- import_node_fs17.default.renameSync(tmpPath, import_node_path16.default.join(hashDir, finalFileName));
40155
+ import_node_fs19.default.renameSync(tmpPath, import_node_path17.default.join(hashDir, finalFileName));
40087
40156
  } catch (err) {
40088
40157
  try {
40089
- import_node_fs17.default.unlinkSync(tmpPath);
40158
+ import_node_fs19.default.unlinkSync(tmpPath);
40090
40159
  } catch {
40091
40160
  }
40092
40161
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
40093
40162
  }
40094
40163
  }
40095
- const absPath = import_node_path16.default.join(hashDir, finalFileName);
40096
- const relPath = import_node_path16.default.relative(args.sessionDir, absPath);
40164
+ const absPath = import_node_path17.default.join(hashDir, finalFileName);
40165
+ const relPath = import_node_path17.default.relative(args.sessionDir, absPath);
40097
40166
  args.groupFileStore.upsert(args.scope, args.sessionId, {
40098
40167
  relPath: absPath,
40099
40168
  // 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
@@ -40107,7 +40176,7 @@ async function writeUploadedAttachment(args) {
40107
40176
 
40108
40177
  // src/extension/import.ts
40109
40178
  var import_promises2 = __toESM(require("fs/promises"), 1);
40110
- var import_node_path17 = __toESM(require("path"), 1);
40179
+ var import_node_path18 = __toESM(require("path"), 1);
40111
40180
  var import_node_os11 = __toESM(require("os"), 1);
40112
40181
  var import_jszip = __toESM(require_lib3(), 1);
40113
40182
  var ImportError = class extends Error {
@@ -40125,7 +40194,7 @@ async function importZip(buf, root) {
40125
40194
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
40126
40195
  }
40127
40196
  for (const name of Object.keys(zip.files)) {
40128
- if (name.includes("..") || name.startsWith("/") || import_node_path17.default.isAbsolute(name)) {
40197
+ if (name.includes("..") || name.startsWith("/") || import_node_path18.default.isAbsolute(name)) {
40129
40198
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
40130
40199
  }
40131
40200
  }
@@ -40158,7 +40227,7 @@ async function importZip(buf, root) {
40158
40227
  );
40159
40228
  }
40160
40229
  }
40161
- const destDir = import_node_path17.default.join(root, manifest.id);
40230
+ const destDir = import_node_path18.default.join(root, manifest.id);
40162
40231
  let destExists = false;
40163
40232
  try {
40164
40233
  await import_promises2.default.access(destDir);
@@ -40168,15 +40237,15 @@ async function importZip(buf, root) {
40168
40237
  if (destExists) {
40169
40238
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
40170
40239
  }
40171
- const stage = await import_promises2.default.mkdtemp(import_node_path17.default.join(import_node_os11.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
40240
+ const stage = await import_promises2.default.mkdtemp(import_node_path18.default.join(import_node_os11.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
40172
40241
  try {
40173
40242
  for (const [name, entry] of Object.entries(zip.files)) {
40174
- const dest = import_node_path17.default.join(stage, name);
40243
+ const dest = import_node_path18.default.join(stage, name);
40175
40244
  if (entry.dir) {
40176
40245
  await import_promises2.default.mkdir(dest, { recursive: true });
40177
40246
  continue;
40178
40247
  }
40179
- await import_promises2.default.mkdir(import_node_path17.default.dirname(dest), { recursive: true });
40248
+ await import_promises2.default.mkdir(import_node_path18.default.dirname(dest), { recursive: true });
40180
40249
  const content = await entry.async("nodebuffer");
40181
40250
  await import_promises2.default.writeFile(dest, content);
40182
40251
  }
@@ -40298,7 +40367,7 @@ function isValidUploadFileName(fileName) {
40298
40367
  if (fileName === "." || fileName === "..") return false;
40299
40368
  if (fileName.startsWith(".")) return false;
40300
40369
  if (fileName.includes("/") || fileName.includes("\\")) return false;
40301
- return fileName === import_node_path18.default.basename(fileName);
40370
+ return fileName === import_node_path19.default.basename(fileName);
40302
40371
  }
40303
40372
  function createHttpRouter(deps) {
40304
40373
  return async (req, res) => {
@@ -40369,7 +40438,7 @@ function createHttpRouter(deps) {
40369
40438
  sendJson(res, 403, { code: "PREVIEW_PORT_FORBIDDEN", message: "preview port not allowed" });
40370
40439
  return true;
40371
40440
  }
40372
- if (!url.pathname.startsWith("/session/") && !url.pathname.startsWith("/files/") && url.pathname !== "/attachments/upload" && url.pathname !== "/extensions/import") {
40441
+ if (!url.pathname.startsWith("/session/") && !url.pathname.startsWith("/files/") && !url.pathname.startsWith("/share/md/") && url.pathname !== "/attachments/upload" && url.pathname !== "/extensions/import") {
40373
40442
  return false;
40374
40443
  }
40375
40444
  if (url.pathname === "/attachments/upload" && req.method === "OPTIONS") {
@@ -40411,6 +40480,45 @@ function createHttpRouter(deps) {
40411
40480
  streamFile(res, r.absPath, deps.logger);
40412
40481
  return true;
40413
40482
  }
40483
+ if (url.pathname.startsWith("/share/md/") && req.method === "GET") {
40484
+ const loader = deps.viewerAssetLoader;
40485
+ if (!loader) {
40486
+ sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "viewer asset not loaded" });
40487
+ return true;
40488
+ }
40489
+ const secret = deps.getSignSecret?.();
40490
+ if (!secret) {
40491
+ sendHtml(res, 501, loader.renderErrorHtml("NOT_IMPLEMENTED", "\u5206\u4EAB\u529F\u80FD\u672A\u542F\u7528\uFF08daemon noAuth \u6A21\u5F0F\uFF09"));
40492
+ return true;
40493
+ }
40494
+ const encodedPath = url.pathname.slice("/share/md".length);
40495
+ let absPath;
40496
+ try {
40497
+ absPath = decodeAbsPathFromUrl(encodedPath);
40498
+ } catch {
40499
+ sendHtml(res, 400, loader.renderErrorHtml("MALFORMED", "\u94FE\u63A5\u683C\u5F0F\u9519\u8BEF"));
40500
+ return true;
40501
+ }
40502
+ const e = url.searchParams.get("e");
40503
+ const s = url.searchParams.get("s") ?? "";
40504
+ const r = verifySignedUrl(secret, absPath, e, s);
40505
+ if (!r.ok) {
40506
+ const statusByCode = {
40507
+ BAD_SIG: 403,
40508
+ EXPIRED: 410,
40509
+ MALFORMED: 400
40510
+ };
40511
+ const msgByCode = {
40512
+ BAD_SIG: "\u94FE\u63A5\u7B7E\u540D\u65E0\u6548\uFF0C\u8BF7\u8054\u7CFB\u5206\u4EAB\u8005\u91CD\u65B0\u751F\u6210",
40513
+ EXPIRED: "\u94FE\u63A5\u5DF2\u8FC7\u671F\uFF0824h \u6709\u6548\u671F\u5DF2\u5230\uFF09\uFF0C\u8BF7\u8054\u7CFB\u5206\u4EAB\u8005\u91CD\u65B0\u751F\u6210",
40514
+ MALFORMED: "\u94FE\u63A5\u683C\u5F0F\u9519\u8BEF"
40515
+ };
40516
+ sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
40517
+ return true;
40518
+ }
40519
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path19.default.basename(r.absPath)));
40520
+ return true;
40521
+ }
40414
40522
  const ctx = deps.authResolver.resolveFromHeader(
40415
40523
  req.headers.authorization,
40416
40524
  req.socket.remoteAddress ?? void 0
@@ -40529,7 +40637,7 @@ function createHttpRouter(deps) {
40529
40637
  return true;
40530
40638
  }
40531
40639
  let absPath;
40532
- if (import_node_path18.default.isAbsolute(pathParam)) {
40640
+ if (import_node_path19.default.isAbsolute(pathParam)) {
40533
40641
  absPath = pathParam;
40534
40642
  } else if (deps.sessionStore) {
40535
40643
  const file = deps.sessionStore.read(sid);
@@ -40537,7 +40645,7 @@ function createHttpRouter(deps) {
40537
40645
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
40538
40646
  return true;
40539
40647
  }
40540
- absPath = import_node_path18.default.join(file.cwd, pathParam);
40648
+ absPath = import_node_path19.default.join(file.cwd, pathParam);
40541
40649
  } else {
40542
40650
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
40543
40651
  return true;
@@ -40614,13 +40722,17 @@ function sendJson(res, status, body, extraHeaders) {
40614
40722
  });
40615
40723
  res.end(JSON.stringify(body));
40616
40724
  }
40725
+ function sendHtml(res, status, body) {
40726
+ res.writeHead(status, { "Content-Type": "text/html; charset=utf-8" });
40727
+ res.end(body);
40728
+ }
40617
40729
  function withCtx(ctx, body) {
40618
40730
  return { ...body, role: ctx.role };
40619
40731
  }
40620
40732
  function streamFile(res, absPath, logger) {
40621
40733
  let stat;
40622
40734
  try {
40623
- stat = import_node_fs18.default.statSync(absPath);
40735
+ stat = import_node_fs20.default.statSync(absPath);
40624
40736
  } catch (err) {
40625
40737
  const code = err?.code;
40626
40738
  if (code === "ENOENT") {
@@ -40635,7 +40747,7 @@ function streamFile(res, absPath, logger) {
40635
40747
  return;
40636
40748
  }
40637
40749
  const mime = lookupMime(absPath);
40638
- const basename = import_node_path18.default.basename(absPath);
40750
+ const basename = import_node_path19.default.basename(absPath);
40639
40751
  res.writeHead(200, {
40640
40752
  "Content-Type": mime,
40641
40753
  "Content-Length": String(stat.size),
@@ -40643,7 +40755,7 @@ function streamFile(res, absPath, logger) {
40643
40755
  // 防止浏览器把任意 mime 当 html 渲染
40644
40756
  "X-Content-Type-Options": "nosniff"
40645
40757
  });
40646
- const stream = import_node_fs18.default.createReadStream(absPath);
40758
+ const stream = import_node_fs20.default.createReadStream(absPath);
40647
40759
  stream.on("error", (err) => {
40648
40760
  logger?.warn("streamFile read error", { absPath, err: err.message });
40649
40761
  res.destroy();
@@ -40652,8 +40764,8 @@ function streamFile(res, absPath, logger) {
40652
40764
  }
40653
40765
 
40654
40766
  // src/attachment/gc.ts
40655
- var import_node_fs19 = __toESM(require("fs"), 1);
40656
- var import_node_path19 = __toESM(require("path"), 1);
40767
+ var import_node_fs21 = __toESM(require("fs"), 1);
40768
+ var import_node_path20 = __toESM(require("path"), 1);
40657
40769
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
40658
40770
  function runAttachmentGc(args) {
40659
40771
  const now = (args.now ?? Date.now)();
@@ -40662,38 +40774,38 @@ function runAttachmentGc(args) {
40662
40774
  for (const { scope, sessionId } of args.sessionScopes) {
40663
40775
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
40664
40776
  if (entry.stale) continue;
40665
- if (import_node_path19.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
40777
+ if (import_node_path20.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
40666
40778
  }
40667
40779
  }
40668
40780
  for (const { scope, sessionId } of args.sessionScopes) {
40669
- const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path19.default.join(
40781
+ const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path20.default.join(
40670
40782
  args.dataDir,
40671
40783
  "sessions",
40672
40784
  ...scopeSubPath(scope).map(safeFileName),
40673
40785
  safeFileName(sessionId)
40674
40786
  );
40675
- const attRoot = import_node_path19.default.join(sessionDir, ".attachments");
40787
+ const attRoot = import_node_path20.default.join(sessionDir, ".attachments");
40676
40788
  let hashDirs;
40677
40789
  try {
40678
- hashDirs = import_node_fs19.default.readdirSync(attRoot);
40790
+ hashDirs = import_node_fs21.default.readdirSync(attRoot);
40679
40791
  } catch (err) {
40680
40792
  if (err.code === "ENOENT") continue;
40681
40793
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
40682
40794
  continue;
40683
40795
  }
40684
40796
  for (const hashDir of hashDirs) {
40685
- const hashDirAbs = import_node_path19.default.join(attRoot, hashDir);
40797
+ const hashDirAbs = import_node_path20.default.join(attRoot, hashDir);
40686
40798
  let files;
40687
40799
  try {
40688
- files = import_node_fs19.default.readdirSync(hashDirAbs);
40800
+ files = import_node_fs21.default.readdirSync(hashDirAbs);
40689
40801
  } catch {
40690
40802
  continue;
40691
40803
  }
40692
40804
  for (const name of files) {
40693
- const file = import_node_path19.default.join(hashDirAbs, name);
40805
+ const file = import_node_path20.default.join(hashDirAbs, name);
40694
40806
  let stat;
40695
40807
  try {
40696
- stat = import_node_fs19.default.statSync(file);
40808
+ stat = import_node_fs21.default.statSync(file);
40697
40809
  } catch {
40698
40810
  continue;
40699
40811
  }
@@ -40702,26 +40814,26 @@ function runAttachmentGc(args) {
40702
40814
  if (age < ttlMs) continue;
40703
40815
  if (liveAbs.has(file)) continue;
40704
40816
  try {
40705
- import_node_fs19.default.unlinkSync(file);
40817
+ import_node_fs21.default.unlinkSync(file);
40706
40818
  } catch (err) {
40707
40819
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
40708
40820
  }
40709
40821
  }
40710
40822
  try {
40711
- if (import_node_fs19.default.readdirSync(hashDirAbs).length === 0) import_node_fs19.default.rmdirSync(hashDirAbs);
40823
+ if (import_node_fs21.default.readdirSync(hashDirAbs).length === 0) import_node_fs21.default.rmdirSync(hashDirAbs);
40712
40824
  } catch {
40713
40825
  }
40714
40826
  }
40715
40827
  try {
40716
- if (import_node_fs19.default.readdirSync(attRoot).length === 0) import_node_fs19.default.rmdirSync(attRoot);
40828
+ if (import_node_fs21.default.readdirSync(attRoot).length === 0) import_node_fs21.default.rmdirSync(attRoot);
40717
40829
  } catch {
40718
40830
  }
40719
40831
  }
40720
40832
  }
40721
40833
 
40722
40834
  // src/attachment/group.ts
40723
- var import_node_fs20 = __toESM(require("fs"), 1);
40724
- var import_node_path20 = __toESM(require("path"), 1);
40835
+ var import_node_fs22 = __toESM(require("fs"), 1);
40836
+ var import_node_path21 = __toESM(require("path"), 1);
40725
40837
  var import_node_crypto6 = __toESM(require("crypto"), 1);
40726
40838
  init_protocol();
40727
40839
  var GroupFileStore = class {
@@ -40733,11 +40845,11 @@ var GroupFileStore = class {
40733
40845
  this.logger = opts.logger;
40734
40846
  }
40735
40847
  rootForScope(scope) {
40736
- return import_node_path20.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
40848
+ return import_node_path21.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
40737
40849
  }
40738
40850
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
40739
40851
  filePath(scope, sessionId) {
40740
- return import_node_path20.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
40852
+ return import_node_path21.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
40741
40853
  }
40742
40854
  cacheKey(scope, sessionId) {
40743
40855
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -40746,7 +40858,7 @@ var GroupFileStore = class {
40746
40858
  readFile(scope, sessionId) {
40747
40859
  const file = this.filePath(scope, sessionId);
40748
40860
  try {
40749
- const raw = import_node_fs20.default.readFileSync(file, "utf8");
40861
+ const raw = import_node_fs22.default.readFileSync(file, "utf8");
40750
40862
  const parsed = JSON.parse(raw);
40751
40863
  if (!Array.isArray(parsed)) {
40752
40864
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -40772,10 +40884,10 @@ var GroupFileStore = class {
40772
40884
  }
40773
40885
  writeFile(scope, sessionId, entries) {
40774
40886
  const file = this.filePath(scope, sessionId);
40775
- import_node_fs20.default.mkdirSync(import_node_path20.default.dirname(file), { recursive: true });
40887
+ import_node_fs22.default.mkdirSync(import_node_path21.default.dirname(file), { recursive: true });
40776
40888
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
40777
- import_node_fs20.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
40778
- import_node_fs20.default.renameSync(tmp, file);
40889
+ import_node_fs22.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
40890
+ import_node_fs22.default.renameSync(tmp, file);
40779
40891
  }
40780
40892
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
40781
40893
  list(scope, sessionId) {
@@ -40861,10 +40973,10 @@ var GroupFileStore = class {
40861
40973
  };
40862
40974
 
40863
40975
  // src/discovery/state-file.ts
40864
- var import_node_fs21 = __toESM(require("fs"), 1);
40865
- var import_node_path21 = __toESM(require("path"), 1);
40976
+ var import_node_fs23 = __toESM(require("fs"), 1);
40977
+ var import_node_path22 = __toESM(require("path"), 1);
40866
40978
  function defaultStateFilePath(dataDir) {
40867
- return import_node_path21.default.join(dataDir, "state.json");
40979
+ return import_node_path22.default.join(dataDir, "state.json");
40868
40980
  }
40869
40981
  function isPidAlive(pid) {
40870
40982
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -40886,7 +40998,7 @@ var StateFileManager = class {
40886
40998
  }
40887
40999
  read() {
40888
41000
  try {
40889
- const raw = import_node_fs21.default.readFileSync(this.file, "utf8");
41001
+ const raw = import_node_fs23.default.readFileSync(this.file, "utf8");
40890
41002
  const parsed = JSON.parse(raw);
40891
41003
  return parsed;
40892
41004
  } catch {
@@ -40900,20 +41012,20 @@ var StateFileManager = class {
40900
41012
  return { status: "stale", existing };
40901
41013
  }
40902
41014
  write(state) {
40903
- import_node_fs21.default.mkdirSync(import_node_path21.default.dirname(this.file), { recursive: true });
41015
+ import_node_fs23.default.mkdirSync(import_node_path22.default.dirname(this.file), { recursive: true });
40904
41016
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
40905
- import_node_fs21.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
40906
- import_node_fs21.default.renameSync(tmp, this.file);
41017
+ import_node_fs23.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
41018
+ import_node_fs23.default.renameSync(tmp, this.file);
40907
41019
  if (process.platform !== "win32") {
40908
41020
  try {
40909
- import_node_fs21.default.chmodSync(this.file, 384);
41021
+ import_node_fs23.default.chmodSync(this.file, 384);
40910
41022
  } catch {
40911
41023
  }
40912
41024
  }
40913
41025
  }
40914
41026
  delete() {
40915
41027
  try {
40916
- import_node_fs21.default.unlinkSync(this.file);
41028
+ import_node_fs23.default.unlinkSync(this.file);
40917
41029
  } catch {
40918
41030
  }
40919
41031
  }
@@ -40928,14 +41040,14 @@ function readDaemonSourceFromEnv(env = process.env) {
40928
41040
  }
40929
41041
 
40930
41042
  // src/tunnel/tunnel-manager.ts
40931
- var import_node_fs25 = __toESM(require("fs"), 1);
40932
- var import_node_path25 = __toESM(require("path"), 1);
41043
+ var import_node_fs27 = __toESM(require("fs"), 1);
41044
+ var import_node_path26 = __toESM(require("path"), 1);
40933
41045
  var import_node_crypto7 = __toESM(require("crypto"), 1);
40934
41046
  var import_node_child_process9 = require("child_process");
40935
41047
 
40936
41048
  // src/tunnel/tunnel-store.ts
40937
- var import_node_fs22 = __toESM(require("fs"), 1);
40938
- var import_node_path22 = __toESM(require("path"), 1);
41049
+ var import_node_fs24 = __toESM(require("fs"), 1);
41050
+ var import_node_path23 = __toESM(require("path"), 1);
40939
41051
  var TunnelStore = class {
40940
41052
  constructor(filePath) {
40941
41053
  this.filePath = filePath;
@@ -40943,7 +41055,7 @@ var TunnelStore = class {
40943
41055
  filePath;
40944
41056
  async get() {
40945
41057
  try {
40946
- const raw = await import_node_fs22.default.promises.readFile(this.filePath, "utf8");
41058
+ const raw = await import_node_fs24.default.promises.readFile(this.filePath, "utf8");
40947
41059
  const obj = JSON.parse(raw);
40948
41060
  if (!isPersistedTunnel(obj)) return null;
40949
41061
  return obj;
@@ -40954,22 +41066,22 @@ var TunnelStore = class {
40954
41066
  }
40955
41067
  }
40956
41068
  async set(v2) {
40957
- const dir = import_node_path22.default.dirname(this.filePath);
40958
- await import_node_fs22.default.promises.mkdir(dir, { recursive: true });
41069
+ const dir = import_node_path23.default.dirname(this.filePath);
41070
+ await import_node_fs24.default.promises.mkdir(dir, { recursive: true });
40959
41071
  const data = JSON.stringify(v2, null, 2);
40960
41072
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
40961
- await import_node_fs22.default.promises.writeFile(tmp, data, { mode: 384 });
41073
+ await import_node_fs24.default.promises.writeFile(tmp, data, { mode: 384 });
40962
41074
  if (process.platform !== "win32") {
40963
41075
  try {
40964
- await import_node_fs22.default.promises.chmod(tmp, 384);
41076
+ await import_node_fs24.default.promises.chmod(tmp, 384);
40965
41077
  } catch {
40966
41078
  }
40967
41079
  }
40968
- await import_node_fs22.default.promises.rename(tmp, this.filePath);
41080
+ await import_node_fs24.default.promises.rename(tmp, this.filePath);
40969
41081
  }
40970
41082
  async clear() {
40971
41083
  try {
40972
- await import_node_fs22.default.promises.unlink(this.filePath);
41084
+ await import_node_fs24.default.promises.unlink(this.filePath);
40973
41085
  } catch (err) {
40974
41086
  const code = err?.code;
40975
41087
  if (code !== "ENOENT") throw err;
@@ -41064,9 +41176,9 @@ function escape(v2) {
41064
41176
  }
41065
41177
 
41066
41178
  // src/tunnel/frpc-binary.ts
41067
- var import_node_fs23 = __toESM(require("fs"), 1);
41179
+ var import_node_fs25 = __toESM(require("fs"), 1);
41068
41180
  var import_node_os12 = __toESM(require("os"), 1);
41069
- var import_node_path23 = __toESM(require("path"), 1);
41181
+ var import_node_path24 = __toESM(require("path"), 1);
41070
41182
  var import_node_child_process7 = require("child_process");
41071
41183
  var import_node_stream3 = require("stream");
41072
41184
  var import_promises3 = require("stream/promises");
@@ -41098,20 +41210,20 @@ function frpcDownloadUrl(version2, p2) {
41098
41210
  }
41099
41211
  async function ensureFrpcBinary(opts) {
41100
41212
  if (opts.override) {
41101
- if (!import_node_fs23.default.existsSync(opts.override)) {
41213
+ if (!import_node_fs25.default.existsSync(opts.override)) {
41102
41214
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
41103
41215
  }
41104
41216
  return opts.override;
41105
41217
  }
41106
41218
  const version2 = opts.version ?? FRPC_VERSION;
41107
41219
  const platform = opts.platform ?? detectPlatform();
41108
- const binDir = import_node_path23.default.join(opts.dataDir, "bin");
41109
- import_node_fs23.default.mkdirSync(binDir, { recursive: true });
41220
+ const binDir = import_node_path24.default.join(opts.dataDir, "bin");
41221
+ import_node_fs25.default.mkdirSync(binDir, { recursive: true });
41110
41222
  cleanupStaleArtifacts(binDir);
41111
- const stableBin = import_node_path23.default.join(binDir, "frpc");
41112
- if (import_node_fs23.default.existsSync(stableBin)) return stableBin;
41223
+ const stableBin = import_node_path24.default.join(binDir, "frpc");
41224
+ if (import_node_fs25.default.existsSync(stableBin)) return stableBin;
41113
41225
  const partialBin = `${stableBin}.partial`;
41114
- const tarballPath = import_node_path23.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
41226
+ const tarballPath = import_node_path24.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
41115
41227
  try {
41116
41228
  const url = frpcDownloadUrl(version2, platform);
41117
41229
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -41120,8 +41232,8 @@ async function ensureFrpcBinary(opts) {
41120
41232
  } else {
41121
41233
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
41122
41234
  }
41123
- import_node_fs23.default.chmodSync(partialBin, 493);
41124
- import_node_fs23.default.renameSync(partialBin, stableBin);
41235
+ import_node_fs25.default.chmodSync(partialBin, 493);
41236
+ import_node_fs25.default.renameSync(partialBin, stableBin);
41125
41237
  } finally {
41126
41238
  safeUnlink(tarballPath);
41127
41239
  safeUnlink(partialBin);
@@ -41131,15 +41243,15 @@ async function ensureFrpcBinary(opts) {
41131
41243
  function cleanupStaleArtifacts(binDir) {
41132
41244
  let entries;
41133
41245
  try {
41134
- entries = import_node_fs23.default.readdirSync(binDir);
41246
+ entries = import_node_fs25.default.readdirSync(binDir);
41135
41247
  } catch {
41136
41248
  return;
41137
41249
  }
41138
41250
  for (const name of entries) {
41139
41251
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
41140
- const full = import_node_path23.default.join(binDir, name);
41252
+ const full = import_node_path24.default.join(binDir, name);
41141
41253
  try {
41142
- import_node_fs23.default.rmSync(full, { recursive: true, force: true });
41254
+ import_node_fs25.default.rmSync(full, { recursive: true, force: true });
41143
41255
  } catch {
41144
41256
  }
41145
41257
  }
@@ -41147,7 +41259,7 @@ function cleanupStaleArtifacts(binDir) {
41147
41259
  }
41148
41260
  function safeUnlink(p2) {
41149
41261
  try {
41150
- import_node_fs23.default.unlinkSync(p2);
41262
+ import_node_fs25.default.unlinkSync(p2);
41151
41263
  } catch {
41152
41264
  }
41153
41265
  }
@@ -41158,13 +41270,13 @@ async function downloadToFile(url, dest, fetchImpl) {
41158
41270
  if (!res.ok || !res.body) {
41159
41271
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
41160
41272
  }
41161
- const out = import_node_fs23.default.createWriteStream(dest);
41273
+ const out = import_node_fs25.default.createWriteStream(dest);
41162
41274
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
41163
41275
  await (0, import_promises3.pipeline)(nodeStream, out);
41164
41276
  }
41165
41277
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
41166
- const work = import_node_path23.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
41167
- import_node_fs23.default.mkdirSync(work, { recursive: true });
41278
+ const work = import_node_path24.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
41279
+ import_node_fs25.default.mkdirSync(work, { recursive: true });
41168
41280
  try {
41169
41281
  await new Promise((resolve6, reject) => {
41170
41282
  const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -41172,32 +41284,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
41172
41284
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
41173
41285
  });
41174
41286
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
41175
- const src = import_node_path23.default.join(work, dirName, "frpc");
41176
- if (!import_node_fs23.default.existsSync(src)) {
41287
+ const src = import_node_path24.default.join(work, dirName, "frpc");
41288
+ if (!import_node_fs25.default.existsSync(src)) {
41177
41289
  throw new Error(`frpc not found inside tarball at ${src}`);
41178
41290
  }
41179
- import_node_fs23.default.copyFileSync(src, destBin);
41291
+ import_node_fs25.default.copyFileSync(src, destBin);
41180
41292
  } finally {
41181
- import_node_fs23.default.rmSync(work, { recursive: true, force: true });
41293
+ import_node_fs25.default.rmSync(work, { recursive: true, force: true });
41182
41294
  }
41183
41295
  }
41184
41296
 
41185
41297
  // src/tunnel/frpc-process.ts
41186
- var import_node_fs24 = __toESM(require("fs"), 1);
41187
- var import_node_path24 = __toESM(require("path"), 1);
41298
+ var import_node_fs26 = __toESM(require("fs"), 1);
41299
+ var import_node_path25 = __toESM(require("path"), 1);
41188
41300
  var import_node_child_process8 = require("child_process");
41189
41301
  function frpcPidFilePath(dataDir) {
41190
- return import_node_path24.default.join(dataDir, "frpc.pid");
41302
+ return import_node_path25.default.join(dataDir, "frpc.pid");
41191
41303
  }
41192
41304
  function writeFrpcPid(dataDir, pid) {
41193
41305
  try {
41194
- import_node_fs24.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
41306
+ import_node_fs26.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
41195
41307
  } catch {
41196
41308
  }
41197
41309
  }
41198
41310
  function clearFrpcPid(dataDir) {
41199
41311
  try {
41200
- import_node_fs24.default.unlinkSync(frpcPidFilePath(dataDir));
41312
+ import_node_fs26.default.unlinkSync(frpcPidFilePath(dataDir));
41201
41313
  } catch {
41202
41314
  }
41203
41315
  }
@@ -41213,7 +41325,7 @@ function defaultIsPidAlive(pid) {
41213
41325
  }
41214
41326
  function defaultReadPidFile(file) {
41215
41327
  try {
41216
- return import_node_fs24.default.readFileSync(file, "utf8");
41328
+ return import_node_fs26.default.readFileSync(file, "utf8");
41217
41329
  } catch {
41218
41330
  return null;
41219
41331
  }
@@ -41229,7 +41341,7 @@ function defaultSleep(ms) {
41229
41341
  }
41230
41342
  async function killStaleFrpc(deps) {
41231
41343
  const pidFile = frpcPidFilePath(deps.dataDir);
41232
- const tomlPath = import_node_path24.default.join(deps.dataDir, "frpc.toml");
41344
+ const tomlPath = import_node_path25.default.join(deps.dataDir, "frpc.toml");
41233
41345
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
41234
41346
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
41235
41347
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -41253,7 +41365,7 @@ async function killStaleFrpc(deps) {
41253
41365
  }
41254
41366
  if (victims.size === 0) {
41255
41367
  try {
41256
- import_node_fs24.default.unlinkSync(pidFile);
41368
+ import_node_fs26.default.unlinkSync(pidFile);
41257
41369
  } catch {
41258
41370
  }
41259
41371
  return;
@@ -41264,7 +41376,7 @@ async function killStaleFrpc(deps) {
41264
41376
  }
41265
41377
  await sleep2(deps.reapWaitMs ?? 300);
41266
41378
  try {
41267
- import_node_fs24.default.unlinkSync(pidFile);
41379
+ import_node_fs26.default.unlinkSync(pidFile);
41268
41380
  } catch {
41269
41381
  }
41270
41382
  }
@@ -41301,7 +41413,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
41301
41413
  var TunnelManager = class {
41302
41414
  constructor(deps) {
41303
41415
  this.deps = deps;
41304
- this.store = deps.store ?? new TunnelStore(import_node_path25.default.join(deps.dataDir, "tunnel.json"));
41416
+ this.store = deps.store ?? new TunnelStore(import_node_path26.default.join(deps.dataDir, "tunnel.json"));
41305
41417
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
41306
41418
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
41307
41419
  }
@@ -41428,7 +41540,7 @@ var TunnelManager = class {
41428
41540
  dataDir: this.deps.dataDir,
41429
41541
  override: this.deps.frpcBinaryOverride ?? void 0
41430
41542
  });
41431
- const tomlPath = import_node_path25.default.join(this.deps.dataDir, "frpc.toml");
41543
+ const tomlPath = import_node_path26.default.join(this.deps.dataDir, "frpc.toml");
41432
41544
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
41433
41545
  const toml = buildFrpcToml({
41434
41546
  serverAddr: t.frpsHost,
@@ -41439,12 +41551,12 @@ var TunnelManager = class {
41439
41551
  localPort,
41440
41552
  logLevel: "info"
41441
41553
  });
41442
- await import_node_fs25.default.promises.writeFile(tomlPath, toml, { mode: 384 });
41554
+ await import_node_fs27.default.promises.writeFile(tomlPath, toml, { mode: 384 });
41443
41555
  const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
41444
41556
  stdio: ["ignore", "pipe", "pipe"]
41445
41557
  });
41446
- const logFilePath = import_node_path25.default.join(this.deps.dataDir, "frpc.log");
41447
- const logStream = import_node_fs25.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
41558
+ const logFilePath = import_node_path26.default.join(this.deps.dataDir, "frpc.log");
41559
+ const logStream = import_node_fs27.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
41448
41560
  logStream.on("error", () => {
41449
41561
  });
41450
41562
  const tee = (chunk) => {
@@ -41527,27 +41639,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
41527
41639
 
41528
41640
  // src/tunnel/device-key.ts
41529
41641
  var import_node_os13 = __toESM(require("os"), 1);
41530
- var import_node_path26 = __toESM(require("path"), 1);
41642
+ var import_node_path27 = __toESM(require("path"), 1);
41531
41643
  var import_node_crypto8 = __toESM(require("crypto"), 1);
41532
41644
  var DERIVE_SALT = "clawd-tunnel-device-v1";
41533
41645
  function deriveStableDeviceKey(opts = {}) {
41534
41646
  const hostname = opts.hostname ?? import_node_os13.default.hostname();
41535
41647
  const uid = opts.uid ?? (typeof import_node_os13.default.userInfo === "function" ? import_node_os13.default.userInfo().uid : 0);
41536
41648
  const home = opts.home ?? import_node_os13.default.homedir();
41537
- const defaultDataDir = import_node_path26.default.resolve(import_node_path26.default.join(home, ".clawd"));
41538
- const normalizedDataDir = opts.dataDir ? import_node_path26.default.resolve(opts.dataDir) : null;
41649
+ const defaultDataDir = import_node_path27.default.resolve(import_node_path27.default.join(home, ".clawd"));
41650
+ const normalizedDataDir = opts.dataDir ? import_node_path27.default.resolve(opts.dataDir) : null;
41539
41651
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
41540
41652
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
41541
41653
  return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
41542
41654
  }
41543
41655
 
41544
41656
  // src/auth-store.ts
41545
- var import_node_fs26 = __toESM(require("fs"), 1);
41546
- var import_node_path27 = __toESM(require("path"), 1);
41657
+ var import_node_fs28 = __toESM(require("fs"), 1);
41658
+ var import_node_path28 = __toESM(require("path"), 1);
41547
41659
  var import_node_crypto9 = __toESM(require("crypto"), 1);
41548
41660
  var AUTH_FILE_NAME = "auth.json";
41549
41661
  function authFilePath(dataDir) {
41550
- return import_node_path27.default.join(dataDir, AUTH_FILE_NAME);
41662
+ return import_node_path28.default.join(dataDir, AUTH_FILE_NAME);
41551
41663
  }
41552
41664
  function loadOrCreateAuthFile(opts) {
41553
41665
  const file = authFilePath(opts.dataDir);
@@ -41581,7 +41693,7 @@ function defaultGenerateOwnerPrincipalId() {
41581
41693
  }
41582
41694
  function readAuthFile(file) {
41583
41695
  try {
41584
- const raw = import_node_fs26.default.readFileSync(file, "utf8");
41696
+ const raw = import_node_fs28.default.readFileSync(file, "utf8");
41585
41697
  const parsed = JSON.parse(raw);
41586
41698
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
41587
41699
  return null;
@@ -41600,25 +41712,25 @@ function readAuthFile(file) {
41600
41712
  }
41601
41713
  }
41602
41714
  function writeAuthFile(file, content) {
41603
- import_node_fs26.default.mkdirSync(import_node_path27.default.dirname(file), { recursive: true });
41604
- import_node_fs26.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
41715
+ import_node_fs28.default.mkdirSync(import_node_path28.default.dirname(file), { recursive: true });
41716
+ import_node_fs28.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
41605
41717
  try {
41606
- import_node_fs26.default.chmodSync(file, 384);
41718
+ import_node_fs28.default.chmodSync(file, 384);
41607
41719
  } catch {
41608
41720
  }
41609
41721
  }
41610
41722
 
41611
41723
  // src/owner-profile.ts
41612
- var import_node_fs27 = __toESM(require("fs"), 1);
41724
+ var import_node_fs29 = __toESM(require("fs"), 1);
41613
41725
  var import_node_os14 = __toESM(require("os"), 1);
41614
- var import_node_path28 = __toESM(require("path"), 1);
41726
+ var import_node_path29 = __toESM(require("path"), 1);
41615
41727
  var PROFILE_FILENAME = "profile.json";
41616
41728
  function loadOwnerDisplayName(dataDir) {
41617
41729
  const fallback = import_node_os14.default.userInfo().username;
41618
- const profilePath = import_node_path28.default.join(dataDir, PROFILE_FILENAME);
41730
+ const profilePath = import_node_path29.default.join(dataDir, PROFILE_FILENAME);
41619
41731
  let raw;
41620
41732
  try {
41621
- raw = import_node_fs27.default.readFileSync(profilePath, "utf8");
41733
+ raw = import_node_fs29.default.readFileSync(profilePath, "utf8");
41622
41734
  } catch {
41623
41735
  return fallback;
41624
41736
  }
@@ -41641,18 +41753,18 @@ function loadOwnerDisplayName(dataDir) {
41641
41753
  }
41642
41754
 
41643
41755
  // src/feishu-auth/owner-identity-store.ts
41644
- var import_node_fs28 = __toESM(require("fs"), 1);
41645
- var import_node_path29 = __toESM(require("path"), 1);
41756
+ var import_node_fs30 = __toESM(require("fs"), 1);
41757
+ var import_node_path30 = __toESM(require("path"), 1);
41646
41758
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
41647
41759
  var OwnerIdentityStore = class {
41648
41760
  file;
41649
41761
  constructor(dataDir) {
41650
- this.file = import_node_path29.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
41762
+ this.file = import_node_path30.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
41651
41763
  }
41652
41764
  read() {
41653
41765
  let raw;
41654
41766
  try {
41655
- raw = import_node_fs28.default.readFileSync(this.file, "utf8");
41767
+ raw = import_node_fs30.default.readFileSync(this.file, "utf8");
41656
41768
  } catch {
41657
41769
  return null;
41658
41770
  }
@@ -41680,16 +41792,16 @@ var OwnerIdentityStore = class {
41680
41792
  };
41681
41793
  }
41682
41794
  write(record) {
41683
- import_node_fs28.default.mkdirSync(import_node_path29.default.dirname(this.file), { recursive: true });
41684
- import_node_fs28.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
41795
+ import_node_fs30.default.mkdirSync(import_node_path30.default.dirname(this.file), { recursive: true });
41796
+ import_node_fs30.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
41685
41797
  try {
41686
- import_node_fs28.default.chmodSync(this.file, 384);
41798
+ import_node_fs30.default.chmodSync(this.file, 384);
41687
41799
  } catch {
41688
41800
  }
41689
41801
  }
41690
41802
  clear() {
41691
41803
  try {
41692
- import_node_fs28.default.unlinkSync(this.file);
41804
+ import_node_fs30.default.unlinkSync(this.file);
41693
41805
  } catch (err) {
41694
41806
  const code = err?.code;
41695
41807
  if (code !== "ENOENT") throw err;
@@ -41810,9 +41922,9 @@ var CentralClientError = class extends Error {
41810
41922
  code;
41811
41923
  cause;
41812
41924
  };
41813
- async function centralRequest(opts, path59, init) {
41925
+ async function centralRequest(opts, path60, init) {
41814
41926
  const f = opts.fetchImpl ?? globalThis.fetch;
41815
- const url = `${opts.api.replace(/\/+$/, "")}${path59}`;
41927
+ const url = `${opts.api.replace(/\/+$/, "")}${path60}`;
41816
41928
  const ctrl = new AbortController();
41817
41929
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
41818
41930
  let res;
@@ -41954,8 +42066,8 @@ function verifyConnectToken(args) {
41954
42066
  }
41955
42067
 
41956
42068
  // src/feishu-auth/server-key.ts
41957
- var fs37 = __toESM(require("fs"), 1);
41958
- var path38 = __toESM(require("path"), 1);
42069
+ var fs39 = __toESM(require("fs"), 1);
42070
+ var path39 = __toESM(require("path"), 1);
41959
42071
  var FILE_NAME2 = "server-signing-key.json";
41960
42072
  var ServerKeyStore = class {
41961
42073
  constructor(dataDir) {
@@ -41963,12 +42075,12 @@ var ServerKeyStore = class {
41963
42075
  }
41964
42076
  dataDir;
41965
42077
  filePath() {
41966
- return path38.join(this.dataDir, FILE_NAME2);
42078
+ return path39.join(this.dataDir, FILE_NAME2);
41967
42079
  }
41968
42080
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
41969
42081
  read() {
41970
42082
  try {
41971
- const raw = fs37.readFileSync(this.filePath(), "utf8");
42083
+ const raw = fs39.readFileSync(this.filePath(), "utf8");
41972
42084
  const parsed = JSON.parse(raw);
41973
42085
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
41974
42086
  return parsed.publicKeyPem;
@@ -41983,12 +42095,12 @@ var ServerKeyStore = class {
41983
42095
  publicKeyPem,
41984
42096
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
41985
42097
  };
41986
- fs37.mkdirSync(this.dataDir, { recursive: true });
41987
- fs37.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
42098
+ fs39.mkdirSync(this.dataDir, { recursive: true });
42099
+ fs39.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
41988
42100
  }
41989
42101
  clear() {
41990
42102
  try {
41991
- fs37.unlinkSync(this.filePath());
42103
+ fs39.unlinkSync(this.filePath());
41992
42104
  } catch {
41993
42105
  }
41994
42106
  }
@@ -42001,12 +42113,12 @@ init_protocol();
42001
42113
  init_protocol();
42002
42114
 
42003
42115
  // src/session/fork.ts
42004
- var import_node_fs29 = __toESM(require("fs"), 1);
42116
+ var import_node_fs31 = __toESM(require("fs"), 1);
42005
42117
  var import_node_os15 = __toESM(require("os"), 1);
42006
- var import_node_path30 = __toESM(require("path"), 1);
42118
+ var import_node_path31 = __toESM(require("path"), 1);
42007
42119
  init_claude_history();
42008
42120
  function readJsonlEntries(file) {
42009
- const raw = import_node_fs29.default.readFileSync(file, "utf8");
42121
+ const raw = import_node_fs31.default.readFileSync(file, "utf8");
42010
42122
  const out = [];
42011
42123
  for (const line of raw.split("\n")) {
42012
42124
  const t = line.trim();
@@ -42019,10 +42131,10 @@ function readJsonlEntries(file) {
42019
42131
  return out;
42020
42132
  }
42021
42133
  function forkSession(input) {
42022
- const baseDir = input.baseDir ?? import_node_path30.default.join(import_node_os15.default.homedir(), ".claude");
42023
- const projectDir = import_node_path30.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
42024
- const sourceFile = import_node_path30.default.join(projectDir, `${input.toolSessionId}.jsonl`);
42025
- if (!import_node_fs29.default.existsSync(sourceFile)) {
42134
+ const baseDir = input.baseDir ?? import_node_path31.default.join(import_node_os15.default.homedir(), ".claude");
42135
+ const projectDir = import_node_path31.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
42136
+ const sourceFile = import_node_path31.default.join(projectDir, `${input.toolSessionId}.jsonl`);
42137
+ if (!import_node_fs31.default.existsSync(sourceFile)) {
42026
42138
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
42027
42139
  }
42028
42140
  const entries = readJsonlEntries(sourceFile);
@@ -42052,9 +42164,9 @@ function forkSession(input) {
42052
42164
  }
42053
42165
  forkedLines.push(JSON.stringify(forked));
42054
42166
  }
42055
- const forkedFilePath = import_node_path30.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
42056
- import_node_fs29.default.mkdirSync(projectDir, { recursive: true });
42057
- import_node_fs29.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
42167
+ const forkedFilePath = import_node_path31.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
42168
+ import_node_fs31.default.mkdirSync(projectDir, { recursive: true });
42169
+ import_node_fs31.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
42058
42170
  return { forkedToolSessionId, forkedFilePath };
42059
42171
  }
42060
42172
 
@@ -42430,7 +42542,7 @@ function buildPermissionHandlers(deps) {
42430
42542
  }
42431
42543
 
42432
42544
  // src/handlers/history.ts
42433
- var path41 = __toESM(require("path"), 1);
42545
+ var path42 = __toESM(require("path"), 1);
42434
42546
  init_protocol();
42435
42547
 
42436
42548
  // src/session/recent-dirs.ts
@@ -42448,7 +42560,7 @@ function listRecentDirs(store, limit = 50) {
42448
42560
  }
42449
42561
 
42450
42562
  // src/permission/persona-paths.ts
42451
- var path40 = __toESM(require("path"), 1);
42563
+ var path41 = __toESM(require("path"), 1);
42452
42564
  function getAllowedPersonaIds(grants, action) {
42453
42565
  const ids = /* @__PURE__ */ new Set();
42454
42566
  for (const g2 of grants) {
@@ -42461,31 +42573,31 @@ function getAllowedPersonaIds(grants, action) {
42461
42573
  return ids;
42462
42574
  }
42463
42575
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
42464
- const target = path40.resolve(absPath);
42576
+ const target = path41.resolve(absPath);
42465
42577
  if (userWorkDir) {
42466
- const u = path40.resolve(userWorkDir);
42467
- const usep = u.endsWith(path40.sep) ? "" : path40.sep;
42578
+ const u = path41.resolve(userWorkDir);
42579
+ const usep = u.endsWith(path41.sep) ? "" : path41.sep;
42468
42580
  if (target === u || target.startsWith(u + usep)) return true;
42469
42581
  }
42470
- const root = path40.resolve(personaRoot);
42471
- const sep3 = root.endsWith(path40.sep) ? "" : path40.sep;
42582
+ const root = path41.resolve(personaRoot);
42583
+ const sep3 = root.endsWith(path41.sep) ? "" : path41.sep;
42472
42584
  if (!target.startsWith(root + sep3)) return false;
42473
- const rel = path40.relative(root, target);
42585
+ const rel = path41.relative(root, target);
42474
42586
  if (!rel || rel.startsWith("..")) return false;
42475
- const personaId = rel.split(path40.sep)[0];
42587
+ const personaId = rel.split(path41.sep)[0];
42476
42588
  if (!personaId) return false;
42477
42589
  const allowed = getAllowedPersonaIds(grants, action);
42478
42590
  if (allowed === "*") return true;
42479
42591
  return allowed.has(personaId);
42480
42592
  }
42481
42593
  function personaIdFromPath(absPath, personaRoot) {
42482
- const root = path40.resolve(personaRoot);
42483
- const target = path40.resolve(absPath);
42484
- const sep3 = root.endsWith(path40.sep) ? "" : path40.sep;
42594
+ const root = path41.resolve(personaRoot);
42595
+ const target = path41.resolve(absPath);
42596
+ const sep3 = root.endsWith(path41.sep) ? "" : path41.sep;
42485
42597
  if (!target.startsWith(root + sep3)) return null;
42486
- const rel = path40.relative(root, target);
42598
+ const rel = path41.relative(root, target);
42487
42599
  if (!rel || rel.startsWith("..")) return null;
42488
- const id = rel.split(path40.sep)[0];
42600
+ const id = rel.split(path41.sep)[0];
42489
42601
  return id || null;
42490
42602
  }
42491
42603
 
@@ -42512,7 +42624,7 @@ function buildHistoryHandlers(deps) {
42512
42624
  if (!pid) return false;
42513
42625
  return isGuestPathAllowed(
42514
42626
  ctx.grants,
42515
- path41.join(personaRoot, pid),
42627
+ path42.join(personaRoot, pid),
42516
42628
  personaRoot,
42517
42629
  "read",
42518
42630
  userWorkDir
@@ -42524,7 +42636,7 @@ function buildHistoryHandlers(deps) {
42524
42636
  };
42525
42637
  const list = async (frame, _client, ctx) => {
42526
42638
  const args = HistoryListArgs.parse(frame);
42527
- assertGuestPath(ctx, path41.resolve(args.projectPath), personaRoot, "history:list");
42639
+ assertGuestPath(ctx, path42.resolve(args.projectPath), personaRoot, "history:list");
42528
42640
  const sessions = await history.listSessions(args);
42529
42641
  return { response: { type: "history:list", sessions } };
42530
42642
  };
@@ -42556,13 +42668,13 @@ function buildHistoryHandlers(deps) {
42556
42668
  };
42557
42669
  const subagents = async (frame, _client, ctx) => {
42558
42670
  const args = HistorySubagentsArgs.parse(frame);
42559
- assertGuestPath(ctx, path41.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
42671
+ assertGuestPath(ctx, path42.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
42560
42672
  const subs = await history.listSubagents(args);
42561
42673
  return { response: { type: "history:subagents", subagents: subs } };
42562
42674
  };
42563
42675
  const subagentRead = async (frame, _client, ctx) => {
42564
42676
  const args = HistorySubagentReadArgs.parse(frame);
42565
- assertGuestPath(ctx, path41.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
42677
+ assertGuestPath(ctx, path42.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
42566
42678
  const res = await history.readSubagent(args);
42567
42679
  return { response: { type: "history:subagent-read", ...res } };
42568
42680
  };
@@ -42571,7 +42683,7 @@ function buildHistoryHandlers(deps) {
42571
42683
  if (ctx?.principal.kind === "guest" && personaRoot) {
42572
42684
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
42573
42685
  const filtered = dirs.filter(
42574
- (d) => isGuestPathAllowed(ctx.grants, path41.resolve(d.cwd), personaRoot, "read", userWorkDir)
42686
+ (d) => isGuestPathAllowed(ctx.grants, path42.resolve(d.cwd), personaRoot, "read", userWorkDir)
42575
42687
  );
42576
42688
  return { response: { type: "history:recentDirs", dirs: filtered } };
42577
42689
  }
@@ -42588,7 +42700,7 @@ function buildHistoryHandlers(deps) {
42588
42700
  }
42589
42701
 
42590
42702
  // src/handlers/workspace.ts
42591
- var path42 = __toESM(require("path"), 1);
42703
+ var path43 = __toESM(require("path"), 1);
42592
42704
  var os15 = __toESM(require("os"), 1);
42593
42705
  init_protocol();
42594
42706
  init_protocol();
@@ -42630,22 +42742,22 @@ function buildWorkspaceHandlers(deps) {
42630
42742
  const args = WorkspaceListArgs.parse(frame);
42631
42743
  const isGuest = ctx?.principal.kind === "guest";
42632
42744
  const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
42633
- const resolvedCwd = path42.resolve(args.cwd ?? fallbackCwd);
42634
- const target = args.path ? path42.resolve(resolvedCwd, args.path) : resolvedCwd;
42745
+ const resolvedCwd = path43.resolve(args.cwd ?? fallbackCwd);
42746
+ const target = args.path ? path43.resolve(resolvedCwd, args.path) : resolvedCwd;
42635
42747
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
42636
42748
  const res = workspace.list({ ...args, cwd: resolvedCwd });
42637
42749
  return { response: { type: "workspace:list", ...res } };
42638
42750
  };
42639
42751
  const read = async (frame, _client, ctx) => {
42640
42752
  const args = WorkspaceReadArgs.parse(frame);
42641
- const target = path42.isAbsolute(args.path) ? path42.resolve(args.path) : path42.resolve(args.cwd, args.path);
42753
+ const target = path43.isAbsolute(args.path) ? path43.resolve(args.path) : path43.resolve(args.cwd, args.path);
42642
42754
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
42643
42755
  const res = workspace.read(args);
42644
42756
  return { response: { type: "workspace:read", ...res } };
42645
42757
  };
42646
42758
  const skillsList = async (frame, _client, ctx) => {
42647
42759
  const args = SkillsListArgs.parse(frame);
42648
- const cwdAbs = path42.resolve(args.cwd);
42760
+ const cwdAbs = path43.resolve(args.cwd);
42649
42761
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
42650
42762
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
42651
42763
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -42657,7 +42769,7 @@ function buildWorkspaceHandlers(deps) {
42657
42769
  };
42658
42770
  const agentsList = async (frame, _client, ctx) => {
42659
42771
  const args = AgentsListArgs.parse(frame);
42660
- const cwdAbs = path42.resolve(args.cwd);
42772
+ const cwdAbs = path43.resolve(args.cwd);
42661
42773
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
42662
42774
  if (args.tool === "codex") {
42663
42775
  return { response: { type: "agents:list", agents: [] } };
@@ -42679,20 +42791,20 @@ function buildWorkspaceHandlers(deps) {
42679
42791
  }
42680
42792
 
42681
42793
  // src/handlers/git.ts
42682
- var path44 = __toESM(require("path"), 1);
42794
+ var path45 = __toESM(require("path"), 1);
42683
42795
  init_protocol();
42684
42796
  init_protocol();
42685
42797
 
42686
42798
  // src/workspace/git.ts
42687
42799
  var import_node_child_process10 = require("child_process");
42688
- var import_node_fs30 = __toESM(require("fs"), 1);
42689
- var import_node_path31 = __toESM(require("path"), 1);
42800
+ var import_node_fs32 = __toESM(require("fs"), 1);
42801
+ var import_node_path32 = __toESM(require("path"), 1);
42690
42802
  var import_node_util = require("util");
42691
42803
  var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
42692
42804
  function normalizePath(p2) {
42693
- const resolved = import_node_path31.default.resolve(p2);
42805
+ const resolved = import_node_path32.default.resolve(p2);
42694
42806
  try {
42695
- return import_node_fs30.default.realpathSync(resolved);
42807
+ return import_node_fs32.default.realpathSync(resolved);
42696
42808
  } catch {
42697
42809
  return resolved;
42698
42810
  }
@@ -42766,7 +42878,7 @@ async function listGitBranches(cwd) {
42766
42878
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
42767
42879
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
42768
42880
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
42769
- if (!isGuestPathAllowed(ctx.grants, path44.resolve(cwd), personaRoot, "read", userWorkDir)) {
42881
+ if (!isGuestPathAllowed(ctx.grants, path45.resolve(cwd), personaRoot, "read", userWorkDir)) {
42770
42882
  throw new ClawdError(
42771
42883
  ERROR_CODES.UNAUTHORIZED,
42772
42884
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -43283,7 +43395,7 @@ function buildPersonaHandlers(deps) {
43283
43395
  }
43284
43396
 
43285
43397
  // src/handlers/attachment.ts
43286
- var import_node_path32 = __toESM(require("path"), 1);
43398
+ var import_node_path33 = __toESM(require("path"), 1);
43287
43399
  init_protocol();
43288
43400
  init_protocol();
43289
43401
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -43338,12 +43450,12 @@ function buildAttachmentHandlers(deps) {
43338
43450
  `session ${args.sessionId} scope unresolved`
43339
43451
  );
43340
43452
  }
43341
- const cwdAbs = import_node_path32.default.resolve(sessionFile.cwd);
43342
- const candidateAbs = import_node_path32.default.isAbsolute(args.relPath) ? import_node_path32.default.resolve(args.relPath) : import_node_path32.default.resolve(cwdAbs, args.relPath);
43453
+ const cwdAbs = import_node_path33.default.resolve(sessionFile.cwd);
43454
+ const candidateAbs = import_node_path33.default.isAbsolute(args.relPath) ? import_node_path33.default.resolve(args.relPath) : import_node_path33.default.resolve(cwdAbs, args.relPath);
43343
43455
  assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl", deps.usersRoot);
43344
43456
  const entries = deps.groupFileStore.list(scope, args.sessionId);
43345
43457
  const entry = entries.find((e) => {
43346
- const storedAbs = import_node_path32.default.isAbsolute(e.relPath) ? import_node_path32.default.resolve(e.relPath) : import_node_path32.default.resolve(cwdAbs, e.relPath);
43458
+ const storedAbs = import_node_path33.default.isAbsolute(e.relPath) ? import_node_path33.default.resolve(e.relPath) : import_node_path33.default.resolve(cwdAbs, e.relPath);
43347
43459
  return storedAbs === candidateAbs && !e.stale;
43348
43460
  });
43349
43461
  if (!entry) {
@@ -43354,7 +43466,8 @@ function buildAttachmentHandlers(deps) {
43354
43466
  }
43355
43467
  const ttl = args.ttlSeconds === null ? null : args.ttlSeconds ?? DEFAULT_TTL_SECONDS;
43356
43468
  const parts = signUrlParts(secret, candidateAbs, ttl);
43357
- const url = buildSignedFileUrl(httpBaseUrl, parts);
43469
+ const prefix = args.view === "md-rendered" ? "/share/md" : "/files";
43470
+ const url = buildSignedFileUrl(httpBaseUrl, parts, prefix);
43358
43471
  return {
43359
43472
  response: {
43360
43473
  type: "attachment.signUrl",
@@ -43367,7 +43480,7 @@ function buildAttachmentHandlers(deps) {
43367
43480
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
43368
43481
  const f = deps.sessionStore.read(sessionId);
43369
43482
  if (!f) return;
43370
- assertGuestAttachmentPath(ctx, import_node_path32.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
43483
+ assertGuestAttachmentPath(ctx, import_node_path33.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
43371
43484
  }
43372
43485
  const groupAdd = async (frame, _client, ctx) => {
43373
43486
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -43439,19 +43552,19 @@ function buildAttachmentHandlers(deps) {
43439
43552
 
43440
43553
  // src/handlers/extension.ts
43441
43554
  var import_promises7 = __toESM(require("fs/promises"), 1);
43442
- var import_node_path37 = __toESM(require("path"), 1);
43555
+ var import_node_path38 = __toESM(require("path"), 1);
43443
43556
  init_protocol();
43444
43557
 
43445
43558
  // src/extension/bundle-zip.ts
43446
43559
  var import_promises4 = __toESM(require("fs/promises"), 1);
43447
- var import_node_path33 = __toESM(require("path"), 1);
43560
+ var import_node_path34 = __toESM(require("path"), 1);
43448
43561
  var import_node_crypto11 = __toESM(require("crypto"), 1);
43449
43562
  var import_jszip2 = __toESM(require_lib3(), 1);
43450
43563
  async function bundleExtensionDir(dir) {
43451
43564
  const entries = await listFilesSorted(dir);
43452
43565
  const zip = new import_jszip2.default();
43453
43566
  for (const rel of entries) {
43454
- const abs = import_node_path33.default.join(dir, rel);
43567
+ const abs = import_node_path34.default.join(dir, rel);
43455
43568
  const content = await import_promises4.default.readFile(abs);
43456
43569
  zip.file(rel, content, { date: FIXED_DATE });
43457
43570
  }
@@ -43472,7 +43585,7 @@ async function listFilesSorted(rootDir) {
43472
43585
  return out;
43473
43586
  }
43474
43587
  async function walk(absRoot, relPrefix, out) {
43475
- const dirAbs = import_node_path33.default.join(absRoot, relPrefix);
43588
+ const dirAbs = import_node_path34.default.join(absRoot, relPrefix);
43476
43589
  const entries = await import_promises4.default.readdir(dirAbs, { withFileTypes: true });
43477
43590
  for (const e of entries) {
43478
43591
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -43526,25 +43639,25 @@ function computePublishCheck(args) {
43526
43639
 
43527
43640
  // src/extension/install-flow.ts
43528
43641
  var import_promises5 = __toESM(require("fs/promises"), 1);
43529
- var import_node_path35 = __toESM(require("path"), 1);
43642
+ var import_node_path36 = __toESM(require("path"), 1);
43530
43643
  var import_node_os18 = __toESM(require("os"), 1);
43531
43644
  var import_node_crypto12 = __toESM(require("crypto"), 1);
43532
43645
  var import_jszip3 = __toESM(require_lib3(), 1);
43533
43646
 
43534
43647
  // src/extension/paths.ts
43535
43648
  var import_node_os17 = __toESM(require("os"), 1);
43536
- var import_node_path34 = __toESM(require("path"), 1);
43649
+ var import_node_path35 = __toESM(require("path"), 1);
43537
43650
  function clawdHomeRoot(override) {
43538
- return override ?? process.env.CLAWD_HOME ?? import_node_path34.default.join(import_node_os17.default.homedir(), ".clawd");
43651
+ return override ?? process.env.CLAWD_HOME ?? import_node_path35.default.join(import_node_os17.default.homedir(), ".clawd");
43539
43652
  }
43540
43653
  function extensionsRoot(override) {
43541
- return import_node_path34.default.join(clawdHomeRoot(override), "extensions");
43654
+ return import_node_path35.default.join(clawdHomeRoot(override), "extensions");
43542
43655
  }
43543
43656
  function publishedChannelsFile(override) {
43544
- return import_node_path34.default.join(clawdHomeRoot(override), "extensions-published.json");
43657
+ return import_node_path35.default.join(clawdHomeRoot(override), "extensions-published.json");
43545
43658
  }
43546
43659
  function bundleCacheRoot(override) {
43547
- return import_node_path34.default.join(clawdHomeRoot(override), "extension-bundles");
43660
+ return import_node_path35.default.join(clawdHomeRoot(override), "extension-bundles");
43548
43661
  }
43549
43662
 
43550
43663
  // src/extension/install-flow.ts
@@ -43571,7 +43684,7 @@ async function installFromChannel(args, deps) {
43571
43684
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
43572
43685
  }
43573
43686
  for (const name of Object.keys(zip.files)) {
43574
- if (name.includes("..") || name.startsWith("/") || import_node_path35.default.isAbsolute(name)) {
43687
+ if (name.includes("..") || name.startsWith("/") || import_node_path36.default.isAbsolute(name)) {
43575
43688
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
43576
43689
  }
43577
43690
  }
@@ -43603,7 +43716,7 @@ async function installFromChannel(args, deps) {
43603
43716
  );
43604
43717
  }
43605
43718
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
43606
- const destDir = import_node_path35.default.join(deps.extensionsRoot, localExtId);
43719
+ const destDir = import_node_path36.default.join(deps.extensionsRoot, localExtId);
43607
43720
  let destExists = false;
43608
43721
  try {
43609
43722
  await import_promises5.default.access(destDir);
@@ -43617,16 +43730,16 @@ async function installFromChannel(args, deps) {
43617
43730
  );
43618
43731
  }
43619
43732
  const stage = await import_promises5.default.mkdtemp(
43620
- import_node_path35.default.join(import_node_os18.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
43733
+ import_node_path36.default.join(import_node_os18.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
43621
43734
  );
43622
43735
  try {
43623
43736
  for (const [name, entry] of Object.entries(zip.files)) {
43624
- const dest = import_node_path35.default.join(stage, name);
43737
+ const dest = import_node_path36.default.join(stage, name);
43625
43738
  if (entry.dir) {
43626
43739
  await import_promises5.default.mkdir(dest, { recursive: true });
43627
43740
  continue;
43628
43741
  }
43629
- await import_promises5.default.mkdir(import_node_path35.default.dirname(dest), { recursive: true });
43742
+ await import_promises5.default.mkdir(import_node_path36.default.dirname(dest), { recursive: true });
43630
43743
  if (name === "manifest.json") {
43631
43744
  const rewritten = { ...parsed.data, id: localExtId };
43632
43745
  await import_promises5.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -43647,7 +43760,7 @@ async function installFromChannel(args, deps) {
43647
43760
 
43648
43761
  // src/extension/update-flow.ts
43649
43762
  var import_promises6 = __toESM(require("fs/promises"), 1);
43650
- var import_node_path36 = __toESM(require("path"), 1);
43763
+ var import_node_path37 = __toESM(require("path"), 1);
43651
43764
  var import_node_os19 = __toESM(require("os"), 1);
43652
43765
  var import_node_crypto13 = __toESM(require("crypto"), 1);
43653
43766
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -43664,11 +43777,11 @@ async function updateFromChannel(args, deps) {
43664
43777
  channelRef.extId,
43665
43778
  channelRef.ownerPrincipalId
43666
43779
  );
43667
- const liveDir = import_node_path36.default.join(deps.extensionsRoot, localExtId);
43780
+ const liveDir = import_node_path37.default.join(deps.extensionsRoot, localExtId);
43668
43781
  const prevDir = `${liveDir}.prev`;
43669
43782
  let existingVersion;
43670
43783
  try {
43671
- const raw = await import_promises6.default.readFile(import_node_path36.default.join(liveDir, "manifest.json"), "utf8");
43784
+ const raw = await import_promises6.default.readFile(import_node_path37.default.join(liveDir, "manifest.json"), "utf8");
43672
43785
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
43673
43786
  if (!parsed2.success) {
43674
43787
  throw new UpdateError(
@@ -43701,7 +43814,7 @@ async function updateFromChannel(args, deps) {
43701
43814
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
43702
43815
  }
43703
43816
  for (const name of Object.keys(zip.files)) {
43704
- if (name.includes("..") || name.startsWith("/") || import_node_path36.default.isAbsolute(name)) {
43817
+ if (name.includes("..") || name.startsWith("/") || import_node_path37.default.isAbsolute(name)) {
43705
43818
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
43706
43819
  }
43707
43820
  }
@@ -43736,16 +43849,16 @@ async function updateFromChannel(args, deps) {
43736
43849
  await import_promises6.default.rm(prevDir, { recursive: true, force: true });
43737
43850
  await import_promises6.default.rename(liveDir, prevDir);
43738
43851
  const stage = await import_promises6.default.mkdtemp(
43739
- import_node_path36.default.join(import_node_os19.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
43852
+ import_node_path37.default.join(import_node_os19.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
43740
43853
  );
43741
43854
  try {
43742
43855
  for (const [name, entry] of Object.entries(zip.files)) {
43743
- const dest = import_node_path36.default.join(stage, name);
43856
+ const dest = import_node_path37.default.join(stage, name);
43744
43857
  if (entry.dir) {
43745
43858
  await import_promises6.default.mkdir(dest, { recursive: true });
43746
43859
  continue;
43747
43860
  }
43748
- await import_promises6.default.mkdir(import_node_path36.default.dirname(dest), { recursive: true });
43861
+ await import_promises6.default.mkdir(import_node_path37.default.dirname(dest), { recursive: true });
43749
43862
  if (name === "manifest.json") {
43750
43863
  const rewritten = { ...parsed.data, id: localExtId };
43751
43864
  await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -43838,7 +43951,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
43838
43951
  );
43839
43952
  }
43840
43953
  }
43841
- const manifestPath = import_node_path37.default.join(root, extId, "manifest.json");
43954
+ const manifestPath = import_node_path38.default.join(root, extId, "manifest.json");
43842
43955
  const manifest = await readManifest(root, extId);
43843
43956
  const next = { ...manifest, version: newVersion };
43844
43957
  const tmp = `${manifestPath}.tmp`;
@@ -43846,7 +43959,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
43846
43959
  await import_promises7.default.rename(tmp, manifestPath);
43847
43960
  }
43848
43961
  async function readManifest(root, extId) {
43849
- const file = import_node_path37.default.join(root, extId, "manifest.json");
43962
+ const file = import_node_path38.default.join(root, extId, "manifest.json");
43850
43963
  let raw;
43851
43964
  try {
43852
43965
  raw = await import_promises7.default.readFile(file, "utf8");
@@ -43937,7 +44050,7 @@ function buildExtensionHandlers(deps) {
43937
44050
  };
43938
44051
  async function buildSnapshotMeta(extId) {
43939
44052
  const manifest = await readManifest(deps.root, extId);
43940
- const { sha256, buffer } = await bundleExtensionDir(import_node_path37.default.join(deps.root, extId));
44053
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path38.default.join(deps.root, extId));
43941
44054
  return { manifest, contentHash: sha256, buffer };
43942
44055
  }
43943
44056
  const publish = async (frame, _client, ctx) => {
@@ -44118,9 +44231,9 @@ function buildExtensionHandlers(deps) {
44118
44231
  }
44119
44232
 
44120
44233
  // src/app-builder/project-store.ts
44121
- var import_node_fs31 = require("fs");
44234
+ var import_node_fs33 = require("fs");
44122
44235
  var import_node_child_process11 = require("child_process");
44123
- var import_node_path38 = require("path");
44236
+ var import_node_path39 = require("path");
44124
44237
  init_protocol();
44125
44238
  var PROJECTS_DIR = "projects";
44126
44239
  var META_FILE = ".clawd-project.json";
@@ -44134,19 +44247,19 @@ var ProjectStore = class {
44134
44247
  root;
44135
44248
  /** projects/<name>/.clawd-project.json 路径 */
44136
44249
  metaPath(name) {
44137
- return (0, import_node_path38.join)(this.projectsRoot(), name, META_FILE);
44250
+ return (0, import_node_path39.join)(this.projectsRoot(), name, META_FILE);
44138
44251
  }
44139
44252
  /** projects/<name>/ 目录路径(cwd 用) */
44140
44253
  projectDir(name) {
44141
- return (0, import_node_path38.join)(this.projectsRoot(), name);
44254
+ return (0, import_node_path39.join)(this.projectsRoot(), name);
44142
44255
  }
44143
44256
  projectsRoot() {
44144
- return (0, import_node_path38.join)(this.root, PROJECTS_DIR);
44257
+ return (0, import_node_path39.join)(this.root, PROJECTS_DIR);
44145
44258
  }
44146
44259
  async list() {
44147
44260
  let entries;
44148
44261
  try {
44149
- entries = await import_node_fs31.promises.readdir(this.projectsRoot());
44262
+ entries = await import_node_fs33.promises.readdir(this.projectsRoot());
44150
44263
  } catch (err) {
44151
44264
  if (err.code === "ENOENT") return [];
44152
44265
  throw err;
@@ -44154,7 +44267,7 @@ var ProjectStore = class {
44154
44267
  const out = [];
44155
44268
  for (const name of entries) {
44156
44269
  try {
44157
- const raw = await import_node_fs31.promises.readFile(this.metaPath(name), "utf8");
44270
+ const raw = await import_node_fs33.promises.readFile(this.metaPath(name), "utf8");
44158
44271
  const json = JSON.parse(raw);
44159
44272
  let migrated = false;
44160
44273
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -44165,7 +44278,7 @@ var ProjectStore = class {
44165
44278
  if (parsed.success) {
44166
44279
  out.push(parsed.data);
44167
44280
  if (migrated) {
44168
- void import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
44281
+ void import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
44169
44282
  });
44170
44283
  }
44171
44284
  }
@@ -44209,8 +44322,8 @@ var ProjectStore = class {
44209
44322
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
44210
44323
  }
44211
44324
  const dir = this.projectDir(name);
44212
- await import_node_fs31.promises.mkdir(dir, { recursive: true });
44213
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
44325
+ await import_node_fs33.promises.mkdir(dir, { recursive: true });
44326
+ await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
44214
44327
  return meta;
44215
44328
  }
44216
44329
  /**
@@ -44253,7 +44366,7 @@ var ProjectStore = class {
44253
44366
  }
44254
44367
  async delete(name) {
44255
44368
  const dir = this.projectDir(name);
44256
- await import_node_fs31.promises.rm(dir, { recursive: true, force: true });
44369
+ await import_node_fs33.promises.rm(dir, { recursive: true, force: true });
44257
44370
  }
44258
44371
  async updatePort(name, newPort) {
44259
44372
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -44269,7 +44382,7 @@ var ProjectStore = class {
44269
44382
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
44270
44383
  }
44271
44384
  const updated = { ...target, port: newPort };
44272
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
44385
+ await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
44273
44386
  return updated;
44274
44387
  }
44275
44388
  /**
@@ -44286,7 +44399,7 @@ var ProjectStore = class {
44286
44399
  if (!validated.success) {
44287
44400
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
44288
44401
  }
44289
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44402
+ await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44290
44403
  return validated.data;
44291
44404
  }
44292
44405
  /**
@@ -44307,7 +44420,7 @@ var ProjectStore = class {
44307
44420
  if (!validated.success) {
44308
44421
  throw new Error(`invalid publishJob: ${validated.error.message}`);
44309
44422
  }
44310
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44423
+ await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44311
44424
  return validated.data;
44312
44425
  }
44313
44426
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -44322,7 +44435,7 @@ var ProjectStore = class {
44322
44435
  if (!validated.success) {
44323
44436
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
44324
44437
  }
44325
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44438
+ await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44326
44439
  return validated.data;
44327
44440
  }
44328
44441
  };
@@ -44443,8 +44556,8 @@ var PublishJobRegistry = class {
44443
44556
 
44444
44557
  // src/app-builder/publish-job-runner.ts
44445
44558
  var import_node_child_process13 = require("child_process");
44446
- var import_node_fs32 = require("fs");
44447
- var import_node_path39 = require("path");
44559
+ var import_node_fs34 = require("fs");
44560
+ var import_node_path40 = require("path");
44448
44561
 
44449
44562
  // src/app-builder/publish-stage-parser.ts
44450
44563
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -44476,10 +44589,10 @@ async function startPublishJob(deps, args) {
44476
44589
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
44477
44590
  }
44478
44591
  const projDir = projectDir(args.name);
44479
- const logPath = (0, import_node_path39.join)(projDir, ".publish.log");
44592
+ const logPath = (0, import_node_path40.join)(projDir, ".publish.log");
44480
44593
  let logStream = null;
44481
44594
  try {
44482
- logStream = (0, import_node_fs32.createWriteStream)(logPath, { flags: "w" });
44595
+ logStream = (0, import_node_fs34.createWriteStream)(logPath, { flags: "w" });
44483
44596
  } catch {
44484
44597
  logStream = null;
44485
44598
  }
@@ -44736,8 +44849,8 @@ async function recoverInterruptedJobs(deps) {
44736
44849
 
44737
44850
  // src/handlers/app-builder.ts
44738
44851
  init_protocol();
44739
- var import_node_path40 = require("path");
44740
- var import_node_fs33 = require("fs");
44852
+ var import_node_path41 = require("path");
44853
+ var import_node_fs35 = require("fs");
44741
44854
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
44742
44855
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
44743
44856
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -44818,7 +44931,7 @@ function buildAppBuilderHandlers(deps) {
44818
44931
  async function listAllUsersProjects() {
44819
44932
  if (!deps.usersRoot || !deps.getStore) return [];
44820
44933
  const getStore = deps.getStore;
44821
- const userIds = await import_node_fs33.promises.readdir(deps.usersRoot).catch(() => []);
44934
+ const userIds = await import_node_fs35.promises.readdir(deps.usersRoot).catch(() => []);
44822
44935
  const perUser = await Promise.all(
44823
44936
  userIds.map((uid) => getStore(uid).list().catch(() => []))
44824
44937
  );
@@ -44894,8 +45007,8 @@ function buildAppBuilderHandlers(deps) {
44894
45007
  const project = await userStore.create(f.name, reservedPorts);
44895
45008
  try {
44896
45009
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
44897
- const templateSrcDir = (0, import_node_path40.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
44898
- const scaffoldScript = (0, import_node_path40.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
45010
+ const templateSrcDir = (0, import_node_path41.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
45011
+ const scaffoldScript = (0, import_node_path41.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
44899
45012
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
44900
45013
  deps.logger?.info("app-builder.scaffold.done", {
44901
45014
  name: project.name,
@@ -45116,7 +45229,7 @@ function buildAppBuilderHandlers(deps) {
45116
45229
  await userStore.clearPublishJob(args.name);
45117
45230
  }
45118
45231
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
45119
- const scriptPath = (0, import_node_path40.join)(deps.deployKitRoot, "scripts", "publish.sh");
45232
+ const scriptPath = (0, import_node_path41.join)(deps.deployKitRoot, "scripts", "publish.sh");
45120
45233
  deps.logger?.info("app-builder.publish.start", {
45121
45234
  name: args.name,
45122
45235
  sessionId: boundSession.sessionId,
@@ -45212,7 +45325,7 @@ function buildAppBuilderHandlers(deps) {
45212
45325
 
45213
45326
  // src/extension/registry.ts
45214
45327
  var import_promises8 = __toESM(require("fs/promises"), 1);
45215
- var import_node_path41 = __toESM(require("path"), 1);
45328
+ var import_node_path42 = __toESM(require("path"), 1);
45216
45329
  async function loadAll(root) {
45217
45330
  let entries;
45218
45331
  try {
@@ -45225,13 +45338,13 @@ async function loadAll(root) {
45225
45338
  for (const ent of entries) {
45226
45339
  if (!ent.isDirectory()) continue;
45227
45340
  if (ent.name.startsWith(".")) continue;
45228
- records.push(await loadOne(import_node_path41.default.join(root, ent.name), ent.name));
45341
+ records.push(await loadOne(import_node_path42.default.join(root, ent.name), ent.name));
45229
45342
  }
45230
45343
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
45231
45344
  return records;
45232
45345
  }
45233
45346
  async function loadOne(dir, dirName) {
45234
- const manifestPath = import_node_path41.default.join(dir, "manifest.json");
45347
+ const manifestPath = import_node_path42.default.join(dir, "manifest.json");
45235
45348
  let raw;
45236
45349
  try {
45237
45350
  raw = await import_promises8.default.readFile(manifestPath, "utf8");
@@ -45276,7 +45389,7 @@ async function loadOne(dir, dirName) {
45276
45389
 
45277
45390
  // src/extension/uninstall.ts
45278
45391
  var import_promises9 = __toESM(require("fs/promises"), 1);
45279
- var import_node_path42 = __toESM(require("path"), 1);
45392
+ var import_node_path43 = __toESM(require("path"), 1);
45280
45393
  var UninstallError = class extends Error {
45281
45394
  constructor(code, message) {
45282
45395
  super(message);
@@ -45285,7 +45398,7 @@ var UninstallError = class extends Error {
45285
45398
  code;
45286
45399
  };
45287
45400
  async function uninstall(deps) {
45288
- const dir = import_node_path42.default.join(deps.root, deps.extId);
45401
+ const dir = import_node_path43.default.join(deps.root, deps.extId);
45289
45402
  try {
45290
45403
  await import_promises9.default.access(dir);
45291
45404
  } catch {
@@ -45796,7 +45909,7 @@ function computeGrantForFrame(method, frame) {
45796
45909
 
45797
45910
  // src/extension/runtime.ts
45798
45911
  var import_node_child_process15 = require("child_process");
45799
- var import_node_path43 = __toESM(require("path"), 1);
45912
+ var import_node_path44 = __toESM(require("path"), 1);
45800
45913
  var import_promises10 = require("timers/promises");
45801
45914
 
45802
45915
  // src/extension/port-allocator.ts
@@ -45897,7 +46010,7 @@ var Runtime = class {
45897
46010
  /\$CLAWOS_EXT_PORT/g,
45898
46011
  String(port)
45899
46012
  );
45900
- const dir = import_node_path43.default.join(this.root, extId);
46013
+ const dir = import_node_path44.default.join(this.root, extId);
45901
46014
  const env = {
45902
46015
  ...process.env,
45903
46016
  CLAWOS_EXT_PORT: String(port),
@@ -46009,7 +46122,7 @@ ${handle.stderrTail}`
46009
46122
 
46010
46123
  // src/extension/published-channels.ts
46011
46124
  var import_promises11 = __toESM(require("fs/promises"), 1);
46012
- var import_node_path44 = __toESM(require("path"), 1);
46125
+ var import_node_path45 = __toESM(require("path"), 1);
46013
46126
  init_zod();
46014
46127
  var PublishedChannelsError = class extends Error {
46015
46128
  constructor(code, message) {
@@ -46108,7 +46221,7 @@ var PublishedChannelStore = class {
46108
46221
  )
46109
46222
  };
46110
46223
  const tmp = `${this.filePath}.tmp`;
46111
- await import_promises11.default.mkdir(import_node_path44.default.dirname(this.filePath), { recursive: true });
46224
+ await import_promises11.default.mkdir(import_node_path45.default.dirname(this.filePath), { recursive: true });
46112
46225
  await import_promises11.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
46113
46226
  await import_promises11.default.rename(tmp, this.filePath);
46114
46227
  }
@@ -46116,7 +46229,7 @@ var PublishedChannelStore = class {
46116
46229
 
46117
46230
  // src/extension/bundle-cache.ts
46118
46231
  var import_promises12 = __toESM(require("fs/promises"), 1);
46119
- var import_node_path45 = __toESM(require("path"), 1);
46232
+ var import_node_path46 = __toESM(require("path"), 1);
46120
46233
  var BundleCache = class {
46121
46234
  constructor(rootDir) {
46122
46235
  this.rootDir = rootDir;
@@ -46125,14 +46238,14 @@ var BundleCache = class {
46125
46238
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
46126
46239
  async write(snapshotHash, buffer) {
46127
46240
  await import_promises12.default.mkdir(this.rootDir, { recursive: true });
46128
- const file = import_node_path45.default.join(this.rootDir, `${snapshotHash}.zip`);
46241
+ const file = import_node_path46.default.join(this.rootDir, `${snapshotHash}.zip`);
46129
46242
  const tmp = `${file}.tmp`;
46130
46243
  await import_promises12.default.writeFile(tmp, buffer, { mode: 384 });
46131
46244
  await import_promises12.default.rename(tmp, file);
46132
46245
  }
46133
46246
  /** Returns the bundle bytes, or null when the file doesn't exist. */
46134
46247
  async read(snapshotHash) {
46135
- const file = import_node_path45.default.join(this.rootDir, `${snapshotHash}.zip`);
46248
+ const file = import_node_path46.default.join(this.rootDir, `${snapshotHash}.zip`);
46136
46249
  try {
46137
46250
  return await import_promises12.default.readFile(file);
46138
46251
  } catch (e) {
@@ -46142,13 +46255,13 @@ var BundleCache = class {
46142
46255
  }
46143
46256
  /** Idempotent — missing file is not an error. */
46144
46257
  async delete(snapshotHash) {
46145
- const file = import_node_path45.default.join(this.rootDir, `${snapshotHash}.zip`);
46258
+ const file = import_node_path46.default.join(this.rootDir, `${snapshotHash}.zip`);
46146
46259
  await import_promises12.default.rm(file, { force: true });
46147
46260
  }
46148
46261
  };
46149
46262
 
46150
46263
  // src/index.ts
46151
- var import_meta4 = {};
46264
+ var import_meta5 = {};
46152
46265
  async function startDaemon(config) {
46153
46266
  const authFile = loadOrCreateAuthFile({ dataDir: config.dataDir });
46154
46267
  const logShippingCfg = config.logShipping ?? { endpoint: null, sampling: {}, mode: "off" };
@@ -46167,7 +46280,7 @@ async function startDaemon(config) {
46167
46280
  });
46168
46281
  const logger = createLogger({
46169
46282
  level: config.logLevel,
46170
- file: import_node_path46.default.join(config.dataDir, "clawd.log"),
46283
+ file: import_node_path47.default.join(config.dataDir, "clawd.log"),
46171
46284
  logClient
46172
46285
  });
46173
46286
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
@@ -46303,8 +46416,8 @@ async function startDaemon(config) {
46303
46416
  const agents = new AgentsScanner();
46304
46417
  const history = new ClaudeHistoryReader();
46305
46418
  let transport = null;
46306
- const personaStore = new PersonaStore(import_node_path46.default.join(config.dataDir, "personas"));
46307
- const usersRoot = import_node_path46.default.join(config.dataDir, "users");
46419
+ const personaStore = new PersonaStore(import_node_path47.default.join(config.dataDir, "personas"));
46420
+ const usersRoot = import_node_path47.default.join(config.dataDir, "users");
46308
46421
  const defaultsRoot = findDefaultsRoot(logger);
46309
46422
  if (defaultsRoot) {
46310
46423
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -46324,17 +46437,17 @@ async function startDaemon(config) {
46324
46437
  migrateCodexSandbox({ store: personaStore, logger });
46325
46438
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
46326
46439
  const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
46327
- const here = typeof __dirname === "string" ? __dirname : import_node_path46.default.dirname((0, import_node_url2.fileURLToPath)(import_meta4.url));
46440
+ const here = typeof __dirname === "string" ? __dirname : import_node_path47.default.dirname((0, import_node_url3.fileURLToPath)(import_meta5.url));
46328
46441
  const dispatchServerCandidates = [
46329
- import_node_path46.default.join(here, "dispatch", "mcp-server.cjs"),
46442
+ import_node_path47.default.join(here, "dispatch", "mcp-server.cjs"),
46330
46443
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
46331
- import_node_path46.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
46444
+ import_node_path47.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
46332
46445
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
46333
46446
  ];
46334
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs34.default.existsSync(p2));
46447
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs36.default.existsSync(p2));
46335
46448
  let dispatchMcpConfigPath2;
46336
46449
  if (dispatchServerScriptPath) {
46337
- const dispatchLogPath = import_node_path46.default.join(config.dataDir, "dispatch-mcp-server.log");
46450
+ const dispatchLogPath = import_node_path47.default.join(config.dataDir, "dispatch-mcp-server.log");
46338
46451
  dispatchMcpConfigPath2 = writeDispatchMcpConfig({
46339
46452
  dataDir: config.dataDir,
46340
46453
  serverScriptPath: dispatchServerScriptPath,
@@ -46359,7 +46472,7 @@ async function startDaemon(config) {
46359
46472
  getAdapter,
46360
46473
  historyReader: history,
46361
46474
  dataDir: config.dataDir,
46362
- personaRoot: import_node_path46.default.join(config.dataDir, "personas"),
46475
+ personaRoot: import_node_path47.default.join(config.dataDir, "personas"),
46363
46476
  usersRoot,
46364
46477
  personaStore,
46365
46478
  ownerDisplayName,
@@ -46395,10 +46508,10 @@ async function startDaemon(config) {
46395
46508
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
46396
46509
  attachmentGroup: {
46397
46510
  onFileEdit: (input) => {
46398
- const absPath = import_node_path46.default.isAbsolute(input.relPath) ? input.relPath : import_node_path46.default.join(input.cwd, input.relPath);
46511
+ const absPath = import_node_path47.default.isAbsolute(input.relPath) ? input.relPath : import_node_path47.default.join(input.cwd, input.relPath);
46399
46512
  let size = 0;
46400
46513
  try {
46401
- size = import_node_fs34.default.statSync(absPath).size;
46514
+ size = import_node_fs36.default.statSync(absPath).size;
46402
46515
  } catch (err) {
46403
46516
  logger.warn("attachment.onFileEdit stat failed", {
46404
46517
  sessionId: input.sessionId,
@@ -46584,11 +46697,11 @@ async function startDaemon(config) {
46584
46697
  // 'persona/<pid>/owner',default 走 'default'。
46585
46698
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
46586
46699
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
46587
- personaRoot: import_node_path46.default.join(config.dataDir, "personas"),
46700
+ personaRoot: import_node_path47.default.join(config.dataDir, "personas"),
46588
46701
  usersRoot
46589
46702
  },
46590
46703
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
46591
- personaRoot: import_node_path46.default.join(config.dataDir, "personas"),
46704
+ personaRoot: import_node_path47.default.join(config.dataDir, "personas"),
46592
46705
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
46593
46706
  usersRoot,
46594
46707
  // capability:list / delete handler 依赖
@@ -46695,11 +46808,11 @@ async function startDaemon(config) {
46695
46808
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
46696
46809
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
46697
46810
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
46698
- appBuilderPersonaRoot: import_node_path46.default.join(config.dataDir, "personas", "persona-app-builder"),
46811
+ appBuilderPersonaRoot: import_node_path47.default.join(config.dataDir, "personas", "persona-app-builder"),
46699
46812
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
46700
- deployKitRoot: import_node_path46.default.join(config.dataDir, "deploy-kit"),
46813
+ deployKitRoot: import_node_path47.default.join(config.dataDir, "deploy-kit"),
46701
46814
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
46702
- resolvePersonaRoot: (personaId) => import_node_path46.default.join(config.dataDir, "personas", personaId),
46815
+ resolvePersonaRoot: (personaId) => import_node_path47.default.join(config.dataDir, "personas", personaId),
46703
46816
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
46704
46817
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
46705
46818
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -46733,7 +46846,7 @@ async function startDaemon(config) {
46733
46846
  if (!sourceFile) {
46734
46847
  throw new Error(`personaDispatch:run source session not found: ${args.sourceSessionId}`);
46735
46848
  }
46736
- const sourceJsonlPath = sourceFile.toolSessionId ? import_node_path46.default.join(
46849
+ const sourceJsonlPath = sourceFile.toolSessionId ? import_node_path47.default.join(
46737
46850
  import_node_os20.default.homedir(),
46738
46851
  ".claude",
46739
46852
  "projects",
@@ -46769,12 +46882,14 @@ async function startDaemon(config) {
46769
46882
  return result.response;
46770
46883
  }
46771
46884
  };
46885
+ const viewerAssetLoader = tryLoadViewerAssets(logger);
46772
46886
  const httpRouter = createHttpRouter({
46773
46887
  authResolver,
46774
46888
  daemonVersion: version,
46775
46889
  logger,
46776
46890
  sessionStore: store,
46777
46891
  rpcDispatcher,
46892
+ ...viewerAssetLoader ? { viewerAssetLoader } : {},
46778
46893
  // /files HMAC verify 用 auth.json 的 signSecret 字段(与 attachment.signUrl 同源)。
46779
46894
  // --auth-token CLI 模式没 signSecret → 路由返 501,sign URL 功能整体禁用。
46780
46895
  getSignSecret: () => authFile?.signSecret ?? null,
@@ -46987,8 +47102,8 @@ async function startDaemon(config) {
46987
47102
  const lines = [
46988
47103
  `Tunnel: ${r.url}`,
46989
47104
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
46990
- `Frpc config: ${import_node_path46.default.join(config.dataDir, "frpc.toml")}`,
46991
- `Frpc log: ${import_node_path46.default.join(config.dataDir, "frpc.log")}`
47105
+ `Frpc config: ${import_node_path47.default.join(config.dataDir, "frpc.toml")}`,
47106
+ `Frpc log: ${import_node_path47.default.join(config.dataDir, "frpc.log")}`
46992
47107
  ];
46993
47108
  const width = Math.max(...lines.map((l) => l.length));
46994
47109
  const bar = "\u2550".repeat(width + 4);
@@ -47001,8 +47116,8 @@ ${bar}
47001
47116
 
47002
47117
  `);
47003
47118
  try {
47004
- const connectPath = import_node_path46.default.join(config.dataDir, "connect.txt");
47005
- import_node_fs34.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
47119
+ const connectPath = import_node_path47.default.join(config.dataDir, "connect.txt");
47120
+ import_node_fs36.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
47006
47121
  } catch {
47007
47122
  }
47008
47123
  } catch (err) {
@@ -47074,9 +47189,9 @@ ${bar}
47074
47189
  };
47075
47190
  }
47076
47191
  function migrateDropPersonsDir(dataDir) {
47077
- const dir = import_node_path46.default.join(dataDir, "persons");
47192
+ const dir = import_node_path47.default.join(dataDir, "persons");
47078
47193
  try {
47079
- import_node_fs34.default.rmSync(dir, { recursive: true, force: true });
47194
+ import_node_fs36.default.rmSync(dir, { recursive: true, force: true });
47080
47195
  } catch {
47081
47196
  }
47082
47197
  }