@clawos-dev/clawd 0.2.191-beta.382.4a6606c → 0.2.191

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -733,8 +733,8 @@ var init_parseUtil = __esm({
733
733
  init_errors2();
734
734
  init_en();
735
735
  makeIssue = (params) => {
736
- const { data, path: path67, errorMaps, issueData } = params;
737
- const fullPath = [...path67, ...issueData.path || []];
736
+ const { data, path: path68, errorMaps, issueData } = params;
737
+ const fullPath = [...path68, ...issueData.path || []];
738
738
  const fullIssue = {
739
739
  ...issueData,
740
740
  path: fullPath
@@ -1045,11 +1045,11 @@ var init_types = __esm({
1045
1045
  init_parseUtil();
1046
1046
  init_util();
1047
1047
  ParseInputLazyPath = class {
1048
- constructor(parent, value, path67, key) {
1048
+ constructor(parent, value, path68, key) {
1049
1049
  this._cachedPath = [];
1050
1050
  this.parent = parent;
1051
1051
  this.data = value;
1052
- this._path = path67;
1052
+ this._path = path68;
1053
1053
  this._key = key;
1054
1054
  }
1055
1055
  get path() {
@@ -6373,8 +6373,8 @@ var require_req = __commonJS({
6373
6373
  if (req.originalUrl) {
6374
6374
  _req.url = req.originalUrl;
6375
6375
  } else {
6376
- const path67 = req.path;
6377
- _req.url = typeof path67 === "string" ? path67 : req.url ? req.url.path || req.url : void 0;
6376
+ const path68 = req.path;
6377
+ _req.url = typeof path68 === "string" ? path68 : req.url ? req.url.path || req.url : void 0;
6378
6378
  }
6379
6379
  if (req.query) {
6380
6380
  _req.query = req.query;
@@ -6539,14 +6539,14 @@ var require_redact = __commonJS({
6539
6539
  }
6540
6540
  return obj;
6541
6541
  }
6542
- function parsePath(path67) {
6542
+ function parsePath(path68) {
6543
6543
  const parts = [];
6544
6544
  let current = "";
6545
6545
  let inBrackets = false;
6546
6546
  let inQuotes = false;
6547
6547
  let quoteChar = "";
6548
- for (let i = 0; i < path67.length; i++) {
6549
- const char = path67[i];
6548
+ for (let i = 0; i < path68.length; i++) {
6549
+ const char = path68[i];
6550
6550
  if (!inBrackets && char === ".") {
6551
6551
  if (current) {
6552
6552
  parts.push(current);
@@ -6677,10 +6677,10 @@ var require_redact = __commonJS({
6677
6677
  return current;
6678
6678
  }
6679
6679
  function redactPaths(obj, paths, censor, remove = false) {
6680
- for (const path67 of paths) {
6681
- const parts = parsePath(path67);
6680
+ for (const path68 of paths) {
6681
+ const parts = parsePath(path68);
6682
6682
  if (parts.includes("*")) {
6683
- redactWildcardPath(obj, parts, censor, path67, remove);
6683
+ redactWildcardPath(obj, parts, censor, path68, remove);
6684
6684
  } else {
6685
6685
  if (remove) {
6686
6686
  removeKey(obj, parts);
@@ -6765,8 +6765,8 @@ var require_redact = __commonJS({
6765
6765
  }
6766
6766
  } else {
6767
6767
  if (afterWildcard.includes("*")) {
6768
- const wrappedCensor = typeof censor === "function" ? (value, path67) => {
6769
- const fullPath = [...pathArray.slice(0, pathLength), ...path67];
6768
+ const wrappedCensor = typeof censor === "function" ? (value, path68) => {
6769
+ const fullPath = [...pathArray.slice(0, pathLength), ...path68];
6770
6770
  return censor(value, fullPath);
6771
6771
  } : censor;
6772
6772
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -6801,8 +6801,8 @@ var require_redact = __commonJS({
6801
6801
  return null;
6802
6802
  }
6803
6803
  const pathStructure = /* @__PURE__ */ new Map();
6804
- for (const path67 of pathsToClone) {
6805
- const parts = parsePath(path67);
6804
+ for (const path68 of pathsToClone) {
6805
+ const parts = parsePath(path68);
6806
6806
  let current = pathStructure;
6807
6807
  for (let i = 0; i < parts.length; i++) {
6808
6808
  const part = parts[i];
@@ -6854,24 +6854,24 @@ var require_redact = __commonJS({
6854
6854
  }
6855
6855
  return cloneSelectively(obj, pathStructure);
6856
6856
  }
6857
- function validatePath(path67) {
6858
- if (typeof path67 !== "string") {
6857
+ function validatePath(path68) {
6858
+ if (typeof path68 !== "string") {
6859
6859
  throw new Error("Paths must be (non-empty) strings");
6860
6860
  }
6861
- if (path67 === "") {
6861
+ if (path68 === "") {
6862
6862
  throw new Error("Invalid redaction path ()");
6863
6863
  }
6864
- if (path67.includes("..")) {
6865
- throw new Error(`Invalid redaction path (${path67})`);
6864
+ if (path68.includes("..")) {
6865
+ throw new Error(`Invalid redaction path (${path68})`);
6866
6866
  }
6867
- if (path67.includes(",")) {
6868
- throw new Error(`Invalid redaction path (${path67})`);
6867
+ if (path68.includes(",")) {
6868
+ throw new Error(`Invalid redaction path (${path68})`);
6869
6869
  }
6870
6870
  let bracketCount = 0;
6871
6871
  let inQuotes = false;
6872
6872
  let quoteChar = "";
6873
- for (let i = 0; i < path67.length; i++) {
6874
- const char = path67[i];
6873
+ for (let i = 0; i < path68.length; i++) {
6874
+ const char = path68[i];
6875
6875
  if ((char === '"' || char === "'") && bracketCount > 0) {
6876
6876
  if (!inQuotes) {
6877
6877
  inQuotes = true;
@@ -6885,20 +6885,20 @@ var require_redact = __commonJS({
6885
6885
  } else if (char === "]" && !inQuotes) {
6886
6886
  bracketCount--;
6887
6887
  if (bracketCount < 0) {
6888
- throw new Error(`Invalid redaction path (${path67})`);
6888
+ throw new Error(`Invalid redaction path (${path68})`);
6889
6889
  }
6890
6890
  }
6891
6891
  }
6892
6892
  if (bracketCount !== 0) {
6893
- throw new Error(`Invalid redaction path (${path67})`);
6893
+ throw new Error(`Invalid redaction path (${path68})`);
6894
6894
  }
6895
6895
  }
6896
6896
  function validatePaths(paths) {
6897
6897
  if (!Array.isArray(paths)) {
6898
6898
  throw new TypeError("paths must be an array");
6899
6899
  }
6900
- for (const path67 of paths) {
6901
- validatePath(path67);
6900
+ for (const path68 of paths) {
6901
+ validatePath(path68);
6902
6902
  }
6903
6903
  }
6904
6904
  function slowRedact(options = {}) {
@@ -7066,8 +7066,8 @@ var require_redaction = __commonJS({
7066
7066
  if (shape[k2] === null) {
7067
7067
  o[k2] = (value) => topCensor(value, [k2]);
7068
7068
  } else {
7069
- const wrappedCensor = typeof censor === "function" ? (value, path67) => {
7070
- return censor(value, [k2, ...path67]);
7069
+ const wrappedCensor = typeof censor === "function" ? (value, path68) => {
7070
+ return censor(value, [k2, ...path68]);
7071
7071
  } : censor;
7072
7072
  o[k2] = Redact({
7073
7073
  paths: shape[k2],
@@ -7288,7 +7288,7 @@ var require_sonic_boom = __commonJS({
7288
7288
  var fs61 = require("fs");
7289
7289
  var EventEmitter3 = require("events");
7290
7290
  var inherits = require("util").inherits;
7291
- var path67 = require("path");
7291
+ var path68 = require("path");
7292
7292
  var sleep2 = require_atomic_sleep();
7293
7293
  var assert = require("assert");
7294
7294
  var BUSY_WRITE_TIMEOUT = 100;
@@ -7342,7 +7342,7 @@ var require_sonic_boom = __commonJS({
7342
7342
  const mode = sonic.mode;
7343
7343
  if (sonic.sync) {
7344
7344
  try {
7345
- if (sonic.mkdir) fs61.mkdirSync(path67.dirname(file), { recursive: true });
7345
+ if (sonic.mkdir) fs61.mkdirSync(path68.dirname(file), { recursive: true });
7346
7346
  const fd = fs61.openSync(file, flags, mode);
7347
7347
  fileOpened(null, fd);
7348
7348
  } catch (err) {
@@ -7350,7 +7350,7 @@ var require_sonic_boom = __commonJS({
7350
7350
  throw err;
7351
7351
  }
7352
7352
  } else if (sonic.mkdir) {
7353
- fs61.mkdir(path67.dirname(file), { recursive: true }, (err) => {
7353
+ fs61.mkdir(path68.dirname(file), { recursive: true }, (err) => {
7354
7354
  if (err) return fileOpened(err);
7355
7355
  fs61.open(file, flags, mode, fileOpened);
7356
7356
  });
@@ -10210,7 +10210,7 @@ var require_multistream = __commonJS({
10210
10210
  var require_pino = __commonJS({
10211
10211
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
10212
10212
  "use strict";
10213
- var os22 = require("os");
10213
+ var os23 = require("os");
10214
10214
  var stdSerializers = require_pino_std_serializers();
10215
10215
  var caller = require_caller();
10216
10216
  var redaction = require_redaction();
@@ -10257,7 +10257,7 @@ var require_pino = __commonJS({
10257
10257
  } = symbols;
10258
10258
  var { epochTime, nullTime } = time;
10259
10259
  var { pid } = process;
10260
- var hostname = os22.hostname();
10260
+ var hostname = os23.hostname();
10261
10261
  var defaultErrorSerializer = stdSerializers.err;
10262
10262
  var defaultOptions = {
10263
10263
  level: "info",
@@ -10981,11 +10981,11 @@ var init_lib = __esm({
10981
10981
  }
10982
10982
  }
10983
10983
  },
10984
- addToPath: function addToPath(path67, added, removed, oldPosInc, options) {
10985
- var last = path67.lastComponent;
10984
+ addToPath: function addToPath(path68, added, removed, oldPosInc, options) {
10985
+ var last = path68.lastComponent;
10986
10986
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
10987
10987
  return {
10988
- oldPos: path67.oldPos + oldPosInc,
10988
+ oldPos: path68.oldPos + oldPosInc,
10989
10989
  lastComponent: {
10990
10990
  count: last.count + 1,
10991
10991
  added,
@@ -10995,7 +10995,7 @@ var init_lib = __esm({
10995
10995
  };
10996
10996
  } else {
10997
10997
  return {
10998
- oldPos: path67.oldPos + oldPosInc,
10998
+ oldPos: path68.oldPos + oldPosInc,
10999
10999
  lastComponent: {
11000
11000
  count: 1,
11001
11001
  added,
@@ -11053,7 +11053,7 @@ var init_lib = __esm({
11053
11053
  tokenize: function tokenize(value) {
11054
11054
  return Array.from(value);
11055
11055
  },
11056
- join: function join5(chars) {
11056
+ join: function join3(chars) {
11057
11057
  return chars.join("");
11058
11058
  },
11059
11059
  postProcess: function postProcess(changeObjects) {
@@ -11235,13 +11235,33 @@ var init_tool_result_extra = __esm({
11235
11235
  function cwdToHashDir(cwd) {
11236
11236
  return cwd.replace(/[^a-zA-Z0-9]/g, "-");
11237
11237
  }
11238
+ function newestSubagentMtimeMs(projectsRoot, cwd, toolSessionId) {
11239
+ const dir = import_node_path4.default.join(projectsRoot, cwdToHashDir(cwd), toolSessionId, "subagents");
11240
+ let entries;
11241
+ try {
11242
+ entries = import_node_fs4.default.readdirSync(dir, { withFileTypes: true });
11243
+ } catch {
11244
+ return null;
11245
+ }
11246
+ let newest = null;
11247
+ for (const e of entries) {
11248
+ if (!e.isFile()) continue;
11249
+ if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
11250
+ try {
11251
+ const m2 = import_node_fs4.default.statSync(import_node_path4.default.join(dir, e.name)).mtimeMs;
11252
+ if (newest === null || m2 > newest) newest = m2;
11253
+ } catch {
11254
+ }
11255
+ }
11256
+ return newest;
11257
+ }
11238
11258
  function hashDirToCwd(hash) {
11239
11259
  const body = hash.startsWith("-") ? hash.slice(1) : hash;
11240
11260
  return "/" + body.replace(/-/g, "/");
11241
11261
  }
11242
11262
  function safeStatMtime(p2) {
11243
11263
  try {
11244
- return import_node_fs13.default.statSync(p2).mtimeMs;
11264
+ return import_node_fs4.default.statSync(p2).mtimeMs;
11245
11265
  } catch {
11246
11266
  return 0;
11247
11267
  }
@@ -11249,7 +11269,7 @@ function safeStatMtime(p2) {
11249
11269
  function readJsonlLines(file) {
11250
11270
  let raw;
11251
11271
  try {
11252
- raw = import_node_fs13.default.readFileSync(file, "utf8");
11272
+ raw = import_node_fs4.default.readFileSync(file, "utf8");
11253
11273
  } catch (err) {
11254
11274
  if (err.code === "ENOENT") return [];
11255
11275
  throw err;
@@ -11441,10 +11461,10 @@ function attachmentToHistoryMessage(o, ts) {
11441
11461
  const memories = raw.map((m2) => {
11442
11462
  if (!m2 || typeof m2 !== "object") return null;
11443
11463
  const rec3 = m2;
11444
- const path67 = typeof rec3.path === "string" ? rec3.path : null;
11464
+ const path68 = typeof rec3.path === "string" ? rec3.path : null;
11445
11465
  const content = typeof rec3.content === "string" ? rec3.content : null;
11446
- if (!path67 || content == null) return null;
11447
- const entry = { path: path67, content };
11466
+ if (!path68 || content == null) return null;
11467
+ const entry = { path: path68, content };
11448
11468
  if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
11449
11469
  return entry;
11450
11470
  }).filter((m2) => m2 !== null);
@@ -11480,8 +11500,8 @@ function attachmentDeferredToolsText(a) {
11480
11500
  function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
11481
11501
  if (backupFileName === null) return null;
11482
11502
  try {
11483
- return import_node_fs13.default.readFileSync(
11484
- import_node_path12.default.join(fileHistoryRoot, toolSessionId, backupFileName),
11503
+ return import_node_fs4.default.readFileSync(
11504
+ import_node_path4.default.join(fileHistoryRoot, toolSessionId, backupFileName),
11485
11505
  "utf8"
11486
11506
  );
11487
11507
  } catch {
@@ -11490,19 +11510,19 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
11490
11510
  }
11491
11511
  function readCurrentContent(filePath) {
11492
11512
  try {
11493
- return import_node_fs13.default.readFileSync(filePath, "utf8");
11513
+ return import_node_fs4.default.readFileSync(filePath, "utf8");
11494
11514
  } catch (err) {
11495
11515
  if (err.code === "ENOENT") return null;
11496
11516
  return null;
11497
11517
  }
11498
11518
  }
11499
- var import_node_fs13, import_node_os5, import_node_path12, 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;
11519
+ var import_node_fs4, import_node_os3, import_node_path4, 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;
11500
11520
  var init_claude_history = __esm({
11501
11521
  "src/tools/claude-history.ts"() {
11502
11522
  "use strict";
11503
- import_node_fs13 = __toESM(require("fs"), 1);
11504
- import_node_os5 = __toESM(require("os"), 1);
11505
- import_node_path12 = __toESM(require("path"), 1);
11523
+ import_node_fs4 = __toESM(require("fs"), 1);
11524
+ import_node_os3 = __toESM(require("os"), 1);
11525
+ import_node_path4 = __toESM(require("path"), 1);
11506
11526
  init_lib();
11507
11527
  init_tool_result_extra();
11508
11528
  TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
@@ -11526,14 +11546,14 @@ var init_claude_history = __esm({
11526
11546
  // 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
11527
11547
  fileHistoryRoot;
11528
11548
  constructor(opts = {}) {
11529
- const base = opts.baseDir ?? import_node_path12.default.join(import_node_os5.default.homedir(), ".claude");
11530
- this.projectsRoot = import_node_path12.default.join(base, "projects");
11531
- this.fileHistoryRoot = import_node_path12.default.join(base, "file-history");
11549
+ const base = opts.baseDir ?? import_node_path4.default.join(import_node_os3.default.homedir(), ".claude");
11550
+ this.projectsRoot = import_node_path4.default.join(base, "projects");
11551
+ this.fileHistoryRoot = import_node_path4.default.join(base, "file-history");
11532
11552
  }
11533
11553
  async listProjects() {
11534
11554
  let entries;
11535
11555
  try {
11536
- entries = import_node_fs13.default.readdirSync(this.projectsRoot, { withFileTypes: true });
11556
+ entries = import_node_fs4.default.readdirSync(this.projectsRoot, { withFileTypes: true });
11537
11557
  } catch (err) {
11538
11558
  if (err.code === "ENOENT") return [];
11539
11559
  throw err;
@@ -11541,9 +11561,9 @@ var init_claude_history = __esm({
11541
11561
  const out = [];
11542
11562
  for (const ent of entries) {
11543
11563
  if (!ent.isDirectory()) continue;
11544
- const dir = import_node_path12.default.join(this.projectsRoot, ent.name);
11545
- const files = import_node_fs13.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11546
- const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path12.default.join(dir, f))), 0);
11564
+ const dir = import_node_path4.default.join(this.projectsRoot, ent.name);
11565
+ const files = import_node_fs4.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11566
+ const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path4.default.join(dir, f))), 0);
11547
11567
  out.push({
11548
11568
  projectPath: hashDirToCwd(ent.name),
11549
11569
  hashDir: ent.name,
@@ -11555,17 +11575,17 @@ var init_claude_history = __esm({
11555
11575
  return out;
11556
11576
  }
11557
11577
  async listSessions(args) {
11558
- const dir = import_node_path12.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
11578
+ const dir = import_node_path4.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
11559
11579
  let files;
11560
11580
  try {
11561
- files = import_node_fs13.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11581
+ files = import_node_fs4.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11562
11582
  } catch (err) {
11563
11583
  if (err.code === "ENOENT") return [];
11564
11584
  throw err;
11565
11585
  }
11566
11586
  const out = [];
11567
11587
  for (const f of files) {
11568
- const full = import_node_path12.default.join(dir, f);
11588
+ const full = import_node_path4.default.join(dir, f);
11569
11589
  const toolSessionId = f.slice(0, -".jsonl".length);
11570
11590
  const lines = readJsonlLines(full);
11571
11591
  let summary = "";
@@ -11620,7 +11640,7 @@ var init_claude_history = __esm({
11620
11640
  return out;
11621
11641
  }
11622
11642
  async read(args) {
11623
- const file = import_node_path12.default.join(
11643
+ const file = import_node_path4.default.join(
11624
11644
  this.projectsRoot,
11625
11645
  cwdToHashDir(args.cwd),
11626
11646
  `${args.toolSessionId}.jsonl`
@@ -11657,7 +11677,7 @@ var init_claude_history = __esm({
11657
11677
  // 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
11658
11678
  // 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
11659
11679
  listSubagentsFromDirectory(cwd, toolSessionId) {
11660
- const dir = import_node_path12.default.join(
11680
+ const dir = import_node_path4.default.join(
11661
11681
  this.projectsRoot,
11662
11682
  cwdToHashDir(cwd),
11663
11683
  toolSessionId,
@@ -11665,7 +11685,7 @@ var init_claude_history = __esm({
11665
11685
  );
11666
11686
  let entries;
11667
11687
  try {
11668
- entries = import_node_fs13.default.readdirSync(dir, { withFileTypes: true });
11688
+ entries = import_node_fs4.default.readdirSync(dir, { withFileTypes: true });
11669
11689
  } catch (err) {
11670
11690
  if (err.code === "ENOENT") return null;
11671
11691
  return null;
@@ -11675,7 +11695,7 @@ var init_claude_history = __esm({
11675
11695
  if (!e.isFile()) continue;
11676
11696
  if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
11677
11697
  const subagentId = e.name.slice("agent-".length, -".jsonl".length);
11678
- const filePath = import_node_path12.default.join(dir, e.name);
11698
+ const filePath = import_node_path4.default.join(dir, e.name);
11679
11699
  const lines = readJsonlLines(filePath);
11680
11700
  let firstText = "";
11681
11701
  let messageCount = 0;
@@ -11692,7 +11712,7 @@ var init_claude_history = __esm({
11692
11712
  return out;
11693
11713
  }
11694
11714
  listSubagentsFromMainJsonl(cwd, toolSessionId) {
11695
- const file = import_node_path12.default.join(
11715
+ const file = import_node_path4.default.join(
11696
11716
  this.projectsRoot,
11697
11717
  cwdToHashDir(cwd),
11698
11718
  `${toolSessionId}.jsonl`
@@ -11727,7 +11747,7 @@ var init_claude_history = __esm({
11727
11747
  }
11728
11748
  // 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
11729
11749
  readSubagentFromFile(cwd, toolSessionId, subagentId) {
11730
- const file = import_node_path12.default.join(
11750
+ const file = import_node_path4.default.join(
11731
11751
  this.projectsRoot,
11732
11752
  cwdToHashDir(cwd),
11733
11753
  toolSessionId,
@@ -11736,7 +11756,7 @@ var init_claude_history = __esm({
11736
11756
  );
11737
11757
  let exists = false;
11738
11758
  try {
11739
- exists = import_node_fs13.default.statSync(file).isFile();
11759
+ exists = import_node_fs4.default.statSync(file).isFile();
11740
11760
  } catch {
11741
11761
  return null;
11742
11762
  }
@@ -11755,7 +11775,7 @@ var init_claude_history = __esm({
11755
11775
  * "那一刻每个 tracked 文件对应的 backup 文件名"
11756
11776
  */
11757
11777
  readFileHistorySnapshots(args) {
11758
- const file = import_node_path12.default.join(
11778
+ const file = import_node_path4.default.join(
11759
11779
  this.projectsRoot,
11760
11780
  cwdToHashDir(args.cwd),
11761
11781
  `${args.toolSessionId}.jsonl`
@@ -11800,7 +11820,7 @@ var init_claude_history = __esm({
11800
11820
  for (const [anchorId, target] of snapshots) {
11801
11821
  let hasAny = false;
11802
11822
  for (const [rawPath, backup] of Object.entries(target)) {
11803
- const absPath = import_node_path12.default.isAbsolute(rawPath) ? rawPath : import_node_path12.default.join(args.cwd, rawPath);
11823
+ const absPath = import_node_path4.default.isAbsolute(rawPath) ? rawPath : import_node_path4.default.join(args.cwd, rawPath);
11804
11824
  const backupContent = readBackupContent(
11805
11825
  this.fileHistoryRoot,
11806
11826
  args.toolSessionId,
@@ -11840,7 +11860,7 @@ var init_claude_history = __esm({
11840
11860
  let totalInsertions = 0;
11841
11861
  let totalDeletions = 0;
11842
11862
  for (const [rawPath, backup] of Object.entries(target)) {
11843
- const absPath = import_node_path12.default.isAbsolute(rawPath) ? rawPath : import_node_path12.default.join(args.cwd, rawPath);
11863
+ const absPath = import_node_path4.default.isAbsolute(rawPath) ? rawPath : import_node_path4.default.join(args.cwd, rawPath);
11844
11864
  const backupContent = readBackupContent(
11845
11865
  this.fileHistoryRoot,
11846
11866
  args.toolSessionId,
@@ -11887,7 +11907,7 @@ var init_claude_history = __esm({
11887
11907
  };
11888
11908
  }
11889
11909
  readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
11890
- const file = import_node_path12.default.join(
11910
+ const file = import_node_path4.default.join(
11891
11911
  this.projectsRoot,
11892
11912
  cwdToHashDir(cwd),
11893
11913
  `${toolSessionId}.jsonl`
@@ -12256,10 +12276,10 @@ function parseAttachment(obj) {
12256
12276
  const memories = raw.map((m2) => {
12257
12277
  if (!m2 || typeof m2 !== "object") return null;
12258
12278
  const rec3 = m2;
12259
- const path67 = typeof rec3.path === "string" ? rec3.path : null;
12279
+ const path68 = typeof rec3.path === "string" ? rec3.path : null;
12260
12280
  const content = typeof rec3.content === "string" ? rec3.content : null;
12261
- if (!path67 || content == null) return null;
12262
- const out = { path: path67, content };
12281
+ if (!path68 || content == null) return null;
12282
+ const out = { path: path68, content };
12263
12283
  if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
12264
12284
  return out;
12265
12285
  }).filter((m2) => m2 !== null);
@@ -12391,8 +12411,9 @@ var init_claude = __esm({
12391
12411
  };
12392
12412
  CLAUDE_MODELS = [
12393
12413
  { id: "", label: "Default", description: "CLI default model", contextWindowSize: 2e5, default: true },
12394
- { id: "sonnet", label: "Sonnet", description: "Fast, balanced", contextWindowSize: 2e5 },
12395
12414
  { id: "opus", label: "Opus", description: "Most capable", contextWindowSize: 1e6 },
12415
+ { id: "fable", label: "Fable", contextWindowSize: 2e5 },
12416
+ { id: "sonnet", label: "Sonnet", description: "Fast, balanced", contextWindowSize: 2e5 },
12396
12417
  { id: "haiku", label: "Haiku", description: "Fastest, lightest", contextWindowSize: 2e5 }
12397
12418
  ];
12398
12419
  CLAUDE_PERMISSION_MODES = [
@@ -33223,8 +33244,8 @@ var require_utils = __commonJS({
33223
33244
  var result = transform[inputType][outputType](input);
33224
33245
  return result;
33225
33246
  };
33226
- exports2.resolve = function(path67) {
33227
- var parts = path67.split("/");
33247
+ exports2.resolve = function(path68) {
33248
+ var parts = path68.split("/");
33228
33249
  var result = [];
33229
33250
  for (var index = 0; index < parts.length; index++) {
33230
33251
  var part = parts[index];
@@ -39077,18 +39098,18 @@ var require_object = __commonJS({
39077
39098
  var object = new ZipObject(name, zipObjectContent, o);
39078
39099
  this.files[name] = object;
39079
39100
  };
39080
- var parentFolder = function(path67) {
39081
- if (path67.slice(-1) === "/") {
39082
- path67 = path67.substring(0, path67.length - 1);
39101
+ var parentFolder = function(path68) {
39102
+ if (path68.slice(-1) === "/") {
39103
+ path68 = path68.substring(0, path68.length - 1);
39083
39104
  }
39084
- var lastSlash = path67.lastIndexOf("/");
39085
- return lastSlash > 0 ? path67.substring(0, lastSlash) : "";
39105
+ var lastSlash = path68.lastIndexOf("/");
39106
+ return lastSlash > 0 ? path68.substring(0, lastSlash) : "";
39086
39107
  };
39087
- var forceTrailingSlash = function(path67) {
39088
- if (path67.slice(-1) !== "/") {
39089
- path67 += "/";
39108
+ var forceTrailingSlash = function(path68) {
39109
+ if (path68.slice(-1) !== "/") {
39110
+ path68 += "/";
39090
39111
  }
39091
- return path67;
39112
+ return path68;
39092
39113
  };
39093
39114
  var folderAdd = function(name, createFolders) {
39094
39115
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -40090,7 +40111,7 @@ var require_lib3 = __commonJS({
40090
40111
  // src/run-case/recorder.ts
40091
40112
  function startRunCaseRecorder(opts) {
40092
40113
  const now = opts.now ?? Date.now;
40093
- const dir = import_node_path55.default.dirname(opts.recordPath);
40114
+ const dir = import_node_path56.default.dirname(opts.recordPath);
40094
40115
  let stream = null;
40095
40116
  let closing = false;
40096
40117
  let closedSettled = false;
@@ -40130,12 +40151,12 @@ function startRunCaseRecorder(opts) {
40130
40151
  };
40131
40152
  return { tap, close, closed };
40132
40153
  }
40133
- var import_node_fs43, import_node_path55;
40154
+ var import_node_fs43, import_node_path56;
40134
40155
  var init_recorder = __esm({
40135
40156
  "src/run-case/recorder.ts"() {
40136
40157
  "use strict";
40137
40158
  import_node_fs43 = __toESM(require("fs"), 1);
40138
- import_node_path55 = __toESM(require("path"), 1);
40159
+ import_node_path56 = __toESM(require("path"), 1);
40139
40160
  }
40140
40161
  });
40141
40162
 
@@ -40178,7 +40199,7 @@ var init_wire = __esm({
40178
40199
  // src/run-case/controller.ts
40179
40200
  async function runController(opts) {
40180
40201
  const now = opts.now ?? Date.now;
40181
- const cwd = opts.cwd ?? (0, import_node_fs44.mkdtempSync)(import_node_path56.default.join(import_node_os21.default.tmpdir(), "clawd-runcase-"));
40202
+ const cwd = opts.cwd ?? (0, import_node_fs44.mkdtempSync)(import_node_path57.default.join(import_node_os22.default.tmpdir(), "clawd-runcase-"));
40182
40203
  const ownsCwd = opts.cwd === void 0;
40183
40204
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
40184
40205
  const spawnCtx = { cwd };
@@ -40345,13 +40366,13 @@ async function runController(opts) {
40345
40366
  }
40346
40367
  return exitCode ?? 0;
40347
40368
  }
40348
- var import_node_fs44, import_node_os21, import_node_path56;
40369
+ var import_node_fs44, import_node_os22, import_node_path57;
40349
40370
  var init_controller = __esm({
40350
40371
  "src/run-case/controller.ts"() {
40351
40372
  "use strict";
40352
40373
  import_node_fs44 = require("fs");
40353
- import_node_os21 = __toESM(require("os"), 1);
40354
- import_node_path56 = __toESM(require("path"), 1);
40374
+ import_node_os22 = __toESM(require("os"), 1);
40375
+ import_node_path57 = __toESM(require("path"), 1);
40355
40376
  init_claude();
40356
40377
  init_stdout_splitter();
40357
40378
  init_permission_stdio();
@@ -40613,9 +40634,9 @@ Env (advanced):
40613
40634
  `;
40614
40635
 
40615
40636
  // src/index.ts
40616
- var import_node_path54 = __toESM(require("path"), 1);
40637
+ var import_node_path55 = __toESM(require("path"), 1);
40617
40638
  var import_node_fs42 = __toESM(require("fs"), 1);
40618
- var import_node_os20 = __toESM(require("os"), 1);
40639
+ var import_node_os21 = __toESM(require("os"), 1);
40619
40640
 
40620
40641
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
40621
40642
  var byteToHex = [];
@@ -41232,9 +41253,9 @@ var SessionStoreFactory = class {
41232
41253
  };
41233
41254
 
41234
41255
  // src/session/manager.ts
41235
- var import_node_fs6 = __toESM(require("fs"), 1);
41236
- var import_node_path6 = __toESM(require("path"), 1);
41237
- var import_node_os3 = __toESM(require("os"), 1);
41256
+ var import_node_fs7 = __toESM(require("fs"), 1);
41257
+ var import_node_path8 = __toESM(require("path"), 1);
41258
+ var import_node_os5 = __toESM(require("os"), 1);
41238
41259
  init_protocol();
41239
41260
 
41240
41261
  // src/tools/guest-settings.ts
@@ -41332,6 +41353,10 @@ function escapeAttr(v2) {
41332
41353
  return v2.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
41333
41354
  }
41334
41355
 
41356
+ // src/session/runner.ts
41357
+ var import_node_os4 = __toESM(require("os"), 1);
41358
+ var import_node_path6 = __toESM(require("path"), 1);
41359
+
41335
41360
  // src/session/reducer.ts
41336
41361
  init_runtime();
41337
41362
 
@@ -41418,7 +41443,7 @@ var ATTACHMENT_SHARING_HINT = `## \u628A\u4EA7\u51FA\u6587\u4EF6\u5206\u4EAB\u7E
41418
41443
  // src/dispatch/system-prompt.ts
41419
41444
  var DISPATCH_SYSTEM_PROMPT_HINT = `## \u59D4\u6D3E\u7ED9\u53E6\u4E00\u4E2A persona\uFF08dispatch\uFF09
41420
41445
 
41421
- \u5F53\u7528\u6237\u6D88\u606F\u91CC\u542B \`@persona/<id>\`\uFF08\u5982 \`@persona/persona-bug-fixer\`\uFF09\u65F6\uFF0C**\u4F60\u5FC5\u987B**\u7ACB\u5373\u8C03 MCP tool \`mcp__clawd-dispatch__personaDispatch\` \u59D4\u6D3E\uFF0C\u4E0D\u8981\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF1A
41446
+ \u5F53\u7528\u6237\u6D88\u606F\u91CC\u542B \`@persona/<id>\`\uFF08\u5982 \`@persona/persona-app-builder\`\uFF09\u65F6\uFF0C**\u4F60\u5FC5\u987B**\u7ACB\u5373\u8C03 MCP tool \`mcp__clawd-dispatch__personaDispatch\` \u59D4\u6D3E\uFF0C\u4E0D\u8981\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF1A
41422
41447
 
41423
41448
  - \`targetPersona = <id>\`\uFF08@ token \u91CC\u7684 persona id\uFF09
41424
41449
  - \`prompt = \u53BB\u6389 @persona/<id> token \u7684\u7528\u6237\u539F\u6587\`
@@ -41470,7 +41495,7 @@ function cloneState(s) {
41470
41495
  pendingSend: s.pendingSend.slice()
41471
41496
  };
41472
41497
  }
41473
- var IDLE_KILL_DELAY_MS = 6e4;
41498
+ var IDLE_KILL_DELAY_MS = 6e5;
41474
41499
  function tryFlushPending(state, deps) {
41475
41500
  if (!state.readyForSend || state.pendingSend.length === 0) return [];
41476
41501
  const text = state.pendingSend.shift();
@@ -42141,6 +42166,18 @@ function reduceSession(state, input, deps) {
42141
42166
  if (state.status !== "running-idle") {
42142
42167
  return { state, effects: [] };
42143
42168
  }
42169
+ if (input.subagentActive) {
42170
+ return {
42171
+ state,
42172
+ effects: [
42173
+ {
42174
+ kind: "schedule-idle-kill",
42175
+ sessionId: state.file.sessionId,
42176
+ ms: IDLE_KILL_DELAY_MS
42177
+ }
42178
+ ]
42179
+ };
42180
+ }
42144
42181
  const next = cloneState(state);
42145
42182
  next.status = "stopping";
42146
42183
  return {
@@ -42197,10 +42234,11 @@ function reduceSession(state, input, deps) {
42197
42234
  // src/session/runner.ts
42198
42235
  init_stdout_splitter();
42199
42236
  init_permission_stdio();
42237
+ init_claude_history();
42200
42238
 
42201
42239
  // src/ipc-recorder.ts
42202
- var import_node_fs4 = __toESM(require("fs"), 1);
42203
- var import_node_path4 = __toESM(require("path"), 1);
42240
+ var import_node_fs5 = __toESM(require("fs"), 1);
42241
+ var import_node_path5 = __toESM(require("path"), 1);
42204
42242
  function tsForFilename(ms) {
42205
42243
  return new Date(ms).toISOString().replace(/[:.]/g, "-");
42206
42244
  }
@@ -42211,8 +42249,8 @@ function startRecorder(opts) {
42211
42249
  return null;
42212
42250
  }
42213
42251
  const now = opts.now ?? Date.now;
42214
- const dir = import_node_path4.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
42215
- const filePath = import_node_path4.default.join(dir, `${tsForFilename(now())}.jsonl`);
42252
+ const dir = import_node_path5.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
42253
+ const filePath = import_node_path5.default.join(dir, `${tsForFilename(now())}.jsonl`);
42216
42254
  let stream = null;
42217
42255
  let closedResolve;
42218
42256
  const closed = new Promise((resolve6) => {
@@ -42221,8 +42259,8 @@ function startRecorder(opts) {
42221
42259
  let exited = false;
42222
42260
  const ensureStream = () => {
42223
42261
  if (stream) return stream;
42224
- import_node_fs4.default.mkdirSync(dir, { recursive: true });
42225
- stream = import_node_fs4.default.createWriteStream(filePath, { flags: "a" });
42262
+ import_node_fs5.default.mkdirSync(dir, { recursive: true });
42263
+ stream = import_node_fs5.default.createWriteStream(filePath, { flags: "a" });
42226
42264
  stream.on("close", () => closedResolve());
42227
42265
  return stream;
42228
42266
  };
@@ -42267,6 +42305,7 @@ function encodeAllowWithInputControlResponse(requestId, updatedInput) {
42267
42305
  return JSON.stringify(payload) + "\n";
42268
42306
  }
42269
42307
  var DEFAULT_WAIT_STOP_TIMEOUT_MS = 3e3;
42308
+ var SUBAGENT_ACTIVE_WINDOW_MS = 3e5;
42270
42309
  var SessionRunner = class {
42271
42310
  constructor(initial, hooks) {
42272
42311
  this.hooks = hooks;
@@ -42579,7 +42618,7 @@ var SessionRunner = class {
42579
42618
  if (existing) clearTimeout(existing);
42580
42619
  const timer = setTimeout(() => {
42581
42620
  this.idleKillTimers.delete(effect.sessionId);
42582
- this.input({ kind: "idle-kill-fired" });
42621
+ this.input({ kind: "idle-kill-fired", subagentActive: this.isSubagentActive() });
42583
42622
  }, effect.ms);
42584
42623
  timer.unref?.();
42585
42624
  this.idleKillTimers.set(effect.sessionId, timer);
@@ -42595,6 +42634,18 @@ var SessionRunner = class {
42595
42634
  }
42596
42635
  }
42597
42636
  }
42637
+ // idle-kill 到点判定:本 session 的 subagents/ 里是否还有 agent-*.jsonl 在近期写盘。
42638
+ // 新鲜(近 SUBAGENT_ACTIVE_WINDOW_MS 内有写)= 后台 subagent 还在干活 → 不该杀。
42639
+ // 没有 toolSessionId(SDK 模式 CC 内生 id)/ 无目录 / 无 agent 文件 → false(照常回收)。
42640
+ isSubagentActive() {
42641
+ const toolSessionId = this.state.file.toolSessionId;
42642
+ if (!toolSessionId) return false;
42643
+ const projectsRoot = import_node_path6.default.join(this.hooks.home ?? import_node_os4.default.homedir(), ".claude", "projects");
42644
+ const mtime = newestSubagentMtimeMs(projectsRoot, this.state.file.cwd, toolSessionId);
42645
+ if (mtime === null) return false;
42646
+ const now = (this.hooks.now ?? Date.now)();
42647
+ return now - mtime < SUBAGENT_ACTIVE_WINDOW_MS;
42648
+ }
42598
42649
  // 清空所有 idle-kill timer(runner dispose / proc 永久退出时调用)。
42599
42650
  // 不喂 idle-kill-fired —— dispose 路径不再翻 reducer 状态
42600
42651
  clearIdleKillTimers() {
@@ -42677,15 +42728,15 @@ function extractEditPath(input) {
42677
42728
  }
42678
42729
 
42679
42730
  // src/debug/pty-probe.ts
42680
- var import_node_fs5 = __toESM(require("fs"), 1);
42681
- var import_node_path5 = __toESM(require("path"), 1);
42731
+ var import_node_fs6 = __toESM(require("fs"), 1);
42732
+ var import_node_path7 = __toESM(require("path"), 1);
42682
42733
  var PROBE_DIR = "/tmp/clawd-probe";
42683
- var EVENTS_FILE = import_node_path5.default.join(PROBE_DIR, "events.jsonl");
42734
+ var EVENTS_FILE = import_node_path7.default.join(PROBE_DIR, "events.jsonl");
42684
42735
  var inited = false;
42685
42736
  function ensureDir() {
42686
42737
  if (inited) return true;
42687
42738
  try {
42688
- import_node_fs5.default.mkdirSync(PROBE_DIR, { recursive: true });
42739
+ import_node_fs6.default.mkdirSync(PROBE_DIR, { recursive: true });
42689
42740
  inited = true;
42690
42741
  return true;
42691
42742
  } catch {
@@ -42696,15 +42747,15 @@ function probeEvent(event, data = {}) {
42696
42747
  try {
42697
42748
  if (!ensureDir()) return;
42698
42749
  const line = JSON.stringify({ ts: Date.now(), event, ...data }) + "\n";
42699
- import_node_fs5.default.appendFileSync(EVENTS_FILE, line);
42750
+ import_node_fs6.default.appendFileSync(EVENTS_FILE, line);
42700
42751
  } catch {
42701
42752
  }
42702
42753
  }
42703
42754
  function probeDumpReplay(sessionId, payload) {
42704
42755
  try {
42705
42756
  if (!ensureDir()) return "";
42706
- const file = import_node_path5.default.join(PROBE_DIR, `replay-${sessionId}-${Date.now()}.ans`);
42707
- import_node_fs5.default.writeFileSync(file, payload, "utf8");
42757
+ const file = import_node_path7.default.join(PROBE_DIR, `replay-${sessionId}-${Date.now()}.ans`);
42758
+ import_node_fs6.default.writeFileSync(file, payload, "utf8");
42708
42759
  return file;
42709
42760
  } catch {
42710
42761
  return "";
@@ -42811,7 +42862,7 @@ function derivePersonaSpawnCwd(file, personaRoot) {
42811
42862
  `derivePersonaSpawnCwd: personaRoot missing for owner session ${file.sessionId} (ownerPersonaId=${personaId})`
42812
42863
  );
42813
42864
  }
42814
- return import_node_path6.default.join(personaRoot, safeFileName(personaId));
42865
+ return import_node_path8.default.join(personaRoot, safeFileName(personaId));
42815
42866
  }
42816
42867
  function makeInitialState(file, subSessionMeta) {
42817
42868
  return {
@@ -42936,10 +42987,10 @@ var SessionManager = class {
42936
42987
  // <dataDir>/sessions/ 列子目录 (排除 'default').
42937
42988
  listPersonaIdsOnDisk() {
42938
42989
  if (!this.deps.dataDir) return [];
42939
- const root = this.deps.storeFactory ? import_node_path6.default.join(this.deps.dataDir, "personas") : import_node_path6.default.join(this.deps.dataDir, "sessions");
42990
+ const root = this.deps.storeFactory ? import_node_path8.default.join(this.deps.dataDir, "personas") : import_node_path8.default.join(this.deps.dataDir, "sessions");
42940
42991
  let entries;
42941
42992
  try {
42942
- entries = import_node_fs6.default.readdirSync(root, { withFileTypes: true });
42993
+ entries = import_node_fs7.default.readdirSync(root, { withFileTypes: true });
42943
42994
  } catch (err) {
42944
42995
  const code = err?.code;
42945
42996
  if (code === "ENOENT") return [];
@@ -42952,7 +43003,7 @@ var SessionManager = class {
42952
43003
  // 只在 storeFactory 注入 (新布局) 下生效, 老布局无 guest 目录.
42953
43004
  listGuestCapIdsForPersona(personaId) {
42954
43005
  if (!this.deps.dataDir || !this.deps.storeFactory) return [];
42955
- const root = import_node_path6.default.join(
43006
+ const root = import_node_path8.default.join(
42956
43007
  this.deps.dataDir,
42957
43008
  "personas",
42958
43009
  personaId,
@@ -42962,7 +43013,7 @@ var SessionManager = class {
42962
43013
  );
42963
43014
  let entries;
42964
43015
  try {
42965
- entries = import_node_fs6.default.readdirSync(root, { withFileTypes: true });
43016
+ entries = import_node_fs7.default.readdirSync(root, { withFileTypes: true });
42966
43017
  } catch (err) {
42967
43018
  const code = err?.code;
42968
43019
  if (code === "ENOENT") return [];
@@ -43081,7 +43132,7 @@ var SessionManager = class {
43081
43132
  callerDisplayName
43082
43133
  );
43083
43134
  if (subSessionMeta?.userWorkDir) {
43084
- import_node_fs6.default.mkdirSync(subSessionMeta.userWorkDir, { recursive: true });
43135
+ import_node_fs7.default.mkdirSync(subSessionMeta.userWorkDir, { recursive: true });
43085
43136
  }
43086
43137
  if (scope.kind === "persona" && scope.mode === "guest") {
43087
43138
  if (!this.deps.personaRoot || !subSessionMeta?.userWorkDir) {
@@ -43092,8 +43143,8 @@ var SessionManager = class {
43092
43143
  const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
43093
43144
  const settings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
43094
43145
  subSessionMeta.extraSettings = JSON.stringify(settings);
43095
- const home = import_node_os3.default.homedir();
43096
- const expand = (p2) => p2 === "~" ? home : p2.startsWith("~/") ? import_node_path6.default.join(home, p2.slice(2)) : p2;
43146
+ const home = import_node_os5.default.homedir();
43147
+ const expand = (p2) => p2 === "~" ? home : p2.startsWith("~/") ? import_node_path8.default.join(home, p2.slice(2)) : p2;
43097
43148
  const codexCfg = this.deps.personaStore?.readCodexSandboxSettings(scope.personaId) ?? null;
43098
43149
  subSessionMeta.codexSandbox = {
43099
43150
  writableRoots: [subSessionMeta.userWorkDir, ...(codexCfg?.writableRoots ?? []).map(expand)],
@@ -43246,7 +43297,7 @@ var SessionManager = class {
43246
43297
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "cwd required when ownerPersonaId is absent");
43247
43298
  }
43248
43299
  try {
43249
- const stat = import_node_fs6.default.statSync(cwd);
43300
+ const stat = import_node_fs7.default.statSync(cwd);
43250
43301
  if (!stat.isDirectory()) throw new Error("not dir");
43251
43302
  } catch {
43252
43303
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${cwd}`);
@@ -43777,7 +43828,7 @@ var SessionManager = class {
43777
43828
  */
43778
43829
  createForScope(args) {
43779
43830
  try {
43780
- const stat = import_node_fs6.default.statSync(args.cwd);
43831
+ const stat = import_node_fs7.default.statSync(args.cwd);
43781
43832
  if (!stat.isDirectory()) throw new Error("not dir");
43782
43833
  } catch {
43783
43834
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
@@ -43993,7 +44044,7 @@ var SessionManager = class {
43993
44044
  personaId: args.targetPersona,
43994
44045
  mode: "owner"
43995
44046
  };
43996
- const cwd = import_node_path6.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44047
+ const cwd = import_node_path8.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
43997
44048
  const now = (/* @__PURE__ */ new Date()).toISOString();
43998
44049
  const file = {
43999
44050
  sessionId,
@@ -44058,7 +44109,7 @@ var SessionManager = class {
44058
44109
  personaId: args.targetPersona,
44059
44110
  mode: "owner"
44060
44111
  };
44061
- const cwd = import_node_path6.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44112
+ const cwd = import_node_path8.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44062
44113
  const now = (/* @__PURE__ */ new Date()).toISOString();
44063
44114
  const file = {
44064
44115
  sessionId,
@@ -44540,28 +44591,28 @@ var SessionManager = class {
44540
44591
  };
44541
44592
 
44542
44593
  // src/persona/store.ts
44543
- var fs7 = __toESM(require("fs"), 1);
44544
- var path9 = __toESM(require("path"), 1);
44594
+ var fs8 = __toESM(require("fs"), 1);
44595
+ var path11 = __toESM(require("path"), 1);
44545
44596
  init_protocol();
44546
44597
  var PersonaStore = class {
44547
44598
  constructor(root) {
44548
44599
  this.root = root;
44549
- fs7.mkdirSync(root, { recursive: true });
44600
+ fs8.mkdirSync(root, { recursive: true });
44550
44601
  }
44551
44602
  root;
44552
44603
  personaDir(personaId) {
44553
- return path9.join(this.root, safeFileName(personaId));
44604
+ return path11.join(this.root, safeFileName(personaId));
44554
44605
  }
44555
44606
  metaPath(personaId) {
44556
- return path9.join(this.personaDir(personaId), ".clawd", "persona.json");
44607
+ return path11.join(this.personaDir(personaId), ".clawd", "persona.json");
44557
44608
  }
44558
44609
  claudeMdPath(personaId) {
44559
- return path9.join(this.personaDir(personaId), "CLAUDE.md");
44610
+ return path11.join(this.personaDir(personaId), "CLAUDE.md");
44560
44611
  }
44561
44612
  // codex 原生读 cwd 的 AGENTS.md。人格双写镜像:claude 读 CLAUDE.md、codex 读 AGENTS.md,
44562
44613
  // 两份内容恒一致,persona 切 tool 零迁移。
44563
44614
  agentsMdPath(personaId) {
44564
- return path9.join(this.personaDir(personaId), "AGENTS.md");
44615
+ return path11.join(this.personaDir(personaId), "AGENTS.md");
44565
44616
  }
44566
44617
  /**
44567
44618
  * persona 级 sandbox base 落盘路径 —— 故意放 `.clawd/` 而非 `.claude/`,让 CC 的 project
@@ -44570,11 +44621,11 @@ var PersonaStore = class {
44570
44621
  * spawn 前 per-guest 动态拼到各自 session 目录的那份(base + 强制底座 + 本 guest userWorkDir carve)。
44571
44622
  */
44572
44623
  sandboxSettingsPath(personaId) {
44573
- return path9.join(this.personaDir(personaId), ".clawd", "sandbox-settings.json");
44624
+ return path11.join(this.personaDir(personaId), ".clawd", "sandbox-settings.json");
44574
44625
  }
44575
44626
  write(persona, personality) {
44576
44627
  const dir = this.personaDir(persona.personaId);
44577
- fs7.mkdirSync(path9.join(dir, ".clawd"), { recursive: true });
44628
+ fs8.mkdirSync(path11.join(dir, ".clawd"), { recursive: true });
44578
44629
  this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
44579
44630
  this.atomicWrite(this.agentsMdPath(persona.personaId), personality);
44580
44631
  this.writeSandboxSettings(persona.personaId, buildGuestSettingsV1());
@@ -44593,9 +44644,9 @@ var PersonaStore = class {
44593
44644
  ensureAgentsMirror(personaId) {
44594
44645
  const claudeMd = this.claudeMdPath(personaId);
44595
44646
  const agentsMd = this.agentsMdPath(personaId);
44596
- if (!fs7.existsSync(claudeMd)) return false;
44597
- if (fs7.existsSync(agentsMd)) return false;
44598
- this.atomicWrite(agentsMd, fs7.readFileSync(claudeMd, "utf8"));
44647
+ if (!fs8.existsSync(claudeMd)) return false;
44648
+ if (fs8.existsSync(agentsMd)) return false;
44649
+ this.atomicWrite(agentsMd, fs8.readFileSync(claudeMd, "utf8"));
44599
44650
  return true;
44600
44651
  }
44601
44652
  /**
@@ -44619,22 +44670,22 @@ var PersonaStore = class {
44619
44670
  return { ...s, permissions: { ...s.permissions ?? {}, deny: [...prev, rule] } };
44620
44671
  }
44621
44672
  codexSandboxSettingsPath(personaId) {
44622
- return path9.join(this.personaDir(personaId), ".clawd", "codex-sandbox.json");
44673
+ return path11.join(this.personaDir(personaId), ".clawd", "codex-sandbox.json");
44623
44674
  }
44624
44675
  /** 读 codex-sandbox.json;不存在/损坏 → null。 */
44625
44676
  readCodexSandboxSettings(personaId) {
44626
44677
  const p2 = this.codexSandboxSettingsPath(personaId);
44627
- if (!fs7.existsSync(p2)) return null;
44678
+ if (!fs8.existsSync(p2)) return null;
44628
44679
  try {
44629
- return CodexSandboxSettingsSchema.parse(JSON.parse(fs7.readFileSync(p2, "utf8")));
44680
+ return CodexSandboxSettingsSchema.parse(JSON.parse(fs8.readFileSync(p2, "utf8")));
44630
44681
  } catch {
44631
44682
  return null;
44632
44683
  }
44633
44684
  }
44634
44685
  /** 覆盖写 codex-sandbox.json(seed/migrate 用)。 */
44635
44686
  writeCodexSandboxSettings(personaId, settings) {
44636
- const dir = path9.join(this.personaDir(personaId), ".clawd");
44637
- fs7.mkdirSync(dir, { recursive: true });
44687
+ const dir = path11.join(this.personaDir(personaId), ".clawd");
44688
+ fs8.mkdirSync(dir, { recursive: true });
44638
44689
  this.atomicWrite(this.codexSandboxSettingsPath(personaId), JSON.stringify(settings, null, 2));
44639
44690
  }
44640
44691
  writeMeta(persona) {
@@ -44642,8 +44693,8 @@ var PersonaStore = class {
44642
44693
  }
44643
44694
  read(personaId) {
44644
44695
  const p2 = this.metaPath(personaId);
44645
- if (!fs7.existsSync(p2)) return null;
44646
- const raw = JSON.parse(fs7.readFileSync(p2, "utf8"));
44696
+ if (!fs8.existsSync(p2)) return null;
44697
+ const raw = JSON.parse(fs8.readFileSync(p2, "utf8"));
44647
44698
  if (raw && typeof raw === "object" && "tokenMap" in raw) {
44648
44699
  delete raw.tokenMap;
44649
44700
  this.atomicWrite(p2, JSON.stringify(raw, null, 2));
@@ -44651,13 +44702,13 @@ var PersonaStore = class {
44651
44702
  return PersonaFileSchema.parse(raw);
44652
44703
  }
44653
44704
  has(personaId) {
44654
- return fs7.existsSync(this.metaPath(personaId));
44705
+ return fs8.existsSync(this.metaPath(personaId));
44655
44706
  }
44656
44707
  readPersonality(personaId) {
44657
44708
  const claudeMd = this.claudeMdPath(personaId);
44658
- if (fs7.existsSync(claudeMd)) return fs7.readFileSync(claudeMd, "utf8");
44709
+ if (fs8.existsSync(claudeMd)) return fs8.readFileSync(claudeMd, "utf8");
44659
44710
  const agentsMd = this.agentsMdPath(personaId);
44660
- if (fs7.existsSync(agentsMd)) return fs7.readFileSync(agentsMd, "utf8");
44711
+ if (fs8.existsSync(agentsMd)) return fs8.readFileSync(agentsMd, "utf8");
44661
44712
  return null;
44662
44713
  }
44663
44714
  /**
@@ -44666,23 +44717,23 @@ var PersonaStore = class {
44666
44717
  */
44667
44718
  readSandboxSettings(personaId) {
44668
44719
  const p2 = this.sandboxSettingsPath(personaId);
44669
- if (!fs7.existsSync(p2)) return null;
44720
+ if (!fs8.existsSync(p2)) return null;
44670
44721
  try {
44671
- return JSON.parse(fs7.readFileSync(p2, "utf8"));
44722
+ return JSON.parse(fs8.readFileSync(p2, "utf8"));
44672
44723
  } catch {
44673
44724
  return null;
44674
44725
  }
44675
44726
  }
44676
44727
  /** Persona 私有 skills 目录路径:<personaDir>/.claude/skills */
44677
44728
  skillsDir(personaId) {
44678
- return path9.join(this.personaDir(personaId), ".claude", "skills");
44729
+ return path11.join(this.personaDir(personaId), ".claude", "skills");
44679
44730
  }
44680
44731
  /**
44681
44732
  * Claude Code 项目级 settings 路径:`<personaDir>/.claude/settings.json`。
44682
44733
  * 这里只读 `enabledPlugins` 字段,由 owner 通过 CC `/plugin` 之类命令维护,daemon 不写。
44683
44734
  */
44684
44735
  claudeSettingsPath(personaId) {
44685
- return path9.join(this.personaDir(personaId), ".claude", "settings.json");
44736
+ return path11.join(this.personaDir(personaId), ".claude", "settings.json");
44686
44737
  }
44687
44738
  /**
44688
44739
  * 读取 persona 的 `.claude/settings.json` 中 `enabledPlugins` map,把 value === true
@@ -44697,10 +44748,10 @@ var PersonaStore = class {
44697
44748
  */
44698
44749
  readEnabledPlugins(personaId) {
44699
44750
  const p2 = this.claudeSettingsPath(personaId);
44700
- if (!fs7.existsSync(p2)) return [];
44751
+ if (!fs8.existsSync(p2)) return [];
44701
44752
  let raw;
44702
44753
  try {
44703
- raw = JSON.parse(fs7.readFileSync(p2, "utf8"));
44754
+ raw = JSON.parse(fs8.readFileSync(p2, "utf8"));
44704
44755
  } catch {
44705
44756
  return [];
44706
44757
  }
@@ -44714,22 +44765,22 @@ var PersonaStore = class {
44714
44765
  return out;
44715
44766
  }
44716
44767
  list() {
44717
- if (!fs7.existsSync(this.root)) return [];
44718
- return fs7.readdirSync(this.root).filter((name) => {
44719
- return fs7.existsSync(path9.join(this.root, name, ".clawd", "persona.json"));
44768
+ if (!fs8.existsSync(this.root)) return [];
44769
+ return fs8.readdirSync(this.root).filter((name) => {
44770
+ return fs8.existsSync(path11.join(this.root, name, ".clawd", "persona.json"));
44720
44771
  });
44721
44772
  }
44722
44773
  remove(personaId) {
44723
44774
  const dir = this.personaDir(personaId);
44724
- if (fs7.existsSync(dir)) fs7.rmSync(dir, { recursive: true, force: true });
44775
+ if (fs8.existsSync(dir)) fs8.rmSync(dir, { recursive: true, force: true });
44725
44776
  }
44726
44777
  personaDirPath(personaId) {
44727
44778
  return this.personaDir(personaId);
44728
44779
  }
44729
44780
  atomicWrite(file, content) {
44730
44781
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
44731
- fs7.writeFileSync(tmp, content, { mode: 384 });
44732
- fs7.renameSync(tmp, file);
44782
+ fs8.writeFileSync(tmp, content, { mode: 384 });
44783
+ fs8.renameSync(tmp, file);
44733
44784
  }
44734
44785
  };
44735
44786
 
@@ -44775,9 +44826,9 @@ var PersonaRegistry = class {
44775
44826
  var import_node_crypto3 = __toESM(require("crypto"), 1);
44776
44827
 
44777
44828
  // src/skills/scanner.ts
44778
- var import_node_fs7 = __toESM(require("fs"), 1);
44779
- var import_node_os4 = __toESM(require("os"), 1);
44780
- var import_node_path7 = __toESM(require("path"), 1);
44829
+ var import_node_fs8 = __toESM(require("fs"), 1);
44830
+ var import_node_os6 = __toESM(require("os"), 1);
44831
+ var import_node_path9 = __toESM(require("path"), 1);
44781
44832
 
44782
44833
  // src/skills/frontmatter.ts
44783
44834
  var STRIP_QUOTES = /^["']|["']$/g;
@@ -44886,7 +44937,7 @@ function parseDescription(content) {
44886
44937
  }
44887
44938
  function isDirLikeSync(p2) {
44888
44939
  try {
44889
- return import_node_fs7.default.statSync(p2).isDirectory();
44940
+ return import_node_fs8.default.statSync(p2).isDirectory();
44890
44941
  } catch {
44891
44942
  return false;
44892
44943
  }
@@ -44894,19 +44945,19 @@ function isDirLikeSync(p2) {
44894
44945
  function scanSkillDir(dir, source, seen, out, pluginName) {
44895
44946
  let entries;
44896
44947
  try {
44897
- entries = import_node_fs7.default.readdirSync(dir, { withFileTypes: true });
44948
+ entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
44898
44949
  } catch {
44899
44950
  return;
44900
44951
  }
44901
44952
  for (const ent of entries) {
44902
- const entryPath = import_node_path7.default.join(dir, ent.name);
44953
+ const entryPath = import_node_path9.default.join(dir, ent.name);
44903
44954
  if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
44904
44955
  let content;
44905
44956
  try {
44906
- content = import_node_fs7.default.readFileSync(import_node_path7.default.join(entryPath, "SKILL.md"), "utf8");
44957
+ content = import_node_fs8.default.readFileSync(import_node_path9.default.join(entryPath, "SKILL.md"), "utf8");
44907
44958
  } catch {
44908
44959
  try {
44909
- content = import_node_fs7.default.readFileSync(import_node_path7.default.join(entryPath, "skill.md"), "utf8");
44960
+ content = import_node_fs8.default.readFileSync(import_node_path9.default.join(entryPath, "skill.md"), "utf8");
44910
44961
  } catch {
44911
44962
  continue;
44912
44963
  }
@@ -44930,26 +44981,26 @@ function listSkillsForDir(dir, source) {
44930
44981
  function scanCommandDir(dir, source, seen, out, pluginName) {
44931
44982
  let entries;
44932
44983
  try {
44933
- entries = import_node_fs7.default.readdirSync(dir, { withFileTypes: true });
44984
+ entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
44934
44985
  } catch {
44935
44986
  return;
44936
44987
  }
44937
44988
  for (const ent of entries) {
44938
- const entryPath = import_node_path7.default.join(dir, ent.name);
44989
+ const entryPath = import_node_path9.default.join(dir, ent.name);
44939
44990
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
44940
44991
  const ns = ent.name;
44941
44992
  let subEntries;
44942
44993
  try {
44943
- subEntries = import_node_fs7.default.readdirSync(entryPath, { withFileTypes: true });
44994
+ subEntries = import_node_fs8.default.readdirSync(entryPath, { withFileTypes: true });
44944
44995
  } catch {
44945
44996
  continue;
44946
44997
  }
44947
44998
  for (const se of subEntries) {
44948
44999
  if (!se.name.endsWith(".md")) continue;
44949
- const sePath = import_node_path7.default.join(entryPath, se.name);
45000
+ const sePath = import_node_path9.default.join(entryPath, se.name);
44950
45001
  let content;
44951
45002
  try {
44952
- content = import_node_fs7.default.readFileSync(sePath, "utf8");
45003
+ content = import_node_fs8.default.readFileSync(sePath, "utf8");
44953
45004
  } catch {
44954
45005
  continue;
44955
45006
  }
@@ -44966,7 +45017,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
44966
45017
  } else if (ent.name.endsWith(".md")) {
44967
45018
  let content;
44968
45019
  try {
44969
- content = import_node_fs7.default.readFileSync(entryPath, "utf8");
45020
+ content = import_node_fs8.default.readFileSync(entryPath, "utf8");
44970
45021
  } catch {
44971
45022
  continue;
44972
45023
  }
@@ -44982,10 +45033,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
44982
45033
  }
44983
45034
  }
44984
45035
  function readInstalledPlugins(home) {
44985
- const file = import_node_path7.default.join(home, ".claude", "plugins", "installed_plugins.json");
45036
+ const file = import_node_path9.default.join(home, ".claude", "plugins", "installed_plugins.json");
44986
45037
  let raw;
44987
45038
  try {
44988
- raw = import_node_fs7.default.readFileSync(file, "utf8");
45039
+ raw = import_node_fs8.default.readFileSync(file, "utf8");
44989
45040
  } catch {
44990
45041
  return [];
44991
45042
  }
@@ -45010,7 +45061,7 @@ var SkillsScanner = class {
45010
45061
  home;
45011
45062
  extraPluginRoots;
45012
45063
  constructor(opts = {}) {
45013
- this.home = opts.home ?? import_node_os4.default.homedir();
45064
+ this.home = opts.home ?? import_node_os6.default.homedir();
45014
45065
  this.extraPluginRoots = opts.extraPluginRoots ?? [];
45015
45066
  }
45016
45067
  /**
@@ -45033,14 +45084,14 @@ var SkillsScanner = class {
45033
45084
  });
45034
45085
  }
45035
45086
  const fsBlock = [];
45036
- scanSkillDir(import_node_path7.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
45037
- scanCommandDir(import_node_path7.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
45038
- scanSkillDir(import_node_path7.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
45039
- scanCommandDir(import_node_path7.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
45087
+ scanSkillDir(import_node_path9.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
45088
+ scanCommandDir(import_node_path9.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
45089
+ scanSkillDir(import_node_path9.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
45090
+ scanCommandDir(import_node_path9.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
45040
45091
  const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
45041
45092
  for (const { name, root } of plugins) {
45042
- scanSkillDir(import_node_path7.default.join(root, "skills"), "plugin", seen, fsBlock, name);
45043
- scanCommandDir(import_node_path7.default.join(root, "commands"), "plugin", seen, fsBlock, name);
45093
+ scanSkillDir(import_node_path9.default.join(root, "skills"), "plugin", seen, fsBlock, name);
45094
+ scanCommandDir(import_node_path9.default.join(root, "commands"), "plugin", seen, fsBlock, name);
45044
45095
  }
45045
45096
  fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
45046
45097
  return [...builtinBlock, ...fsBlock];
@@ -45146,8 +45197,8 @@ var PersonaManager = class {
45146
45197
  };
45147
45198
 
45148
45199
  // src/persona/seed.ts
45149
- var fs9 = __toESM(require("fs"), 1);
45150
- var path11 = __toESM(require("path"), 1);
45200
+ var fs10 = __toESM(require("fs"), 1);
45201
+ var path13 = __toESM(require("path"), 1);
45151
45202
  var import_node_url = require("url");
45152
45203
  var import_meta = {};
45153
45204
  var DEFAULT_BYPASS_PROFILE = {
@@ -45178,16 +45229,6 @@ var DEFAULT_PERSONAS = [
45178
45229
  public: false,
45179
45230
  sandboxProfile: DEFAULT_BYPASS_PROFILE
45180
45231
  },
45181
- {
45182
- // 工单管理员:纯操作员,按指令调 clawd-ticket MCP 增删改查 ticket。MCP 由 daemon 全局
45183
- // 注入(index.ts ticket-mcp wiring),persona 端不需要单独 .mcp.json。
45184
- personaId: "persona-ticket-manager",
45185
- label: "\u5DE5\u5355\u7BA1\u7406\u5458",
45186
- model: "opus",
45187
- iconKey: "assist",
45188
- public: false,
45189
- sandboxProfile: DEFAULT_BYPASS_PROFILE
45190
- },
45191
45232
  {
45192
45233
  personaId: "persona-feishu-assistant",
45193
45234
  label: "\u98DE\u4E66\u52A9\u7406",
@@ -45281,14 +45322,6 @@ var DEFAULT_PERSONAS = [
45281
45322
  public: false,
45282
45323
  sandboxProfile: DEFAULT_BYPASS_PROFILE
45283
45324
  },
45284
- {
45285
- personaId: "persona-bug-fixer",
45286
- label: "Bug \u4FEE\u590D\u5E08",
45287
- model: "opus",
45288
- iconKey: "debug",
45289
- public: false,
45290
- sandboxProfile: DEFAULT_BYPASS_PROFILE
45291
- },
45292
45325
  {
45293
45326
  // HTML PPT 制作师:把想法/文字/旧 PPT 转成单文件 HTML 演示稿
45294
45327
  // bundle 含 frontend-slides skill(MIT,Zara Zhang),daemon ship 进 .claude/skills/
@@ -45335,24 +45368,24 @@ function bundleSiblingFromArgv(argv1, sibling) {
45335
45368
  if (!argv1) return null;
45336
45369
  let real = argv1;
45337
45370
  try {
45338
- real = fs9.realpathSync(argv1);
45371
+ real = fs10.realpathSync(argv1);
45339
45372
  } catch {
45340
45373
  }
45341
- return path11.resolve(path11.dirname(real), sibling);
45374
+ return path13.resolve(path13.dirname(real), sibling);
45342
45375
  }
45343
45376
  function findDefaultsRoot(logger) {
45344
45377
  const candidates = [];
45345
45378
  try {
45346
- const here = path11.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
45347
- candidates.push(path11.resolve(here, "defaults"));
45348
- candidates.push(path11.resolve(here, "persona-defaults"));
45379
+ const here = path13.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
45380
+ candidates.push(path13.resolve(here, "defaults"));
45381
+ candidates.push(path13.resolve(here, "persona-defaults"));
45349
45382
  } catch {
45350
45383
  }
45351
45384
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "persona-defaults");
45352
45385
  if (fromArgv) candidates.push(fromArgv);
45353
45386
  for (const c of candidates) {
45354
45387
  try {
45355
- if (fs9.statSync(c).isDirectory()) {
45388
+ if (fs10.statSync(c).isDirectory()) {
45356
45389
  logger?.info("persona.defaults-root.resolved", { root: c });
45357
45390
  return c;
45358
45391
  }
@@ -45369,8 +45402,8 @@ function seedDefaultPersonas(args) {
45369
45402
  args.logger.info("persona.seed.skip", { personaId: entry.personaId, reason: "exists" });
45370
45403
  continue;
45371
45404
  }
45372
- const bundleDir = path11.join(args.defaultsRoot, entry.personaId);
45373
- if (!fs9.existsSync(bundleDir)) {
45405
+ const bundleDir = path13.join(args.defaultsRoot, entry.personaId);
45406
+ if (!fs10.existsSync(bundleDir)) {
45374
45407
  args.logger.warn("persona.seed.skip", {
45375
45408
  personaId: entry.personaId,
45376
45409
  reason: "bundle-missing",
@@ -45378,8 +45411,8 @@ function seedDefaultPersonas(args) {
45378
45411
  });
45379
45412
  continue;
45380
45413
  }
45381
- const claudeMdPath = path11.join(bundleDir, "CLAUDE.md");
45382
- if (!fs9.existsSync(claudeMdPath)) {
45414
+ const claudeMdPath = path13.join(bundleDir, "CLAUDE.md");
45415
+ if (!fs10.existsSync(claudeMdPath)) {
45383
45416
  args.logger.warn("persona.seed.skip", {
45384
45417
  personaId: entry.personaId,
45385
45418
  reason: "no-CLAUDE.md",
@@ -45387,7 +45420,7 @@ function seedDefaultPersonas(args) {
45387
45420
  });
45388
45421
  continue;
45389
45422
  }
45390
- const personality = fs9.readFileSync(claudeMdPath, "utf8");
45423
+ const personality = fs10.readFileSync(claudeMdPath, "utf8");
45391
45424
  const now = Date.now();
45392
45425
  const persona = {
45393
45426
  personaId: entry.personaId,
@@ -45413,17 +45446,17 @@ function seedDefaultPersonas(args) {
45413
45446
  }
45414
45447
  }
45415
45448
  function skipNodeModulesUnder(srcRoot) {
45416
- return (src) => !path11.relative(srcRoot, src).split(path11.sep).includes("node_modules");
45449
+ return (src) => !path13.relative(srcRoot, src).split(path13.sep).includes("node_modules");
45417
45450
  }
45418
45451
  function copyBundleExtras(srcDir, dstDir) {
45419
- for (const entry of fs9.readdirSync(srcDir, { withFileTypes: true })) {
45452
+ for (const entry of fs10.readdirSync(srcDir, { withFileTypes: true })) {
45420
45453
  if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
45421
- const srcPath = path11.join(srcDir, entry.name);
45422
- const dstPath = path11.join(dstDir, entry.name);
45454
+ const srcPath = path13.join(srcDir, entry.name);
45455
+ const dstPath = path13.join(dstDir, entry.name);
45423
45456
  if (entry.isDirectory()) {
45424
- fs9.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
45457
+ fs10.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
45425
45458
  } else if (entry.isFile()) {
45426
- fs9.copyFileSync(srcPath, dstPath);
45459
+ fs10.copyFileSync(srcPath, dstPath);
45427
45460
  }
45428
45461
  }
45429
45462
  }
@@ -45431,16 +45464,16 @@ var DAEMON_MANAGED_PATHS = ["extension-kit", "CLAUDE.md", ".mcp.json"];
45431
45464
  function refreshDaemonManagedDirs(args) {
45432
45465
  const entries = args.entries ?? DEFAULT_PERSONAS;
45433
45466
  for (const entry of entries) {
45434
- const bundleDir = path11.join(args.defaultsRoot, entry.personaId);
45435
- if (!fs9.existsSync(bundleDir)) continue;
45467
+ const bundleDir = path13.join(args.defaultsRoot, entry.personaId);
45468
+ if (!fs10.existsSync(bundleDir)) continue;
45436
45469
  const personaDir = args.store.personaDirPath(entry.personaId);
45437
- if (!fs9.existsSync(personaDir)) continue;
45470
+ if (!fs10.existsSync(personaDir)) continue;
45438
45471
  for (const relPath of DAEMON_MANAGED_PATHS) {
45439
- const srcPath = path11.join(bundleDir, relPath);
45440
- if (!fs9.existsSync(srcPath)) continue;
45441
- const dstPath = path11.join(personaDir, relPath);
45472
+ const srcPath = path13.join(bundleDir, relPath);
45473
+ if (!fs10.existsSync(srcPath)) continue;
45474
+ const dstPath = path13.join(personaDir, relPath);
45442
45475
  try {
45443
- fs9.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
45476
+ fs10.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
45444
45477
  args.logger.info("persona.refresh.synced", {
45445
45478
  personaId: entry.personaId,
45446
45479
  path: relPath
@@ -45500,15 +45533,15 @@ function migrateCodexSandbox(args) {
45500
45533
  function findDeployKitRoot(logger) {
45501
45534
  const candidates = [];
45502
45535
  try {
45503
- const here = path11.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
45504
- candidates.push(path11.resolve(here, "..", "deploy-kit"));
45536
+ const here = path13.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
45537
+ candidates.push(path13.resolve(here, "..", "deploy-kit"));
45505
45538
  } catch {
45506
45539
  }
45507
45540
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "deploy-kit");
45508
45541
  if (fromArgv) candidates.push(fromArgv);
45509
45542
  for (const c of candidates) {
45510
45543
  try {
45511
- if (fs9.statSync(c).isDirectory()) {
45544
+ if (fs10.statSync(c).isDirectory()) {
45512
45545
  logger?.info("persona.deploy-kit-root.resolved", { root: c });
45513
45546
  return c;
45514
45547
  }
@@ -45519,8 +45552,8 @@ function findDeployKitRoot(logger) {
45519
45552
  return null;
45520
45553
  }
45521
45554
  function seedDeployKit(args) {
45522
- const dst = path11.join(args.dataDir, "deploy-kit");
45523
- fs9.cpSync(args.deployKitBundleRoot, dst, {
45555
+ const dst = path13.join(args.dataDir, "deploy-kit");
45556
+ fs10.cpSync(args.deployKitBundleRoot, dst, {
45524
45557
  recursive: true,
45525
45558
  dereference: true,
45526
45559
  force: false,
@@ -45529,35 +45562,35 @@ function seedDeployKit(args) {
45529
45562
  args.logger.info("deploy-kit.seed.done", { dst });
45530
45563
  }
45531
45564
  function refreshDeployKit(args) {
45532
- const dst = path11.join(args.dataDir, "deploy-kit");
45533
- if (!fs9.existsSync(dst)) {
45565
+ const dst = path13.join(args.dataDir, "deploy-kit");
45566
+ if (!fs10.existsSync(dst)) {
45534
45567
  seedDeployKit(args);
45535
45568
  return;
45536
45569
  }
45537
45570
  for (const sub of ["scripts", "contract"]) {
45538
- const s = path11.join(args.deployKitBundleRoot, sub);
45539
- if (fs9.existsSync(s)) {
45540
- fs9.cpSync(s, path11.join(dst, sub), { recursive: true, force: true, dereference: true });
45571
+ const s = path13.join(args.deployKitBundleRoot, sub);
45572
+ if (fs10.existsSync(s)) {
45573
+ fs10.cpSync(s, path13.join(dst, sub), { recursive: true, force: true, dereference: true });
45541
45574
  }
45542
45575
  }
45543
- const secretsSrc = path11.join(args.deployKitBundleRoot, ".secrets");
45544
- if (fs9.existsSync(secretsSrc)) {
45545
- fs9.mkdirSync(path11.join(dst, ".secrets"), { recursive: true });
45546
- for (const f of fs9.readdirSync(secretsSrc)) {
45576
+ const secretsSrc = path13.join(args.deployKitBundleRoot, ".secrets");
45577
+ if (fs10.existsSync(secretsSrc)) {
45578
+ fs10.mkdirSync(path13.join(dst, ".secrets"), { recursive: true });
45579
+ for (const f of fs10.readdirSync(secretsSrc)) {
45547
45580
  if (!f.endsWith(".example")) continue;
45548
- fs9.copyFileSync(path11.join(secretsSrc, f), path11.join(dst, ".secrets", f));
45581
+ fs10.copyFileSync(path13.join(secretsSrc, f), path13.join(dst, ".secrets", f));
45549
45582
  }
45550
45583
  }
45551
45584
  args.logger.info("deploy-kit.refresh.done", { dst });
45552
45585
  }
45553
45586
 
45554
45587
  // src/share-md-viewer/load.ts
45555
- var import_node_fs9 = __toESM(require("fs"), 1);
45556
- var import_node_path8 = __toESM(require("path"), 1);
45588
+ var import_node_fs10 = __toESM(require("fs"), 1);
45589
+ var import_node_path10 = __toESM(require("path"), 1);
45557
45590
  var import_node_url2 = require("url");
45558
45591
 
45559
45592
  // src/share-md-viewer/asset-loader.ts
45560
- var import_node_fs8 = __toESM(require("fs"), 1);
45593
+ var import_node_fs9 = __toESM(require("fs"), 1);
45561
45594
  function htmlEscape(s) {
45562
45595
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
45563
45596
  }
@@ -45565,12 +45598,12 @@ function createViewerAssetLoader(opts) {
45565
45598
  let viewerTemplate;
45566
45599
  let errorTemplate;
45567
45600
  try {
45568
- viewerTemplate = import_node_fs8.default.readFileSync(opts.viewerHtmlPath, "utf8");
45601
+ viewerTemplate = import_node_fs9.default.readFileSync(opts.viewerHtmlPath, "utf8");
45569
45602
  } catch (err) {
45570
45603
  throw new Error(`viewer asset not found at ${opts.viewerHtmlPath}: ${err.message}`);
45571
45604
  }
45572
45605
  try {
45573
- errorTemplate = import_node_fs8.default.readFileSync(opts.errorHtmlPath, "utf8");
45606
+ errorTemplate = import_node_fs9.default.readFileSync(opts.errorHtmlPath, "utf8");
45574
45607
  } catch (err) {
45575
45608
  throw new Error(`viewer error asset not found at ${opts.errorHtmlPath}: ${err.message}`);
45576
45609
  }
@@ -45589,25 +45622,25 @@ var import_meta2 = {};
45589
45622
  function tryLoadViewerAssets(logger) {
45590
45623
  const candidates = [];
45591
45624
  try {
45592
- const here = import_node_path8.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
45625
+ const here = import_node_path10.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
45593
45626
  candidates.push(here);
45594
- candidates.push(import_node_path8.default.resolve(here, ".."));
45595
- candidates.push(import_node_path8.default.resolve(here, "..", "..", "dist"));
45627
+ candidates.push(import_node_path10.default.resolve(here, ".."));
45628
+ candidates.push(import_node_path10.default.resolve(here, "..", "..", "dist"));
45596
45629
  } catch {
45597
45630
  }
45598
45631
  if (process.argv[1]) {
45599
45632
  let real = process.argv[1];
45600
45633
  try {
45601
- real = import_node_fs9.default.realpathSync(process.argv[1]);
45634
+ real = import_node_fs10.default.realpathSync(process.argv[1]);
45602
45635
  } catch {
45603
45636
  }
45604
- candidates.push(import_node_path8.default.dirname(real));
45637
+ candidates.push(import_node_path10.default.dirname(real));
45605
45638
  }
45606
45639
  for (const root of candidates) {
45607
- const viewerHtmlPath = import_node_path8.default.join(root, "share-md-viewer.html");
45608
- const errorHtmlPath = import_node_path8.default.join(root, "share-md-viewer-error.html");
45640
+ const viewerHtmlPath = import_node_path10.default.join(root, "share-md-viewer.html");
45641
+ const errorHtmlPath = import_node_path10.default.join(root, "share-md-viewer-error.html");
45609
45642
  try {
45610
- if (import_node_fs9.default.statSync(viewerHtmlPath).isFile() && import_node_fs9.default.statSync(errorHtmlPath).isFile()) {
45643
+ if (import_node_fs10.default.statSync(viewerHtmlPath).isFile() && import_node_fs10.default.statSync(errorHtmlPath).isFile()) {
45611
45644
  logger?.info("share-md-viewer.assets-root.resolved", { root });
45612
45645
  return createViewerAssetLoader({ viewerHtmlPath, errorHtmlPath });
45613
45646
  }
@@ -45622,30 +45655,30 @@ function tryLoadViewerAssets(logger) {
45622
45655
  }
45623
45656
 
45624
45657
  // src/share-ui/load.ts
45625
- var import_node_fs11 = __toESM(require("fs"), 1);
45626
- var import_node_path10 = __toESM(require("path"), 1);
45658
+ var import_node_fs12 = __toESM(require("fs"), 1);
45659
+ var import_node_path12 = __toESM(require("path"), 1);
45627
45660
  var import_node_url3 = require("url");
45628
45661
 
45629
45662
  // src/share-ui/asset-loader.ts
45630
- var import_node_fs10 = __toESM(require("fs"), 1);
45631
- var import_node_path9 = __toESM(require("path"), 1);
45663
+ var import_node_fs11 = __toESM(require("fs"), 1);
45664
+ var import_node_path11 = __toESM(require("path"), 1);
45632
45665
  function createShareUiAssetLoader(opts) {
45633
45666
  let indexHtml;
45634
45667
  try {
45635
- indexHtml = import_node_fs10.default.readFileSync(opts.indexHtmlPath, "utf8");
45668
+ indexHtml = import_node_fs11.default.readFileSync(opts.indexHtmlPath, "utf8");
45636
45669
  } catch (err) {
45637
45670
  throw new Error(`share-ui index.html not found at ${opts.indexHtmlPath}: ${err.message}`);
45638
45671
  }
45639
- const assetsDir = import_node_path9.default.resolve(opts.assetsDir);
45672
+ const assetsDir = import_node_path11.default.resolve(opts.assetsDir);
45640
45673
  return {
45641
45674
  renderIndexHtml() {
45642
45675
  return indexHtml;
45643
45676
  },
45644
45677
  resolveAssetPath(rel) {
45645
- const resolved = import_node_path9.default.resolve(assetsDir, rel);
45646
- if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path9.default.sep)) return null;
45678
+ const resolved = import_node_path11.default.resolve(assetsDir, rel);
45679
+ if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path11.default.sep)) return null;
45647
45680
  try {
45648
- if (import_node_fs10.default.statSync(resolved).isFile()) return resolved;
45681
+ if (import_node_fs11.default.statSync(resolved).isFile()) return resolved;
45649
45682
  } catch {
45650
45683
  }
45651
45684
  return null;
@@ -45659,28 +45692,28 @@ function bundleDirFromArgv(argv1) {
45659
45692
  if (!argv1) return null;
45660
45693
  let real = argv1;
45661
45694
  try {
45662
- real = import_node_fs11.default.realpathSync(argv1);
45695
+ real = import_node_fs12.default.realpathSync(argv1);
45663
45696
  } catch {
45664
45697
  }
45665
- return import_node_path10.default.dirname(real);
45698
+ return import_node_path12.default.dirname(real);
45666
45699
  }
45667
45700
  function tryLoadShareUi(logger) {
45668
45701
  const candidates = [];
45669
45702
  try {
45670
- const here = import_node_path10.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url));
45703
+ const here = import_node_path12.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url));
45671
45704
  candidates.push(here);
45672
- candidates.push(import_node_path10.default.resolve(here, ".."));
45673
- candidates.push(import_node_path10.default.resolve(here, "..", "..", "dist"));
45705
+ candidates.push(import_node_path12.default.resolve(here, ".."));
45706
+ candidates.push(import_node_path12.default.resolve(here, "..", "..", "dist"));
45674
45707
  } catch {
45675
45708
  }
45676
45709
  const argvDir = bundleDirFromArgv(process.argv[1]);
45677
45710
  if (argvDir) candidates.push(argvDir);
45678
45711
  for (const root of candidates) {
45679
- const shareUiDir = import_node_path10.default.join(root, "share-ui");
45680
- const indexHtmlPath = import_node_path10.default.join(shareUiDir, "guest.html");
45681
- const assetsDir = import_node_path10.default.join(shareUiDir, "assets");
45712
+ const shareUiDir = import_node_path12.default.join(root, "share-ui");
45713
+ const indexHtmlPath = import_node_path12.default.join(shareUiDir, "guest.html");
45714
+ const assetsDir = import_node_path12.default.join(shareUiDir, "assets");
45682
45715
  try {
45683
- if (import_node_fs11.default.statSync(indexHtmlPath).isFile() && import_node_fs11.default.statSync(assetsDir).isDirectory()) {
45716
+ if (import_node_fs12.default.statSync(indexHtmlPath).isFile() && import_node_fs12.default.statSync(assetsDir).isDirectory()) {
45684
45717
  logger?.info("share-ui.assets-root.resolved", { root: shareUiDir });
45685
45718
  return createShareUiAssetLoader({ indexHtmlPath, assetsDir });
45686
45719
  }
@@ -45762,20 +45795,20 @@ function buildVisitorLogin(deps) {
45762
45795
  }
45763
45796
 
45764
45797
  // src/visitor/visitor-store.ts
45765
- var import_node_fs12 = __toESM(require("fs"), 1);
45766
- var import_node_path11 = __toESM(require("path"), 1);
45798
+ var import_node_fs13 = __toESM(require("fs"), 1);
45799
+ var import_node_path13 = __toESM(require("path"), 1);
45767
45800
  function createVisitorStore(opts) {
45768
- const file = import_node_path11.default.join(opts.dir, "visitors.json");
45801
+ const file = import_node_path13.default.join(opts.dir, "visitors.json");
45769
45802
  const read = () => {
45770
45803
  try {
45771
- return JSON.parse(import_node_fs12.default.readFileSync(file, "utf8"));
45804
+ return JSON.parse(import_node_fs13.default.readFileSync(file, "utf8"));
45772
45805
  } catch {
45773
45806
  return [];
45774
45807
  }
45775
45808
  };
45776
45809
  const write = (rows) => {
45777
- import_node_fs12.default.mkdirSync(opts.dir, { recursive: true });
45778
- import_node_fs12.default.writeFileSync(file, JSON.stringify(rows, null, 2));
45810
+ import_node_fs13.default.mkdirSync(opts.dir, { recursive: true });
45811
+ import_node_fs13.default.writeFileSync(file, JSON.stringify(rows, null, 2));
45779
45812
  };
45780
45813
  return {
45781
45814
  upsert(r) {
@@ -46057,8 +46090,8 @@ function turnStartInput(text) {
46057
46090
  const items = [];
46058
46091
  let leftover = text;
46059
46092
  for (const m2 of text.matchAll(SKILL_RE)) {
46060
- const [marker, name, path67] = m2;
46061
- items.push({ type: "skill", name, path: path67 });
46093
+ const [marker, name, path68] = m2;
46094
+ items.push({ type: "skill", name, path: path68 });
46062
46095
  leftover = leftover.replace(marker, "");
46063
46096
  }
46064
46097
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -46291,8 +46324,8 @@ var CodexAdapter = class {
46291
46324
 
46292
46325
  // src/tools/claude-tui.ts
46293
46326
  var import_node_fs16 = __toESM(require("fs"), 1);
46294
- var import_node_os6 = __toESM(require("os"), 1);
46295
- var import_node_path13 = __toESM(require("path"), 1);
46327
+ var import_node_os7 = __toESM(require("os"), 1);
46328
+ var import_node_path14 = __toESM(require("path"), 1);
46296
46329
  var import_headless = __toESM(require_xterm_headless(), 1);
46297
46330
 
46298
46331
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -47428,8 +47461,8 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
47428
47461
  }
47429
47462
  function jsonlExistsForCtx(ctx) {
47430
47463
  if (!ctx.toolSessionId) return false;
47431
- const home = import_node_os6.default.homedir();
47432
- const file = import_node_path13.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
47464
+ const home = import_node_os7.default.homedir();
47465
+ const file = import_node_path14.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
47433
47466
  try {
47434
47467
  return import_node_fs16.default.statSync(file).isFile();
47435
47468
  } catch {
@@ -47501,9 +47534,9 @@ var PersonaDispatchManager = class {
47501
47534
 
47502
47535
  // src/dispatch/mcp-config.ts
47503
47536
  var import_node_fs17 = __toESM(require("fs"), 1);
47504
- var import_node_path14 = __toESM(require("path"), 1);
47537
+ var import_node_path15 = __toESM(require("path"), 1);
47505
47538
  function dispatchMcpConfigPath(dataDir) {
47506
- return import_node_path14.default.join(dataDir, "dispatch.mcp.json");
47539
+ return import_node_path15.default.join(dataDir, "dispatch.mcp.json");
47507
47540
  }
47508
47541
  function writeDispatchMcpConfig(args) {
47509
47542
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -47525,9 +47558,9 @@ function writeDispatchMcpConfig(args) {
47525
47558
 
47526
47559
  // src/ticket/mcp-config.ts
47527
47560
  var import_node_fs18 = __toESM(require("fs"), 1);
47528
- var import_node_path15 = __toESM(require("path"), 1);
47561
+ var import_node_path16 = __toESM(require("path"), 1);
47529
47562
  function ticketMcpConfigPath(dataDir) {
47530
- return import_node_path15.default.join(dataDir, "ticket.mcp.json");
47563
+ return import_node_path16.default.join(dataDir, "ticket.mcp.json");
47531
47564
  }
47532
47565
  function writeTicketMcpConfig(args) {
47533
47566
  const cfgPath = ticketMcpConfigPath(args.dataDir);
@@ -47555,9 +47588,9 @@ function writeTicketMcpConfig(args) {
47555
47588
 
47556
47589
  // src/shift/mcp-config.ts
47557
47590
  var import_node_fs19 = __toESM(require("fs"), 1);
47558
- var import_node_path16 = __toESM(require("path"), 1);
47591
+ var import_node_path17 = __toESM(require("path"), 1);
47559
47592
  function shiftMcpConfigPath(dataDir) {
47560
- return import_node_path16.default.join(dataDir, "shift.mcp.json");
47593
+ return import_node_path17.default.join(dataDir, "shift.mcp.json");
47561
47594
  }
47562
47595
  async function writeShiftMcpConfig(args) {
47563
47596
  const cfgPath = shiftMcpConfigPath(args.dataDir);
@@ -47579,19 +47612,20 @@ async function writeShiftMcpConfig(args) {
47579
47612
 
47580
47613
  // src/inbox/mcp-config.ts
47581
47614
  var import_node_fs20 = __toESM(require("fs"), 1);
47582
- var import_node_path17 = __toESM(require("path"), 1);
47615
+ var import_node_path18 = __toESM(require("path"), 1);
47583
47616
  function inboxMcpConfigPath(dataDir) {
47584
- return import_node_path17.default.join(dataDir, "inbox.mcp.json");
47617
+ return import_node_path18.default.join(dataDir, "inbox.mcp.json");
47585
47618
  }
47586
47619
  async function writeInboxMcpConfig(args) {
47587
47620
  const cfgPath = inboxMcpConfigPath(args.dataDir);
47588
47621
  const content = {
47589
- _comment: "daemon \u542F\u52A8\u65F6\u81EA\u52A8\u751F\u6210\uFF1Bcc spawn \u901A\u8FC7 --mcp-config \u6CE8\u5165\u3002inbox/mcp-server.cjs \u662F daemon \u81EA\u5E26\u7684 stdio MCP server\uFF0C\u66B4\u9732 sendDm tool\uFF08persona \u53D7\u63A7\u53D1 P2P IM DM\uFF09\u3002",
47622
+ _comment: "daemon \u542F\u52A8\u65F6\u81EA\u52A8\u751F\u6210\uFF1Bcc spawn \u901A\u8FC7 --mcp-config \u6CE8\u5165\u3002inbox/mcp-server.cjs \u662F daemon \u81EA\u5E26\u7684 stdio MCP server\uFF0C\u66B4\u9732 sendDm tool\uFF08persona \u53D7\u63A7\u53D1 P2P IM DM\uFF09\u3002env.CLAWD_INBOX_LOG \u6307 server \u5199\u65E5\u5FD7\u7684 append \u6587\u4EF6\u8DEF\u5F84\u3002",
47590
47623
  mcpServers: {
47591
47624
  "clawd-inbox": {
47592
47625
  type: "stdio",
47593
47626
  command: "node",
47594
- args: [args.serverScriptPath]
47627
+ args: [args.serverScriptPath],
47628
+ ...args.logPath ? { env: { CLAWD_INBOX_LOG: args.logPath } } : {}
47595
47629
  }
47596
47630
  }
47597
47631
  };
@@ -47602,7 +47636,7 @@ async function writeInboxMcpConfig(args) {
47602
47636
 
47603
47637
  // src/shift/store.ts
47604
47638
  var import_promises = __toESM(require("fs/promises"), 1);
47605
- var import_node_path18 = __toESM(require("path"), 1);
47639
+ var import_node_path19 = __toESM(require("path"), 1);
47606
47640
  var import_node_crypto5 = require("crypto");
47607
47641
 
47608
47642
  // src/shift/constants.ts
@@ -47671,7 +47705,7 @@ function createShiftStore(deps) {
47671
47705
  flushTimer = null;
47672
47706
  }
47673
47707
  const content = { version: 1, shifts };
47674
- await import_promises.default.mkdir(import_node_path18.default.dirname(deps.filePath), { recursive: true });
47708
+ await import_promises.default.mkdir(import_node_path19.default.dirname(deps.filePath), { recursive: true });
47675
47709
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
47676
47710
  await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
47677
47711
  await import_promises.default.rename(tmp, deps.filePath);
@@ -48475,13 +48509,13 @@ function mapSkillsListResponse(res) {
48475
48509
  const r = s ?? {};
48476
48510
  const name = str3(r.name);
48477
48511
  if (!name) continue;
48478
- const path67 = str3(r.path);
48512
+ const path68 = str3(r.path);
48479
48513
  const description = str3(r.description);
48480
48514
  const isPlugin = name.includes(":");
48481
48515
  out.push({
48482
48516
  name,
48483
48517
  source: isPlugin ? "plugin" : "project",
48484
- ...path67 ? { path: path67 } : {},
48518
+ ...path68 ? { path: path68 } : {},
48485
48519
  ...description ? { description } : {},
48486
48520
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
48487
48521
  });
@@ -48521,15 +48555,15 @@ async function listCodexSkills(cwd, deps = {}) {
48521
48555
 
48522
48556
  // src/workspace/browser.ts
48523
48557
  var import_node_fs21 = __toESM(require("fs"), 1);
48524
- var import_node_os7 = __toESM(require("os"), 1);
48525
- var import_node_path19 = __toESM(require("path"), 1);
48558
+ var import_node_os8 = __toESM(require("os"), 1);
48559
+ var import_node_path20 = __toESM(require("path"), 1);
48526
48560
  init_protocol();
48527
48561
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
48528
48562
  function resolveInsideCwd(cwd, subpath) {
48529
- const absCwd = import_node_path19.default.resolve(cwd);
48530
- const joined = import_node_path19.default.resolve(absCwd, subpath ?? ".");
48531
- const rel = import_node_path19.default.relative(absCwd, joined);
48532
- if (rel.startsWith("..") || import_node_path19.default.isAbsolute(rel)) {
48563
+ const absCwd = import_node_path20.default.resolve(cwd);
48564
+ const joined = import_node_path20.default.resolve(absCwd, subpath ?? ".");
48565
+ const rel = import_node_path20.default.relative(absCwd, joined);
48566
+ if (rel.startsWith("..") || import_node_path20.default.isAbsolute(rel)) {
48533
48567
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
48534
48568
  }
48535
48569
  return joined;
@@ -48547,7 +48581,7 @@ function ensureCwd(cwd) {
48547
48581
  }
48548
48582
  var WorkspaceBrowser = class {
48549
48583
  list(args) {
48550
- const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os7.default.homedir();
48584
+ const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
48551
48585
  ensureCwd(cwd);
48552
48586
  const full = resolveInsideCwd(cwd, args.path);
48553
48587
  const dirents = import_node_fs21.default.readdirSync(full, { withFileTypes: true });
@@ -48560,7 +48594,7 @@ var WorkspaceBrowser = class {
48560
48594
  mtime: ""
48561
48595
  };
48562
48596
  try {
48563
- const st = import_node_fs21.default.statSync(import_node_path19.default.join(full, d.name));
48597
+ const st = import_node_fs21.default.statSync(import_node_path20.default.join(full, d.name));
48564
48598
  entry.mtime = new Date(st.mtimeMs).toISOString();
48565
48599
  if (d.isFile()) entry.size = st.size;
48566
48600
  } catch {
@@ -48606,8 +48640,8 @@ var WorkspaceBrowser = class {
48606
48640
 
48607
48641
  // src/skills/agents-scanner.ts
48608
48642
  var import_node_fs22 = __toESM(require("fs"), 1);
48609
- var import_node_os8 = __toESM(require("os"), 1);
48610
- var import_node_path20 = __toESM(require("path"), 1);
48643
+ var import_node_os9 = __toESM(require("os"), 1);
48644
+ var import_node_path21 = __toESM(require("path"), 1);
48611
48645
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
48612
48646
  function isDirLikeSync2(p2) {
48613
48647
  try {
@@ -48645,10 +48679,10 @@ function scanAgentsDir(dir, source, seen, out) {
48645
48679
  }
48646
48680
  for (const ent of entries) {
48647
48681
  if (!ent.name.endsWith(".md")) continue;
48648
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path20.default.join(dir, ent.name)))) {
48682
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path21.default.join(dir, ent.name)))) {
48649
48683
  continue;
48650
48684
  }
48651
- const filePath = import_node_path20.default.join(dir, ent.name);
48685
+ const filePath = import_node_path21.default.join(dir, ent.name);
48652
48686
  const baseName = ent.name.replace(/\.md$/, "");
48653
48687
  if (seen.has(baseName)) continue;
48654
48688
  seen.add(baseName);
@@ -48671,7 +48705,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
48671
48705
  return;
48672
48706
  }
48673
48707
  for (const ent of entries) {
48674
- const childPath = import_node_path20.default.join(dir, ent.name);
48708
+ const childPath = import_node_path21.default.join(dir, ent.name);
48675
48709
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
48676
48710
  walk2(childPath, [...namespaces, ent.name]);
48677
48711
  continue;
@@ -48696,9 +48730,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
48696
48730
  walk2(root, []);
48697
48731
  }
48698
48732
  function readInstalledPlugins2(home) {
48699
- const pluginsDir = import_node_path20.default.join(home, ".claude", "plugins");
48700
- const v2 = import_node_path20.default.join(pluginsDir, "installed_plugins_v2.json");
48701
- const v1 = import_node_path20.default.join(pluginsDir, "installed_plugins.json");
48733
+ const pluginsDir = import_node_path21.default.join(home, ".claude", "plugins");
48734
+ const v2 = import_node_path21.default.join(pluginsDir, "installed_plugins_v2.json");
48735
+ const v1 = import_node_path21.default.join(pluginsDir, "installed_plugins.json");
48702
48736
  let raw = null;
48703
48737
  for (const candidate of [v2, v1]) {
48704
48738
  try {
@@ -48727,19 +48761,19 @@ function readInstalledPlugins2(home) {
48727
48761
  return out;
48728
48762
  }
48729
48763
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
48730
- let cur = import_node_path20.default.resolve(startCwd);
48731
- const fsRoot = import_node_path20.default.parse(cur).root;
48764
+ let cur = import_node_path21.default.resolve(startCwd);
48765
+ const fsRoot = import_node_path21.default.parse(cur).root;
48732
48766
  while (true) {
48733
- scanAgentsDir(import_node_path20.default.join(cur, ".claude", "agents"), "project", seen, out);
48767
+ scanAgentsDir(import_node_path21.default.join(cur, ".claude", "agents"), "project", seen, out);
48734
48768
  let hasGit = false;
48735
48769
  try {
48736
- hasGit = import_node_fs22.default.existsSync(import_node_path20.default.join(cur, ".git"));
48770
+ hasGit = import_node_fs22.default.existsSync(import_node_path21.default.join(cur, ".git"));
48737
48771
  } catch {
48738
48772
  }
48739
48773
  if (hasGit) return;
48740
48774
  if (cur === home) return;
48741
48775
  if (cur === fsRoot) return;
48742
- const parent = import_node_path20.default.dirname(cur);
48776
+ const parent = import_node_path21.default.dirname(cur);
48743
48777
  if (parent === cur) return;
48744
48778
  cur = parent;
48745
48779
  }
@@ -48749,7 +48783,7 @@ var AgentsScanner = class {
48749
48783
  extraPluginRoots;
48750
48784
  policyDir;
48751
48785
  constructor(opts = {}) {
48752
- this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os8.default.homedir();
48786
+ this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os9.default.homedir();
48753
48787
  this.extraPluginRoots = opts.extraPluginRoots ?? [];
48754
48788
  if (opts.policyDir !== void 0) {
48755
48789
  this.policyDir = opts.policyDir;
@@ -48774,7 +48808,7 @@ var AgentsScanner = class {
48774
48808
  }
48775
48809
  const fsBlock = [];
48776
48810
  scanAgentsDir(
48777
- import_node_path20.default.join(this.home, ".claude", "agents"),
48811
+ import_node_path21.default.join(this.home, ".claude", "agents"),
48778
48812
  "global",
48779
48813
  seen,
48780
48814
  fsBlock
@@ -48788,7 +48822,7 @@ var AgentsScanner = class {
48788
48822
  ...this.extraPluginRoots
48789
48823
  ];
48790
48824
  for (const { name, root } of plugins) {
48791
- const agentsRoot = import_node_path20.default.join(root, "agents");
48825
+ const agentsRoot = import_node_path21.default.join(root, "agents");
48792
48826
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
48793
48827
  }
48794
48828
  return [...builtinBlock, ...fsBlock];
@@ -48797,27 +48831,27 @@ var AgentsScanner = class {
48797
48831
 
48798
48832
  // src/observer/session-observer.ts
48799
48833
  var import_node_fs24 = __toESM(require("fs"), 1);
48800
- var import_node_os10 = __toESM(require("os"), 1);
48801
- var import_node_path22 = __toESM(require("path"), 1);
48834
+ var import_node_os11 = __toESM(require("os"), 1);
48835
+ var import_node_path23 = __toESM(require("path"), 1);
48802
48836
  init_claude_history();
48803
48837
 
48804
48838
  // src/observer/subagent-meta-observer.ts
48805
48839
  var import_node_fs23 = __toESM(require("fs"), 1);
48806
- var import_node_os9 = __toESM(require("os"), 1);
48807
- var import_node_path21 = __toESM(require("path"), 1);
48840
+ var import_node_os10 = __toESM(require("os"), 1);
48841
+ var import_node_path22 = __toESM(require("path"), 1);
48808
48842
  init_claude_history();
48809
48843
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
48810
48844
  var SubagentMetaObserver = class {
48811
48845
  constructor(opts) {
48812
48846
  this.opts = opts;
48813
- this.home = opts.home ?? import_node_os9.default.homedir();
48847
+ this.home = opts.home ?? import_node_os10.default.homedir();
48814
48848
  }
48815
48849
  opts;
48816
48850
  home;
48817
48851
  watches = /* @__PURE__ */ new Map();
48818
48852
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
48819
48853
  resolveSubagentDir(cwd, toolSessionId) {
48820
- return import_node_path21.default.join(
48854
+ return import_node_path22.default.join(
48821
48855
  this.home,
48822
48856
  ".claude",
48823
48857
  "projects",
@@ -48873,7 +48907,7 @@ var SubagentMetaObserver = class {
48873
48907
  if (!m2) return;
48874
48908
  const agentId = m2[1];
48875
48909
  if (w2.emitted.has(agentId)) return;
48876
- const file = import_node_path21.default.join(w2.dirPath, name);
48910
+ const file = import_node_path22.default.join(w2.dirPath, name);
48877
48911
  let raw;
48878
48912
  try {
48879
48913
  raw = import_node_fs23.default.readFileSync(file, "utf8");
@@ -48921,7 +48955,7 @@ var SubagentMetaObserver = class {
48921
48955
  var SessionObserver = class {
48922
48956
  constructor(opts) {
48923
48957
  this.opts = opts;
48924
- this.home = opts.home ?? import_node_os10.default.homedir();
48958
+ this.home = opts.home ?? import_node_os11.default.homedir();
48925
48959
  this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
48926
48960
  }
48927
48961
  opts;
@@ -48933,7 +48967,7 @@ var SessionObserver = class {
48933
48967
  metaObserver;
48934
48968
  resolveJsonlPath(cwd, toolSessionId, override) {
48935
48969
  if (override) return override;
48936
- return import_node_path22.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
48970
+ return import_node_path23.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
48937
48971
  }
48938
48972
  start(args) {
48939
48973
  this.stop(args.sessionId);
@@ -48954,10 +48988,10 @@ var SessionObserver = class {
48954
48988
  prevIsRejectSentinel: false
48955
48989
  };
48956
48990
  try {
48957
- import_node_fs24.default.mkdirSync(import_node_path22.default.dirname(filePath), { recursive: true });
48991
+ import_node_fs24.default.mkdirSync(import_node_path23.default.dirname(filePath), { recursive: true });
48958
48992
  } catch {
48959
48993
  }
48960
- w2.watcher = import_node_fs24.default.watch(import_node_path22.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
48994
+ w2.watcher = import_node_fs24.default.watch(import_node_path23.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
48961
48995
  if (!changedName || !filePath.endsWith(changedName)) return;
48962
48996
  this.poll(w2);
48963
48997
  });
@@ -49839,7 +49873,7 @@ async function authenticate(token, deps) {
49839
49873
 
49840
49874
  // src/permission/capability-store.ts
49841
49875
  var fs28 = __toESM(require("fs"), 1);
49842
- var path27 = __toESM(require("path"), 1);
49876
+ var path28 = __toESM(require("path"), 1);
49843
49877
  var CAPABILITIES_FILE_NAME = "capabilities.json";
49844
49878
  var FILE_VERSION = 1;
49845
49879
  var CapabilityStore = class {
@@ -49869,7 +49903,7 @@ var CapabilityStore = class {
49869
49903
  this.flush();
49870
49904
  }
49871
49905
  filePath() {
49872
- return path27.join(this.dataDir, CAPABILITIES_FILE_NAME);
49906
+ return path28.join(this.dataDir, CAPABILITIES_FILE_NAME);
49873
49907
  }
49874
49908
  readFromDisk() {
49875
49909
  const file = this.filePath();
@@ -50016,7 +50050,7 @@ function cleanupGuestSessionsForCapability(cap, factory) {
50016
50050
 
50017
50051
  // src/inbox/inbox-store.ts
50018
50052
  var fs30 = __toESM(require("fs"), 1);
50019
- var path28 = __toESM(require("path"), 1);
50053
+ var path29 = __toESM(require("path"), 1);
50020
50054
  var INBOX_SUBDIR = "inbox";
50021
50055
  var InboxStore = class {
50022
50056
  constructor(dataDir) {
@@ -50114,10 +50148,10 @@ var InboxStore = class {
50114
50148
  }
50115
50149
  }
50116
50150
  dirPath() {
50117
- return path28.join(this.dataDir, INBOX_SUBDIR);
50151
+ return path29.join(this.dataDir, INBOX_SUBDIR);
50118
50152
  }
50119
50153
  filePath(peerDeviceId) {
50120
- return path28.join(this.dirPath(), `${peerDeviceId}.jsonl`);
50154
+ return path29.join(this.dirPath(), `${peerDeviceId}.jsonl`);
50121
50155
  }
50122
50156
  };
50123
50157
  function parseAllLines(raw) {
@@ -50206,7 +50240,7 @@ var InboxManager = class {
50206
50240
 
50207
50241
  // src/state/contact-store.ts
50208
50242
  var fs31 = __toESM(require("fs"), 1);
50209
- var path29 = __toESM(require("path"), 1);
50243
+ var path30 = __toESM(require("path"), 1);
50210
50244
  var FILE_NAME = "contacts.json";
50211
50245
  var ContactStore = class {
50212
50246
  constructor(dataDir) {
@@ -50216,7 +50250,7 @@ var ContactStore = class {
50216
50250
  contacts = /* @__PURE__ */ new Map();
50217
50251
  load() {
50218
50252
  this.contacts.clear();
50219
- const file = path29.join(this.dataDir, FILE_NAME);
50253
+ const file = path30.join(this.dataDir, FILE_NAME);
50220
50254
  let raw;
50221
50255
  try {
50222
50256
  raw = fs31.readFileSync(file, "utf8");
@@ -50262,7 +50296,7 @@ var ContactStore = class {
50262
50296
  return existed;
50263
50297
  }
50264
50298
  flush() {
50265
- const file = path29.join(this.dataDir, FILE_NAME);
50299
+ const file = path30.join(this.dataDir, FILE_NAME);
50266
50300
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
50267
50301
  const content = JSON.stringify(
50268
50302
  { contacts: Array.from(this.contacts.values()) },
@@ -50426,52 +50460,52 @@ async function autoReverseContact(args) {
50426
50460
 
50427
50461
  // src/migrations/2026-05-20-flatten-sessions.ts
50428
50462
  var fs32 = __toESM(require("fs"), 1);
50429
- var path30 = __toESM(require("path"), 1);
50463
+ var path31 = __toESM(require("path"), 1);
50430
50464
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
50431
50465
  function migrateFlattenSessions(opts) {
50432
50466
  const dataDir = opts.dataDir;
50433
50467
  const now = opts.now ?? Date.now;
50434
- const sessionsDir = path30.join(dataDir, "sessions");
50435
- const flagPath = path30.join(sessionsDir, MIGRATION_FLAG_NAME);
50468
+ const sessionsDir = path31.join(dataDir, "sessions");
50469
+ const flagPath = path31.join(sessionsDir, MIGRATION_FLAG_NAME);
50436
50470
  if (existsSync3(flagPath)) {
50437
50471
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
50438
50472
  }
50439
50473
  let movedBare = 0;
50440
50474
  let movedVmOwner = 0;
50441
50475
  let archivedListener = 0;
50442
- const defaultDir = path30.join(sessionsDir, "default");
50476
+ const defaultDir = path31.join(sessionsDir, "default");
50443
50477
  if (existsSync3(defaultDir)) {
50444
50478
  for (const entry of readdirSafe(defaultDir)) {
50445
50479
  if (!entry.endsWith(".json")) continue;
50446
- const src = path30.join(defaultDir, entry);
50447
- const dst = path30.join(sessionsDir, entry);
50480
+ const src = path31.join(defaultDir, entry);
50481
+ const dst = path31.join(sessionsDir, entry);
50448
50482
  fs32.renameSync(src, dst);
50449
50483
  movedBare += 1;
50450
50484
  }
50451
50485
  rmdirIfEmpty(defaultDir);
50452
50486
  }
50453
50487
  for (const pid of readdirSafe(sessionsDir)) {
50454
- const personaDir = path30.join(sessionsDir, pid);
50488
+ const personaDir = path31.join(sessionsDir, pid);
50455
50489
  if (!isDir(personaDir)) continue;
50456
50490
  if (pid === "default") continue;
50457
- const ownerSrc = path30.join(personaDir, "owner");
50491
+ const ownerSrc = path31.join(personaDir, "owner");
50458
50492
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
50459
- const ownerDst = path30.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
50493
+ const ownerDst = path31.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
50460
50494
  fs32.mkdirSync(ownerDst, { recursive: true });
50461
50495
  for (const file of readdirSafe(ownerSrc)) {
50462
50496
  if (!file.endsWith(".json")) continue;
50463
- fs32.renameSync(path30.join(ownerSrc, file), path30.join(ownerDst, file));
50497
+ fs32.renameSync(path31.join(ownerSrc, file), path31.join(ownerDst, file));
50464
50498
  movedVmOwner += 1;
50465
50499
  }
50466
50500
  rmdirIfEmpty(ownerSrc);
50467
50501
  }
50468
- const listenerSrc = path30.join(personaDir, "listener");
50502
+ const listenerSrc = path31.join(personaDir, "listener");
50469
50503
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
50470
- const archiveDst = path30.join(dataDir, ".legacy", `listener-${pid}`);
50504
+ const archiveDst = path31.join(dataDir, ".legacy", `listener-${pid}`);
50471
50505
  fs32.mkdirSync(archiveDst, { recursive: true });
50472
50506
  for (const file of readdirSafe(listenerSrc)) {
50473
50507
  if (!file.endsWith(".json")) continue;
50474
- fs32.renameSync(path30.join(listenerSrc, file), path30.join(archiveDst, file));
50508
+ fs32.renameSync(path31.join(listenerSrc, file), path31.join(archiveDst, file));
50475
50509
  archivedListener += 1;
50476
50510
  }
50477
50511
  rmdirIfEmpty(listenerSrc);
@@ -50519,10 +50553,10 @@ function rmdirIfEmpty(p2) {
50519
50553
 
50520
50554
  // src/transport/http-router.ts
50521
50555
  var import_node_fs26 = __toESM(require("fs"), 1);
50522
- var import_node_path26 = __toESM(require("path"), 1);
50556
+ var import_node_path27 = __toESM(require("path"), 1);
50523
50557
 
50524
50558
  // src/attachment/mime.ts
50525
- var import_node_path23 = __toESM(require("path"), 1);
50559
+ var import_node_path24 = __toESM(require("path"), 1);
50526
50560
  var TEXT_PLAIN = "text/plain; charset=utf-8";
50527
50561
  var EXT_TO_NATIVE_MIME = {
50528
50562
  // 图片
@@ -50629,7 +50663,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
50629
50663
  ".mk"
50630
50664
  ]);
50631
50665
  function lookupMime(filePathOrName) {
50632
- const ext = import_node_path23.default.extname(filePathOrName).toLowerCase();
50666
+ const ext = import_node_path24.default.extname(filePathOrName).toLowerCase();
50633
50667
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
50634
50668
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
50635
50669
  return "application/octet-stream";
@@ -50699,7 +50733,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
50699
50733
 
50700
50734
  // src/attachment/upload.ts
50701
50735
  var import_node_fs25 = __toESM(require("fs"), 1);
50702
- var import_node_path24 = __toESM(require("path"), 1);
50736
+ var import_node_path25 = __toESM(require("path"), 1);
50703
50737
  var import_node_crypto7 = __toESM(require("crypto"), 1);
50704
50738
  var import_promises2 = require("stream/promises");
50705
50739
  var UploadError = class extends Error {
@@ -50711,14 +50745,14 @@ var UploadError = class extends Error {
50711
50745
  code;
50712
50746
  };
50713
50747
  function assertValidFileName(fileName) {
50714
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path24.default.basename(fileName)) {
50748
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path25.default.basename(fileName)) {
50715
50749
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
50716
50750
  }
50717
50751
  }
50718
50752
  var HASH_PREFIX_LEN = 16;
50719
50753
  async function writeUploadedAttachment(args) {
50720
50754
  assertValidFileName(args.fileName);
50721
- const attachmentsRoot = import_node_path24.default.join(args.sessionDir, ".attachments");
50755
+ const attachmentsRoot = import_node_path25.default.join(args.sessionDir, ".attachments");
50722
50756
  try {
50723
50757
  import_node_fs25.default.mkdirSync(attachmentsRoot, { recursive: true });
50724
50758
  } catch (err) {
@@ -50726,7 +50760,7 @@ async function writeUploadedAttachment(args) {
50726
50760
  }
50727
50761
  const hasher = import_node_crypto7.default.createHash("sha256");
50728
50762
  let actualSize = 0;
50729
- const tmpPath = import_node_path24.default.join(
50763
+ const tmpPath = import_node_path25.default.join(
50730
50764
  attachmentsRoot,
50731
50765
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto7.default.randomBytes(4).toString("hex")}`
50732
50766
  );
@@ -50761,7 +50795,7 @@ async function writeUploadedAttachment(args) {
50761
50795
  );
50762
50796
  }
50763
50797
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
50764
- const hashDir = import_node_path24.default.join(attachmentsRoot, attachmentId);
50798
+ const hashDir = import_node_path25.default.join(attachmentsRoot, attachmentId);
50765
50799
  let finalFileName;
50766
50800
  let hashDirExists = false;
50767
50801
  try {
@@ -50779,7 +50813,7 @@ async function writeUploadedAttachment(args) {
50779
50813
  try {
50780
50814
  import_node_fs25.default.mkdirSync(hashDir, { recursive: true });
50781
50815
  finalFileName = args.fileName;
50782
- import_node_fs25.default.renameSync(tmpPath, import_node_path24.default.join(hashDir, finalFileName));
50816
+ import_node_fs25.default.renameSync(tmpPath, import_node_path25.default.join(hashDir, finalFileName));
50783
50817
  } catch (err) {
50784
50818
  try {
50785
50819
  import_node_fs25.default.unlinkSync(tmpPath);
@@ -50788,8 +50822,8 @@ async function writeUploadedAttachment(args) {
50788
50822
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
50789
50823
  }
50790
50824
  }
50791
- const absPath = import_node_path24.default.join(hashDir, finalFileName);
50792
- const relPath = import_node_path24.default.relative(args.sessionDir, absPath);
50825
+ const absPath = import_node_path25.default.join(hashDir, finalFileName);
50826
+ const relPath = import_node_path25.default.relative(args.sessionDir, absPath);
50793
50827
  args.groupFileStore.upsert(args.scope, args.sessionId, {
50794
50828
  relPath: absPath,
50795
50829
  // 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
@@ -50803,8 +50837,8 @@ async function writeUploadedAttachment(args) {
50803
50837
 
50804
50838
  // src/extension/import.ts
50805
50839
  var import_promises3 = __toESM(require("fs/promises"), 1);
50806
- var import_node_path25 = __toESM(require("path"), 1);
50807
- var import_node_os11 = __toESM(require("os"), 1);
50840
+ var import_node_path26 = __toESM(require("path"), 1);
50841
+ var import_node_os12 = __toESM(require("os"), 1);
50808
50842
  var import_jszip = __toESM(require_lib3(), 1);
50809
50843
  var ImportError = class extends Error {
50810
50844
  constructor(code, message) {
@@ -50821,7 +50855,7 @@ async function importZip(buf, root) {
50821
50855
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
50822
50856
  }
50823
50857
  for (const name of Object.keys(zip.files)) {
50824
- if (name.includes("..") || name.startsWith("/") || import_node_path25.default.isAbsolute(name)) {
50858
+ if (name.includes("..") || name.startsWith("/") || import_node_path26.default.isAbsolute(name)) {
50825
50859
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
50826
50860
  }
50827
50861
  }
@@ -50854,7 +50888,7 @@ async function importZip(buf, root) {
50854
50888
  );
50855
50889
  }
50856
50890
  }
50857
- const destDir = import_node_path25.default.join(root, manifest.id);
50891
+ const destDir = import_node_path26.default.join(root, manifest.id);
50858
50892
  let destExists = false;
50859
50893
  try {
50860
50894
  await import_promises3.default.access(destDir);
@@ -50864,15 +50898,15 @@ async function importZip(buf, root) {
50864
50898
  if (destExists) {
50865
50899
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
50866
50900
  }
50867
- const stage = await import_promises3.default.mkdtemp(import_node_path25.default.join(import_node_os11.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
50901
+ const stage = await import_promises3.default.mkdtemp(import_node_path26.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
50868
50902
  try {
50869
50903
  for (const [name, entry] of Object.entries(zip.files)) {
50870
- const dest = import_node_path25.default.join(stage, name);
50904
+ const dest = import_node_path26.default.join(stage, name);
50871
50905
  if (entry.dir) {
50872
50906
  await import_promises3.default.mkdir(dest, { recursive: true });
50873
50907
  continue;
50874
50908
  }
50875
- await import_promises3.default.mkdir(import_node_path25.default.dirname(dest), { recursive: true });
50909
+ await import_promises3.default.mkdir(import_node_path26.default.dirname(dest), { recursive: true });
50876
50910
  const content = await entry.async("nodebuffer");
50877
50911
  await import_promises3.default.writeFile(dest, content);
50878
50912
  }
@@ -50903,7 +50937,7 @@ var SHARE_UI_ASSET_MIME = {
50903
50937
  ".wasm": "application/wasm"
50904
50938
  };
50905
50939
  function shareUiAssetMime(filePath) {
50906
- const ext = import_node_path26.default.extname(filePath).toLowerCase();
50940
+ const ext = import_node_path27.default.extname(filePath).toLowerCase();
50907
50941
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
50908
50942
  }
50909
50943
  var DISPATCH_HEARTBEAT_MS = 25e3;
@@ -50990,7 +51024,7 @@ function isValidUploadFileName(fileName) {
50990
51024
  if (fileName === "." || fileName === "..") return false;
50991
51025
  if (fileName.startsWith(".")) return false;
50992
51026
  if (fileName.includes("/") || fileName.includes("\\")) return false;
50993
- return fileName === import_node_path26.default.basename(fileName);
51027
+ return fileName === import_node_path27.default.basename(fileName);
50994
51028
  }
50995
51029
  function createHttpRouter(deps) {
50996
51030
  return async (req, res) => {
@@ -51286,7 +51320,7 @@ function createHttpRouter(deps) {
51286
51320
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
51287
51321
  return true;
51288
51322
  }
51289
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path26.default.basename(r.absPath)));
51323
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path27.default.basename(r.absPath)));
51290
51324
  return true;
51291
51325
  }
51292
51326
  const ctx = deps.authResolver.resolveFromHeader(
@@ -51407,7 +51441,7 @@ function createHttpRouter(deps) {
51407
51441
  return true;
51408
51442
  }
51409
51443
  let absPath;
51410
- if (import_node_path26.default.isAbsolute(pathParam)) {
51444
+ if (import_node_path27.default.isAbsolute(pathParam)) {
51411
51445
  absPath = pathParam;
51412
51446
  } else if (deps.sessionStore) {
51413
51447
  const file = deps.sessionStore.read(sid);
@@ -51415,7 +51449,7 @@ function createHttpRouter(deps) {
51415
51449
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
51416
51450
  return true;
51417
51451
  }
51418
- absPath = import_node_path26.default.join(file.cwd, pathParam);
51452
+ absPath = import_node_path27.default.join(file.cwd, pathParam);
51419
51453
  } else {
51420
51454
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
51421
51455
  return true;
@@ -51517,7 +51551,7 @@ function streamFile(res, absPath, logger) {
51517
51551
  return;
51518
51552
  }
51519
51553
  const mime = lookupMime(absPath);
51520
- const basename = import_node_path26.default.basename(absPath);
51554
+ const basename = import_node_path27.default.basename(absPath);
51521
51555
  res.writeHead(200, {
51522
51556
  "Content-Type": mime,
51523
51557
  "Content-Length": String(stat.size),
@@ -51535,7 +51569,7 @@ function streamFile(res, absPath, logger) {
51535
51569
 
51536
51570
  // src/attachment/gc.ts
51537
51571
  var import_node_fs27 = __toESM(require("fs"), 1);
51538
- var import_node_path27 = __toESM(require("path"), 1);
51572
+ var import_node_path28 = __toESM(require("path"), 1);
51539
51573
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
51540
51574
  function runAttachmentGc(args) {
51541
51575
  const now = (args.now ?? Date.now)();
@@ -51544,17 +51578,17 @@ function runAttachmentGc(args) {
51544
51578
  for (const { scope, sessionId } of args.sessionScopes) {
51545
51579
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
51546
51580
  if (entry.stale) continue;
51547
- if (import_node_path27.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
51581
+ if (import_node_path28.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
51548
51582
  }
51549
51583
  }
51550
51584
  for (const { scope, sessionId } of args.sessionScopes) {
51551
- const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path27.default.join(
51585
+ const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path28.default.join(
51552
51586
  args.dataDir,
51553
51587
  "sessions",
51554
51588
  ...scopeSubPath(scope).map(safeFileName),
51555
51589
  safeFileName(sessionId)
51556
51590
  );
51557
- const attRoot = import_node_path27.default.join(sessionDir, ".attachments");
51591
+ const attRoot = import_node_path28.default.join(sessionDir, ".attachments");
51558
51592
  let hashDirs;
51559
51593
  try {
51560
51594
  hashDirs = import_node_fs27.default.readdirSync(attRoot);
@@ -51564,7 +51598,7 @@ function runAttachmentGc(args) {
51564
51598
  continue;
51565
51599
  }
51566
51600
  for (const hashDir of hashDirs) {
51567
- const hashDirAbs = import_node_path27.default.join(attRoot, hashDir);
51601
+ const hashDirAbs = import_node_path28.default.join(attRoot, hashDir);
51568
51602
  let files;
51569
51603
  try {
51570
51604
  files = import_node_fs27.default.readdirSync(hashDirAbs);
@@ -51572,7 +51606,7 @@ function runAttachmentGc(args) {
51572
51606
  continue;
51573
51607
  }
51574
51608
  for (const name of files) {
51575
- const file = import_node_path27.default.join(hashDirAbs, name);
51609
+ const file = import_node_path28.default.join(hashDirAbs, name);
51576
51610
  let stat;
51577
51611
  try {
51578
51612
  stat = import_node_fs27.default.statSync(file);
@@ -51603,7 +51637,7 @@ function runAttachmentGc(args) {
51603
51637
 
51604
51638
  // src/attachment/group.ts
51605
51639
  var import_node_fs28 = __toESM(require("fs"), 1);
51606
- var import_node_path28 = __toESM(require("path"), 1);
51640
+ var import_node_path29 = __toESM(require("path"), 1);
51607
51641
  var import_node_crypto8 = __toESM(require("crypto"), 1);
51608
51642
  init_protocol();
51609
51643
  var GroupFileStore = class {
@@ -51615,11 +51649,11 @@ var GroupFileStore = class {
51615
51649
  this.logger = opts.logger;
51616
51650
  }
51617
51651
  rootForScope(scope) {
51618
- return import_node_path28.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
51652
+ return import_node_path29.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
51619
51653
  }
51620
51654
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
51621
51655
  filePath(scope, sessionId) {
51622
- return import_node_path28.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
51656
+ return import_node_path29.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
51623
51657
  }
51624
51658
  cacheKey(scope, sessionId) {
51625
51659
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -51654,7 +51688,7 @@ var GroupFileStore = class {
51654
51688
  }
51655
51689
  writeFile(scope, sessionId, entries) {
51656
51690
  const file = this.filePath(scope, sessionId);
51657
- import_node_fs28.default.mkdirSync(import_node_path28.default.dirname(file), { recursive: true });
51691
+ import_node_fs28.default.mkdirSync(import_node_path29.default.dirname(file), { recursive: true });
51658
51692
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
51659
51693
  import_node_fs28.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
51660
51694
  import_node_fs28.default.renameSync(tmp, file);
@@ -51744,9 +51778,9 @@ var GroupFileStore = class {
51744
51778
 
51745
51779
  // src/discovery/state-file.ts
51746
51780
  var import_node_fs29 = __toESM(require("fs"), 1);
51747
- var import_node_path29 = __toESM(require("path"), 1);
51781
+ var import_node_path30 = __toESM(require("path"), 1);
51748
51782
  function defaultStateFilePath(dataDir) {
51749
- return import_node_path29.default.join(dataDir, "state.json");
51783
+ return import_node_path30.default.join(dataDir, "state.json");
51750
51784
  }
51751
51785
  function isPidAlive(pid) {
51752
51786
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -51782,7 +51816,7 @@ var StateFileManager = class {
51782
51816
  return { status: "stale", existing };
51783
51817
  }
51784
51818
  write(state) {
51785
- import_node_fs29.default.mkdirSync(import_node_path29.default.dirname(this.file), { recursive: true });
51819
+ import_node_fs29.default.mkdirSync(import_node_path30.default.dirname(this.file), { recursive: true });
51786
51820
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
51787
51821
  import_node_fs29.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
51788
51822
  import_node_fs29.default.renameSync(tmp, this.file);
@@ -51811,13 +51845,13 @@ function readDaemonSourceFromEnv(env = process.env) {
51811
51845
 
51812
51846
  // src/tunnel/tunnel-manager.ts
51813
51847
  var import_node_fs33 = __toESM(require("fs"), 1);
51814
- var import_node_path33 = __toESM(require("path"), 1);
51848
+ var import_node_path34 = __toESM(require("path"), 1);
51815
51849
  var import_node_crypto9 = __toESM(require("crypto"), 1);
51816
51850
  var import_node_child_process9 = require("child_process");
51817
51851
 
51818
51852
  // src/tunnel/tunnel-store.ts
51819
51853
  var import_node_fs30 = __toESM(require("fs"), 1);
51820
- var import_node_path30 = __toESM(require("path"), 1);
51854
+ var import_node_path31 = __toESM(require("path"), 1);
51821
51855
  var TunnelStore = class {
51822
51856
  constructor(filePath) {
51823
51857
  this.filePath = filePath;
@@ -51836,7 +51870,7 @@ var TunnelStore = class {
51836
51870
  }
51837
51871
  }
51838
51872
  async set(v2) {
51839
- const dir = import_node_path30.default.dirname(this.filePath);
51873
+ const dir = import_node_path31.default.dirname(this.filePath);
51840
51874
  await import_node_fs30.default.promises.mkdir(dir, { recursive: true });
51841
51875
  const data = JSON.stringify(v2, null, 2);
51842
51876
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
@@ -51947,8 +51981,8 @@ function escape(v2) {
51947
51981
 
51948
51982
  // src/tunnel/frpc-binary.ts
51949
51983
  var import_node_fs31 = __toESM(require("fs"), 1);
51950
- var import_node_os12 = __toESM(require("os"), 1);
51951
- var import_node_path31 = __toESM(require("path"), 1);
51984
+ var import_node_os13 = __toESM(require("os"), 1);
51985
+ var import_node_path32 = __toESM(require("path"), 1);
51952
51986
  var import_node_child_process7 = require("child_process");
51953
51987
  var import_node_stream3 = require("stream");
51954
51988
  var import_promises4 = require("stream/promises");
@@ -51987,13 +52021,13 @@ async function ensureFrpcBinary(opts) {
51987
52021
  }
51988
52022
  const version2 = opts.version ?? FRPC_VERSION;
51989
52023
  const platform = opts.platform ?? detectPlatform();
51990
- const binDir = import_node_path31.default.join(opts.dataDir, "bin");
52024
+ const binDir = import_node_path32.default.join(opts.dataDir, "bin");
51991
52025
  import_node_fs31.default.mkdirSync(binDir, { recursive: true });
51992
52026
  cleanupStaleArtifacts(binDir);
51993
- const stableBin = import_node_path31.default.join(binDir, "frpc");
52027
+ const stableBin = import_node_path32.default.join(binDir, "frpc");
51994
52028
  if (import_node_fs31.default.existsSync(stableBin)) return stableBin;
51995
52029
  const partialBin = `${stableBin}.partial`;
51996
- const tarballPath = import_node_path31.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
52030
+ const tarballPath = import_node_path32.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
51997
52031
  try {
51998
52032
  const url = frpcDownloadUrl(version2, platform);
51999
52033
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -52019,7 +52053,7 @@ function cleanupStaleArtifacts(binDir) {
52019
52053
  }
52020
52054
  for (const name of entries) {
52021
52055
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
52022
- const full = import_node_path31.default.join(binDir, name);
52056
+ const full = import_node_path32.default.join(binDir, name);
52023
52057
  try {
52024
52058
  import_node_fs31.default.rmSync(full, { recursive: true, force: true });
52025
52059
  } catch {
@@ -52045,7 +52079,7 @@ async function downloadToFile(url, dest, fetchImpl) {
52045
52079
  await (0, import_promises4.pipeline)(nodeStream, out);
52046
52080
  }
52047
52081
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
52048
- const work = import_node_path31.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
52082
+ const work = import_node_path32.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
52049
52083
  import_node_fs31.default.mkdirSync(work, { recursive: true });
52050
52084
  try {
52051
52085
  await new Promise((resolve6, reject) => {
@@ -52054,7 +52088,7 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
52054
52088
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
52055
52089
  });
52056
52090
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
52057
- const src = import_node_path31.default.join(work, dirName, "frpc");
52091
+ const src = import_node_path32.default.join(work, dirName, "frpc");
52058
52092
  if (!import_node_fs31.default.existsSync(src)) {
52059
52093
  throw new Error(`frpc not found inside tarball at ${src}`);
52060
52094
  }
@@ -52066,10 +52100,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
52066
52100
 
52067
52101
  // src/tunnel/frpc-process.ts
52068
52102
  var import_node_fs32 = __toESM(require("fs"), 1);
52069
- var import_node_path32 = __toESM(require("path"), 1);
52103
+ var import_node_path33 = __toESM(require("path"), 1);
52070
52104
  var import_node_child_process8 = require("child_process");
52071
52105
  function frpcPidFilePath(dataDir) {
52072
- return import_node_path32.default.join(dataDir, "frpc.pid");
52106
+ return import_node_path33.default.join(dataDir, "frpc.pid");
52073
52107
  }
52074
52108
  function writeFrpcPid(dataDir, pid) {
52075
52109
  try {
@@ -52111,7 +52145,7 @@ function defaultSleep(ms) {
52111
52145
  }
52112
52146
  async function killStaleFrpc(deps) {
52113
52147
  const pidFile = frpcPidFilePath(deps.dataDir);
52114
- const tomlPath = import_node_path32.default.join(deps.dataDir, "frpc.toml");
52148
+ const tomlPath = import_node_path33.default.join(deps.dataDir, "frpc.toml");
52115
52149
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
52116
52150
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
52117
52151
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -52183,7 +52217,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
52183
52217
  var TunnelManager = class {
52184
52218
  constructor(deps) {
52185
52219
  this.deps = deps;
52186
- this.store = deps.store ?? new TunnelStore(import_node_path33.default.join(deps.dataDir, "tunnel.json"));
52220
+ this.store = deps.store ?? new TunnelStore(import_node_path34.default.join(deps.dataDir, "tunnel.json"));
52187
52221
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
52188
52222
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
52189
52223
  }
@@ -52310,7 +52344,7 @@ var TunnelManager = class {
52310
52344
  dataDir: this.deps.dataDir,
52311
52345
  override: this.deps.frpcBinaryOverride ?? void 0
52312
52346
  });
52313
- const tomlPath = import_node_path33.default.join(this.deps.dataDir, "frpc.toml");
52347
+ const tomlPath = import_node_path34.default.join(this.deps.dataDir, "frpc.toml");
52314
52348
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto9.default.randomBytes(3).toString("hex")}`;
52315
52349
  const toml = buildFrpcToml({
52316
52350
  serverAddr: t.frpsHost,
@@ -52325,7 +52359,7 @@ var TunnelManager = class {
52325
52359
  const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
52326
52360
  stdio: ["ignore", "pipe", "pipe"]
52327
52361
  });
52328
- const logFilePath = import_node_path33.default.join(this.deps.dataDir, "frpc.log");
52362
+ const logFilePath = import_node_path34.default.join(this.deps.dataDir, "frpc.log");
52329
52363
  const logStream = import_node_fs33.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
52330
52364
  logStream.on("error", () => {
52331
52365
  });
@@ -52408,16 +52442,16 @@ async function waitForFrpcReady(proc, timeoutMs) {
52408
52442
  }
52409
52443
 
52410
52444
  // src/tunnel/device-key.ts
52411
- var import_node_os13 = __toESM(require("os"), 1);
52412
- var import_node_path34 = __toESM(require("path"), 1);
52445
+ var import_node_os14 = __toESM(require("os"), 1);
52446
+ var import_node_path35 = __toESM(require("path"), 1);
52413
52447
  var import_node_crypto10 = __toESM(require("crypto"), 1);
52414
52448
  var DERIVE_SALT = "clawd-tunnel-device-v1";
52415
52449
  function deriveStableDeviceKey(opts = {}) {
52416
- const hostname = opts.hostname ?? import_node_os13.default.hostname();
52417
- const uid = opts.uid ?? (typeof import_node_os13.default.userInfo === "function" ? import_node_os13.default.userInfo().uid : 0);
52418
- const home = opts.home ?? import_node_os13.default.homedir();
52419
- const defaultDataDir = import_node_path34.default.resolve(import_node_path34.default.join(home, ".clawd"));
52420
- const normalizedDataDir = opts.dataDir ? import_node_path34.default.resolve(opts.dataDir) : null;
52450
+ const hostname = opts.hostname ?? import_node_os14.default.hostname();
52451
+ const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
52452
+ const home = opts.home ?? import_node_os14.default.homedir();
52453
+ const defaultDataDir = import_node_path35.default.resolve(import_node_path35.default.join(home, ".clawd"));
52454
+ const normalizedDataDir = opts.dataDir ? import_node_path35.default.resolve(opts.dataDir) : null;
52421
52455
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
52422
52456
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
52423
52457
  return import_node_crypto10.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
@@ -52425,11 +52459,11 @@ function deriveStableDeviceKey(opts = {}) {
52425
52459
 
52426
52460
  // src/auth-store.ts
52427
52461
  var import_node_fs34 = __toESM(require("fs"), 1);
52428
- var import_node_path35 = __toESM(require("path"), 1);
52462
+ var import_node_path36 = __toESM(require("path"), 1);
52429
52463
  var import_node_crypto11 = __toESM(require("crypto"), 1);
52430
52464
  var AUTH_FILE_NAME = "auth.json";
52431
52465
  function authFilePath(dataDir) {
52432
- return import_node_path35.default.join(dataDir, AUTH_FILE_NAME);
52466
+ return import_node_path36.default.join(dataDir, AUTH_FILE_NAME);
52433
52467
  }
52434
52468
  function loadOrCreateAuthFile(opts) {
52435
52469
  const file = authFilePath(opts.dataDir);
@@ -52485,7 +52519,7 @@ function readAuthFile(file) {
52485
52519
  }
52486
52520
  }
52487
52521
  function writeAuthFile(file, content) {
52488
- import_node_fs34.default.mkdirSync(import_node_path35.default.dirname(file), { recursive: true });
52522
+ import_node_fs34.default.mkdirSync(import_node_path36.default.dirname(file), { recursive: true });
52489
52523
  import_node_fs34.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
52490
52524
  try {
52491
52525
  import_node_fs34.default.chmodSync(file, 384);
@@ -52495,12 +52529,12 @@ function writeAuthFile(file, content) {
52495
52529
 
52496
52530
  // src/owner-profile.ts
52497
52531
  var import_node_fs35 = __toESM(require("fs"), 1);
52498
- var import_node_os14 = __toESM(require("os"), 1);
52499
- var import_node_path36 = __toESM(require("path"), 1);
52532
+ var import_node_os15 = __toESM(require("os"), 1);
52533
+ var import_node_path37 = __toESM(require("path"), 1);
52500
52534
  var PROFILE_FILENAME = "profile.json";
52501
52535
  function loadOwnerDisplayName(dataDir) {
52502
- const fallback = import_node_os14.default.userInfo().username;
52503
- const profilePath = import_node_path36.default.join(dataDir, PROFILE_FILENAME);
52536
+ const fallback = import_node_os15.default.userInfo().username;
52537
+ const profilePath = import_node_path37.default.join(dataDir, PROFILE_FILENAME);
52504
52538
  let raw;
52505
52539
  try {
52506
52540
  raw = import_node_fs35.default.readFileSync(profilePath, "utf8");
@@ -52527,12 +52561,12 @@ function loadOwnerDisplayName(dataDir) {
52527
52561
 
52528
52562
  // src/feishu-auth/owner-identity-store.ts
52529
52563
  var import_node_fs36 = __toESM(require("fs"), 1);
52530
- var import_node_path37 = __toESM(require("path"), 1);
52564
+ var import_node_path38 = __toESM(require("path"), 1);
52531
52565
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
52532
52566
  var OwnerIdentityStore = class {
52533
52567
  file;
52534
52568
  constructor(dataDir) {
52535
- this.file = import_node_path37.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
52569
+ this.file = import_node_path38.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
52536
52570
  }
52537
52571
  read() {
52538
52572
  let raw;
@@ -52565,7 +52599,7 @@ var OwnerIdentityStore = class {
52565
52599
  };
52566
52600
  }
52567
52601
  write(record) {
52568
- import_node_fs36.default.mkdirSync(import_node_path37.default.dirname(this.file), { recursive: true });
52602
+ import_node_fs36.default.mkdirSync(import_node_path38.default.dirname(this.file), { recursive: true });
52569
52603
  import_node_fs36.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
52570
52604
  try {
52571
52605
  import_node_fs36.default.chmodSync(this.file, 384);
@@ -52695,9 +52729,9 @@ var CentralClientError = class extends Error {
52695
52729
  code;
52696
52730
  cause;
52697
52731
  };
52698
- async function centralRequest(opts, path67, init) {
52732
+ async function centralRequest(opts, path68, init) {
52699
52733
  const f = opts.fetchImpl ?? globalThis.fetch;
52700
- const url = `${opts.api.replace(/\/+$/, "")}${path67}`;
52734
+ const url = `${opts.api.replace(/\/+$/, "")}${path68}`;
52701
52735
  const ctrl = new AbortController();
52702
52736
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
52703
52737
  let res;
@@ -52840,7 +52874,7 @@ function verifyConnectToken(args) {
52840
52874
 
52841
52875
  // src/feishu-auth/server-key.ts
52842
52876
  var fs46 = __toESM(require("fs"), 1);
52843
- var path46 = __toESM(require("path"), 1);
52877
+ var path47 = __toESM(require("path"), 1);
52844
52878
  var FILE_NAME2 = "server-signing-key.json";
52845
52879
  var ServerKeyStore = class {
52846
52880
  constructor(dataDir) {
@@ -52848,7 +52882,7 @@ var ServerKeyStore = class {
52848
52882
  }
52849
52883
  dataDir;
52850
52884
  filePath() {
52851
- return path46.join(this.dataDir, FILE_NAME2);
52885
+ return path47.join(this.dataDir, FILE_NAME2);
52852
52886
  }
52853
52887
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
52854
52888
  read() {
@@ -52887,8 +52921,8 @@ init_protocol();
52887
52921
 
52888
52922
  // src/session/fork.ts
52889
52923
  var import_node_fs37 = __toESM(require("fs"), 1);
52890
- var import_node_os15 = __toESM(require("os"), 1);
52891
- var import_node_path38 = __toESM(require("path"), 1);
52924
+ var import_node_os16 = __toESM(require("os"), 1);
52925
+ var import_node_path39 = __toESM(require("path"), 1);
52892
52926
  init_claude_history();
52893
52927
  function readJsonlEntries(file) {
52894
52928
  const raw = import_node_fs37.default.readFileSync(file, "utf8");
@@ -52904,9 +52938,9 @@ function readJsonlEntries(file) {
52904
52938
  return out;
52905
52939
  }
52906
52940
  function forkSession(input) {
52907
- const baseDir = input.baseDir ?? import_node_path38.default.join(import_node_os15.default.homedir(), ".claude");
52908
- const projectDir = import_node_path38.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
52909
- const sourceFile = import_node_path38.default.join(projectDir, `${input.toolSessionId}.jsonl`);
52941
+ const baseDir = input.baseDir ?? import_node_path39.default.join(import_node_os16.default.homedir(), ".claude");
52942
+ const projectDir = import_node_path39.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
52943
+ const sourceFile = import_node_path39.default.join(projectDir, `${input.toolSessionId}.jsonl`);
52910
52944
  if (!import_node_fs37.default.existsSync(sourceFile)) {
52911
52945
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
52912
52946
  }
@@ -52937,7 +52971,7 @@ function forkSession(input) {
52937
52971
  }
52938
52972
  forkedLines.push(JSON.stringify(forked));
52939
52973
  }
52940
- const forkedFilePath = import_node_path38.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
52974
+ const forkedFilePath = import_node_path39.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
52941
52975
  import_node_fs37.default.mkdirSync(projectDir, { recursive: true });
52942
52976
  import_node_fs37.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
52943
52977
  return { forkedToolSessionId, forkedFilePath };
@@ -53291,7 +53325,7 @@ function buildPermissionHandlers(deps) {
53291
53325
  }
53292
53326
 
53293
53327
  // src/handlers/history.ts
53294
- var path49 = __toESM(require("path"), 1);
53328
+ var path50 = __toESM(require("path"), 1);
53295
53329
  init_protocol();
53296
53330
 
53297
53331
  // src/session/recent-dirs.ts
@@ -53309,7 +53343,7 @@ function listRecentDirs(store, limit = 50) {
53309
53343
  }
53310
53344
 
53311
53345
  // src/permission/persona-paths.ts
53312
- var path48 = __toESM(require("path"), 1);
53346
+ var path49 = __toESM(require("path"), 1);
53313
53347
  function getAllowedPersonaIds(grants, action) {
53314
53348
  const ids = /* @__PURE__ */ new Set();
53315
53349
  for (const g2 of grants) {
@@ -53322,42 +53356,42 @@ function getAllowedPersonaIds(grants, action) {
53322
53356
  return ids;
53323
53357
  }
53324
53358
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
53325
- const target = path48.resolve(absPath);
53359
+ const target = path49.resolve(absPath);
53326
53360
  if (userWorkDir) {
53327
- const u = path48.resolve(userWorkDir);
53328
- const usep = u.endsWith(path48.sep) ? "" : path48.sep;
53361
+ const u = path49.resolve(userWorkDir);
53362
+ const usep = u.endsWith(path49.sep) ? "" : path49.sep;
53329
53363
  if (target === u || target.startsWith(u + usep)) return true;
53330
53364
  }
53331
- const root = path48.resolve(personaRoot);
53332
- const sep3 = root.endsWith(path48.sep) ? "" : path48.sep;
53365
+ const root = path49.resolve(personaRoot);
53366
+ const sep3 = root.endsWith(path49.sep) ? "" : path49.sep;
53333
53367
  if (!target.startsWith(root + sep3)) return false;
53334
- const rel = path48.relative(root, target);
53368
+ const rel = path49.relative(root, target);
53335
53369
  if (!rel || rel.startsWith("..")) return false;
53336
- const personaId = rel.split(path48.sep)[0];
53370
+ const personaId = rel.split(path49.sep)[0];
53337
53371
  if (!personaId) return false;
53338
53372
  const allowed = getAllowedPersonaIds(grants, action);
53339
53373
  if (allowed === "*") return true;
53340
53374
  return allowed.has(personaId);
53341
53375
  }
53342
53376
  function personaIdFromPath(absPath, personaRoot) {
53343
- const root = path48.resolve(personaRoot);
53344
- const target = path48.resolve(absPath);
53345
- const sep3 = root.endsWith(path48.sep) ? "" : path48.sep;
53377
+ const root = path49.resolve(personaRoot);
53378
+ const target = path49.resolve(absPath);
53379
+ const sep3 = root.endsWith(path49.sep) ? "" : path49.sep;
53346
53380
  if (!target.startsWith(root + sep3)) return null;
53347
- const rel = path48.relative(root, target);
53381
+ const rel = path49.relative(root, target);
53348
53382
  if (!rel || rel.startsWith("..")) return null;
53349
- const id = rel.split(path48.sep)[0];
53383
+ const id = rel.split(path49.sep)[0];
53350
53384
  return id || null;
53351
53385
  }
53352
53386
  function isPathWithin(dir, absPath) {
53353
- const d = path48.resolve(dir);
53354
- const t = path48.resolve(absPath);
53355
- const sep3 = d.endsWith(path48.sep) ? "" : path48.sep;
53387
+ const d = path49.resolve(dir);
53388
+ const t = path49.resolve(absPath);
53389
+ const sep3 = d.endsWith(path49.sep) ? "" : path49.sep;
53356
53390
  return t === d || t.startsWith(d + sep3);
53357
53391
  }
53358
53392
  function isPathInGuestBoundary(personaRoot, personaId, userWorkDir, absPath) {
53359
53393
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
53360
- return personaIdFromPath(path48.resolve(absPath), personaRoot) === personaId;
53394
+ return personaIdFromPath(path49.resolve(absPath), personaRoot) === personaId;
53361
53395
  }
53362
53396
 
53363
53397
  // src/handlers/history.ts
@@ -53383,7 +53417,7 @@ function buildHistoryHandlers(deps) {
53383
53417
  if (!pid) return false;
53384
53418
  return isGuestPathAllowed(
53385
53419
  ctx.grants,
53386
- path49.join(personaRoot, pid),
53420
+ path50.join(personaRoot, pid),
53387
53421
  personaRoot,
53388
53422
  "read",
53389
53423
  userWorkDir
@@ -53395,7 +53429,7 @@ function buildHistoryHandlers(deps) {
53395
53429
  };
53396
53430
  const list = async (frame, _client, ctx) => {
53397
53431
  const args = HistoryListArgs.parse(frame);
53398
- assertGuestPath(ctx, path49.resolve(args.projectPath), personaRoot, "history:list");
53432
+ assertGuestPath(ctx, path50.resolve(args.projectPath), personaRoot, "history:list");
53399
53433
  const sessions = await history.listSessions(args);
53400
53434
  return { response: { type: "history:list", sessions } };
53401
53435
  };
@@ -53427,13 +53461,13 @@ function buildHistoryHandlers(deps) {
53427
53461
  };
53428
53462
  const subagents = async (frame, _client, ctx) => {
53429
53463
  const args = HistorySubagentsArgs.parse(frame);
53430
- assertGuestPath(ctx, path49.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
53464
+ assertGuestPath(ctx, path50.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
53431
53465
  const subs = await history.listSubagents(args);
53432
53466
  return { response: { type: "history:subagents", subagents: subs } };
53433
53467
  };
53434
53468
  const subagentRead = async (frame, _client, ctx) => {
53435
53469
  const args = HistorySubagentReadArgs.parse(frame);
53436
- assertGuestPath(ctx, path49.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
53470
+ assertGuestPath(ctx, path50.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
53437
53471
  const res = await history.readSubagent(args);
53438
53472
  return { response: { type: "history:subagent-read", ...res } };
53439
53473
  };
@@ -53442,7 +53476,7 @@ function buildHistoryHandlers(deps) {
53442
53476
  if (ctx?.principal.kind === "guest" && personaRoot) {
53443
53477
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
53444
53478
  const filtered = dirs.filter(
53445
- (d) => isGuestPathAllowed(ctx.grants, path49.resolve(d.cwd), personaRoot, "read", userWorkDir)
53479
+ (d) => isGuestPathAllowed(ctx.grants, path50.resolve(d.cwd), personaRoot, "read", userWorkDir)
53446
53480
  );
53447
53481
  return { response: { type: "history:recentDirs", dirs: filtered } };
53448
53482
  }
@@ -53459,8 +53493,8 @@ function buildHistoryHandlers(deps) {
53459
53493
  }
53460
53494
 
53461
53495
  // src/handlers/workspace.ts
53462
- var path50 = __toESM(require("path"), 1);
53463
- var os15 = __toESM(require("os"), 1);
53496
+ var path51 = __toESM(require("path"), 1);
53497
+ var os16 = __toESM(require("os"), 1);
53464
53498
  init_protocol();
53465
53499
  init_protocol();
53466
53500
  function buildEnabledPluginNames(personaManager, personaId) {
@@ -53500,23 +53534,23 @@ function buildWorkspaceHandlers(deps) {
53500
53534
  const list = async (frame, _client, ctx) => {
53501
53535
  const args = WorkspaceListArgs.parse(frame);
53502
53536
  const isGuest = ctx?.principal.kind === "guest";
53503
- const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
53504
- const resolvedCwd = path50.resolve(args.cwd ?? fallbackCwd);
53505
- const target = args.path ? path50.resolve(resolvedCwd, args.path) : resolvedCwd;
53537
+ const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
53538
+ const resolvedCwd = path51.resolve(args.cwd ?? fallbackCwd);
53539
+ const target = args.path ? path51.resolve(resolvedCwd, args.path) : resolvedCwd;
53506
53540
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
53507
53541
  const res = workspace.list({ ...args, cwd: resolvedCwd });
53508
53542
  return { response: { type: "workspace:list", ...res } };
53509
53543
  };
53510
53544
  const read = async (frame, _client, ctx) => {
53511
53545
  const args = WorkspaceReadArgs.parse(frame);
53512
- const target = path50.isAbsolute(args.path) ? path50.resolve(args.path) : path50.resolve(args.cwd, args.path);
53546
+ const target = path51.isAbsolute(args.path) ? path51.resolve(args.path) : path51.resolve(args.cwd, args.path);
53513
53547
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
53514
53548
  const res = workspace.read(args);
53515
53549
  return { response: { type: "workspace:read", ...res } };
53516
53550
  };
53517
53551
  const skillsList = async (frame, _client, ctx) => {
53518
53552
  const args = SkillsListArgs.parse(frame);
53519
- const cwdAbs = path50.resolve(args.cwd);
53553
+ const cwdAbs = path51.resolve(args.cwd);
53520
53554
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
53521
53555
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
53522
53556
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -53528,7 +53562,7 @@ function buildWorkspaceHandlers(deps) {
53528
53562
  };
53529
53563
  const agentsList = async (frame, _client, ctx) => {
53530
53564
  const args = AgentsListArgs.parse(frame);
53531
- const cwdAbs = path50.resolve(args.cwd);
53565
+ const cwdAbs = path51.resolve(args.cwd);
53532
53566
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
53533
53567
  if (args.tool === "codex") {
53534
53568
  return { response: { type: "agents:list", agents: [] } };
@@ -53550,18 +53584,18 @@ function buildWorkspaceHandlers(deps) {
53550
53584
  }
53551
53585
 
53552
53586
  // src/handlers/git.ts
53553
- var path52 = __toESM(require("path"), 1);
53587
+ var path53 = __toESM(require("path"), 1);
53554
53588
  init_protocol();
53555
53589
  init_protocol();
53556
53590
 
53557
53591
  // src/workspace/git.ts
53558
53592
  var import_node_child_process10 = require("child_process");
53559
53593
  var import_node_fs38 = __toESM(require("fs"), 1);
53560
- var import_node_path39 = __toESM(require("path"), 1);
53594
+ var import_node_path40 = __toESM(require("path"), 1);
53561
53595
  var import_node_util = require("util");
53562
53596
  var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
53563
53597
  function normalizePath(p2) {
53564
- const resolved = import_node_path39.default.resolve(p2);
53598
+ const resolved = import_node_path40.default.resolve(p2);
53565
53599
  try {
53566
53600
  return import_node_fs38.default.realpathSync(resolved);
53567
53601
  } catch {
@@ -53637,7 +53671,7 @@ async function listGitBranches(cwd) {
53637
53671
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
53638
53672
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
53639
53673
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
53640
- if (!isGuestPathAllowed(ctx.grants, path52.resolve(cwd), personaRoot, "read", userWorkDir)) {
53674
+ if (!isGuestPathAllowed(ctx.grants, path53.resolve(cwd), personaRoot, "read", userWorkDir)) {
53641
53675
  throw new ClawdError(
53642
53676
  ERROR_CODES.UNAUTHORIZED,
53643
53677
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -54123,7 +54157,7 @@ function buildDeviceHandlers(deps) {
54123
54157
  }
54124
54158
 
54125
54159
  // src/handlers/meta.ts
54126
- var import_node_os16 = __toESM(require("os"), 1);
54160
+ var import_node_os17 = __toESM(require("os"), 1);
54127
54161
  init_protocol();
54128
54162
 
54129
54163
  // src/version.ts
@@ -54155,7 +54189,7 @@ function buildReadyFrame(deps, client) {
54155
54189
  return {
54156
54190
  version,
54157
54191
  protocolVersion: PROTOCOL_VERSION,
54158
- hostname: import_node_os16.default.hostname(),
54192
+ hostname: import_node_os17.default.hostname(),
54159
54193
  os: process.platform,
54160
54194
  tools,
54161
54195
  runningSessions: info.runningSessions,
@@ -54252,7 +54286,7 @@ function buildPersonaHandlers(deps) {
54252
54286
  }
54253
54287
 
54254
54288
  // src/handlers/attachment.ts
54255
- var import_node_path40 = __toESM(require("path"), 1);
54289
+ var import_node_path41 = __toESM(require("path"), 1);
54256
54290
  init_protocol();
54257
54291
  init_protocol();
54258
54292
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -54332,12 +54366,12 @@ function buildAttachmentHandlers(deps) {
54332
54366
  `session ${args.sessionId} scope unresolved`
54333
54367
  );
54334
54368
  }
54335
- const cwdAbs = import_node_path40.default.resolve(sessionFile.cwd);
54336
- const candidateAbs = import_node_path40.default.isAbsolute(args.relPath) ? import_node_path40.default.resolve(args.relPath) : import_node_path40.default.resolve(cwdAbs, args.relPath);
54369
+ const cwdAbs = import_node_path41.default.resolve(sessionFile.cwd);
54370
+ const candidateAbs = import_node_path41.default.isAbsolute(args.relPath) ? import_node_path41.default.resolve(args.relPath) : import_node_path41.default.resolve(cwdAbs, args.relPath);
54337
54371
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
54338
54372
  const entries = deps.groupFileStore.list(scope, args.sessionId);
54339
54373
  const entry = entries.find((e) => {
54340
- const storedAbs = import_node_path40.default.isAbsolute(e.relPath) ? import_node_path40.default.resolve(e.relPath) : import_node_path40.default.resolve(cwdAbs, e.relPath);
54374
+ const storedAbs = import_node_path41.default.isAbsolute(e.relPath) ? import_node_path41.default.resolve(e.relPath) : import_node_path41.default.resolve(cwdAbs, e.relPath);
54341
54375
  return storedAbs === candidateAbs && !e.stale;
54342
54376
  });
54343
54377
  if (!entry) {
@@ -54362,7 +54396,7 @@ function buildAttachmentHandlers(deps) {
54362
54396
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
54363
54397
  const f = deps.sessionStore.read(sessionId);
54364
54398
  if (!f) return;
54365
- assertGuestAttachmentPath(ctx, import_node_path40.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
54399
+ assertGuestAttachmentPath(ctx, import_node_path41.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
54366
54400
  }
54367
54401
  const groupAdd = async (frame, _client, ctx) => {
54368
54402
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -54377,8 +54411,8 @@ function buildAttachmentHandlers(deps) {
54377
54411
  if (!scope) {
54378
54412
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
54379
54413
  }
54380
- const cwdAbs = import_node_path40.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
54381
- const candidateAbs = import_node_path40.default.isAbsolute(args.relPath) ? import_node_path40.default.resolve(args.relPath) : import_node_path40.default.resolve(cwdAbs, args.relPath);
54414
+ const cwdAbs = import_node_path41.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
54415
+ const candidateAbs = import_node_path41.default.isAbsolute(args.relPath) ? import_node_path41.default.resolve(args.relPath) : import_node_path41.default.resolve(cwdAbs, args.relPath);
54382
54416
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
54383
54417
  const from = ctx?.principal.kind === "owner" ? "owner" : "agent";
54384
54418
  const size = 0;
@@ -54437,19 +54471,19 @@ function buildAttachmentHandlers(deps) {
54437
54471
 
54438
54472
  // src/handlers/extension.ts
54439
54473
  var import_promises8 = __toESM(require("fs/promises"), 1);
54440
- var import_node_path45 = __toESM(require("path"), 1);
54474
+ var import_node_path46 = __toESM(require("path"), 1);
54441
54475
  init_protocol();
54442
54476
 
54443
54477
  // src/extension/bundle-zip.ts
54444
54478
  var import_promises5 = __toESM(require("fs/promises"), 1);
54445
- var import_node_path41 = __toESM(require("path"), 1);
54479
+ var import_node_path42 = __toESM(require("path"), 1);
54446
54480
  var import_node_crypto13 = __toESM(require("crypto"), 1);
54447
54481
  var import_jszip2 = __toESM(require_lib3(), 1);
54448
54482
  async function bundleExtensionDir(dir) {
54449
54483
  const entries = await listFilesSorted(dir);
54450
54484
  const zip = new import_jszip2.default();
54451
54485
  for (const rel of entries) {
54452
- const abs = import_node_path41.default.join(dir, rel);
54486
+ const abs = import_node_path42.default.join(dir, rel);
54453
54487
  const content = await import_promises5.default.readFile(abs);
54454
54488
  zip.file(rel, content, { date: FIXED_DATE });
54455
54489
  }
@@ -54470,7 +54504,7 @@ async function listFilesSorted(rootDir) {
54470
54504
  return out;
54471
54505
  }
54472
54506
  async function walk(absRoot, relPrefix, out) {
54473
- const dirAbs = import_node_path41.default.join(absRoot, relPrefix);
54507
+ const dirAbs = import_node_path42.default.join(absRoot, relPrefix);
54474
54508
  const entries = await import_promises5.default.readdir(dirAbs, { withFileTypes: true });
54475
54509
  for (const e of entries) {
54476
54510
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -54524,25 +54558,25 @@ function computePublishCheck(args) {
54524
54558
 
54525
54559
  // src/extension/install-flow.ts
54526
54560
  var import_promises6 = __toESM(require("fs/promises"), 1);
54527
- var import_node_path43 = __toESM(require("path"), 1);
54528
- var import_node_os18 = __toESM(require("os"), 1);
54561
+ var import_node_path44 = __toESM(require("path"), 1);
54562
+ var import_node_os19 = __toESM(require("os"), 1);
54529
54563
  var import_node_crypto14 = __toESM(require("crypto"), 1);
54530
54564
  var import_jszip3 = __toESM(require_lib3(), 1);
54531
54565
 
54532
54566
  // src/extension/paths.ts
54533
- var import_node_os17 = __toESM(require("os"), 1);
54534
- var import_node_path42 = __toESM(require("path"), 1);
54567
+ var import_node_os18 = __toESM(require("os"), 1);
54568
+ var import_node_path43 = __toESM(require("path"), 1);
54535
54569
  function clawdHomeRoot(override) {
54536
- return override ?? process.env.CLAWD_HOME ?? import_node_path42.default.join(import_node_os17.default.homedir(), ".clawd");
54570
+ return override ?? process.env.CLAWD_HOME ?? import_node_path43.default.join(import_node_os18.default.homedir(), ".clawd");
54537
54571
  }
54538
54572
  function extensionsRoot(override) {
54539
- return import_node_path42.default.join(clawdHomeRoot(override), "extensions");
54573
+ return import_node_path43.default.join(clawdHomeRoot(override), "extensions");
54540
54574
  }
54541
54575
  function publishedChannelsFile(override) {
54542
- return import_node_path42.default.join(clawdHomeRoot(override), "extensions-published.json");
54576
+ return import_node_path43.default.join(clawdHomeRoot(override), "extensions-published.json");
54543
54577
  }
54544
54578
  function bundleCacheRoot(override) {
54545
- return import_node_path42.default.join(clawdHomeRoot(override), "extension-bundles");
54579
+ return import_node_path43.default.join(clawdHomeRoot(override), "extension-bundles");
54546
54580
  }
54547
54581
 
54548
54582
  // src/extension/install-flow.ts
@@ -54569,7 +54603,7 @@ async function installFromChannel(args, deps) {
54569
54603
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
54570
54604
  }
54571
54605
  for (const name of Object.keys(zip.files)) {
54572
- if (name.includes("..") || name.startsWith("/") || import_node_path43.default.isAbsolute(name)) {
54606
+ if (name.includes("..") || name.startsWith("/") || import_node_path44.default.isAbsolute(name)) {
54573
54607
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
54574
54608
  }
54575
54609
  }
@@ -54601,7 +54635,7 @@ async function installFromChannel(args, deps) {
54601
54635
  );
54602
54636
  }
54603
54637
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
54604
- const destDir = import_node_path43.default.join(deps.extensionsRoot, localExtId);
54638
+ const destDir = import_node_path44.default.join(deps.extensionsRoot, localExtId);
54605
54639
  let destExists = false;
54606
54640
  try {
54607
54641
  await import_promises6.default.access(destDir);
@@ -54615,16 +54649,16 @@ async function installFromChannel(args, deps) {
54615
54649
  );
54616
54650
  }
54617
54651
  const stage = await import_promises6.default.mkdtemp(
54618
- import_node_path43.default.join(import_node_os18.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
54652
+ import_node_path44.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
54619
54653
  );
54620
54654
  try {
54621
54655
  for (const [name, entry] of Object.entries(zip.files)) {
54622
- const dest = import_node_path43.default.join(stage, name);
54656
+ const dest = import_node_path44.default.join(stage, name);
54623
54657
  if (entry.dir) {
54624
54658
  await import_promises6.default.mkdir(dest, { recursive: true });
54625
54659
  continue;
54626
54660
  }
54627
- await import_promises6.default.mkdir(import_node_path43.default.dirname(dest), { recursive: true });
54661
+ await import_promises6.default.mkdir(import_node_path44.default.dirname(dest), { recursive: true });
54628
54662
  if (name === "manifest.json") {
54629
54663
  const rewritten = { ...parsed.data, id: localExtId };
54630
54664
  await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -54645,8 +54679,8 @@ async function installFromChannel(args, deps) {
54645
54679
 
54646
54680
  // src/extension/update-flow.ts
54647
54681
  var import_promises7 = __toESM(require("fs/promises"), 1);
54648
- var import_node_path44 = __toESM(require("path"), 1);
54649
- var import_node_os19 = __toESM(require("os"), 1);
54682
+ var import_node_path45 = __toESM(require("path"), 1);
54683
+ var import_node_os20 = __toESM(require("os"), 1);
54650
54684
  var import_node_crypto15 = __toESM(require("crypto"), 1);
54651
54685
  var import_jszip4 = __toESM(require_lib3(), 1);
54652
54686
  var UpdateError = class extends Error {
@@ -54662,11 +54696,11 @@ async function updateFromChannel(args, deps) {
54662
54696
  channelRef.extId,
54663
54697
  channelRef.ownerPrincipalId
54664
54698
  );
54665
- const liveDir = import_node_path44.default.join(deps.extensionsRoot, localExtId);
54699
+ const liveDir = import_node_path45.default.join(deps.extensionsRoot, localExtId);
54666
54700
  const prevDir = `${liveDir}.prev`;
54667
54701
  let existingVersion;
54668
54702
  try {
54669
- const raw = await import_promises7.default.readFile(import_node_path44.default.join(liveDir, "manifest.json"), "utf8");
54703
+ const raw = await import_promises7.default.readFile(import_node_path45.default.join(liveDir, "manifest.json"), "utf8");
54670
54704
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
54671
54705
  if (!parsed2.success) {
54672
54706
  throw new UpdateError(
@@ -54699,7 +54733,7 @@ async function updateFromChannel(args, deps) {
54699
54733
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
54700
54734
  }
54701
54735
  for (const name of Object.keys(zip.files)) {
54702
- if (name.includes("..") || name.startsWith("/") || import_node_path44.default.isAbsolute(name)) {
54736
+ if (name.includes("..") || name.startsWith("/") || import_node_path45.default.isAbsolute(name)) {
54703
54737
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
54704
54738
  }
54705
54739
  }
@@ -54734,16 +54768,16 @@ async function updateFromChannel(args, deps) {
54734
54768
  await import_promises7.default.rm(prevDir, { recursive: true, force: true });
54735
54769
  await import_promises7.default.rename(liveDir, prevDir);
54736
54770
  const stage = await import_promises7.default.mkdtemp(
54737
- import_node_path44.default.join(import_node_os19.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
54771
+ import_node_path45.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
54738
54772
  );
54739
54773
  try {
54740
54774
  for (const [name, entry] of Object.entries(zip.files)) {
54741
- const dest = import_node_path44.default.join(stage, name);
54775
+ const dest = import_node_path45.default.join(stage, name);
54742
54776
  if (entry.dir) {
54743
54777
  await import_promises7.default.mkdir(dest, { recursive: true });
54744
54778
  continue;
54745
54779
  }
54746
- await import_promises7.default.mkdir(import_node_path44.default.dirname(dest), { recursive: true });
54780
+ await import_promises7.default.mkdir(import_node_path45.default.dirname(dest), { recursive: true });
54747
54781
  if (name === "manifest.json") {
54748
54782
  const rewritten = { ...parsed.data, id: localExtId };
54749
54783
  await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -54836,7 +54870,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
54836
54870
  );
54837
54871
  }
54838
54872
  }
54839
- const manifestPath = import_node_path45.default.join(root, extId, "manifest.json");
54873
+ const manifestPath = import_node_path46.default.join(root, extId, "manifest.json");
54840
54874
  const manifest = await readManifest(root, extId);
54841
54875
  const next = { ...manifest, version: newVersion };
54842
54876
  const tmp = `${manifestPath}.tmp`;
@@ -54844,7 +54878,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
54844
54878
  await import_promises8.default.rename(tmp, manifestPath);
54845
54879
  }
54846
54880
  async function readManifest(root, extId) {
54847
- const file = import_node_path45.default.join(root, extId, "manifest.json");
54881
+ const file = import_node_path46.default.join(root, extId, "manifest.json");
54848
54882
  let raw;
54849
54883
  try {
54850
54884
  raw = await import_promises8.default.readFile(file, "utf8");
@@ -54935,7 +54969,7 @@ function buildExtensionHandlers(deps) {
54935
54969
  };
54936
54970
  async function buildSnapshotMeta(extId) {
54937
54971
  const manifest = await readManifest(deps.root, extId);
54938
- const { sha256, buffer } = await bundleExtensionDir(import_node_path45.default.join(deps.root, extId));
54972
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path46.default.join(deps.root, extId));
54939
54973
  return { manifest, contentHash: sha256, buffer };
54940
54974
  }
54941
54975
  const publish = async (frame, _client, ctx) => {
@@ -55118,7 +55152,7 @@ function buildExtensionHandlers(deps) {
55118
55152
  // src/app-builder/project-store.ts
55119
55153
  var import_node_fs39 = require("fs");
55120
55154
  var import_node_child_process11 = require("child_process");
55121
- var import_node_path46 = require("path");
55155
+ var import_node_path47 = require("path");
55122
55156
  init_protocol();
55123
55157
  var PROJECTS_DIR = "projects";
55124
55158
  var META_FILE = ".clawd-project.json";
@@ -55132,14 +55166,14 @@ var ProjectStore = class {
55132
55166
  root;
55133
55167
  /** projects/<name>/.clawd-project.json 路径 */
55134
55168
  metaPath(name) {
55135
- return (0, import_node_path46.join)(this.projectsRoot(), name, META_FILE);
55169
+ return (0, import_node_path47.join)(this.projectsRoot(), name, META_FILE);
55136
55170
  }
55137
55171
  /** projects/<name>/ 目录路径(cwd 用) */
55138
55172
  projectDir(name) {
55139
- return (0, import_node_path46.join)(this.projectsRoot(), name);
55173
+ return (0, import_node_path47.join)(this.projectsRoot(), name);
55140
55174
  }
55141
55175
  projectsRoot() {
55142
- return (0, import_node_path46.join)(this.root, PROJECTS_DIR);
55176
+ return (0, import_node_path47.join)(this.root, PROJECTS_DIR);
55143
55177
  }
55144
55178
  async list() {
55145
55179
  let entries;
@@ -55442,7 +55476,7 @@ var PublishJobRegistry = class {
55442
55476
  // src/app-builder/publish-job-runner.ts
55443
55477
  var import_node_child_process13 = require("child_process");
55444
55478
  var import_node_fs40 = require("fs");
55445
- var import_node_path47 = require("path");
55479
+ var import_node_path48 = require("path");
55446
55480
 
55447
55481
  // src/app-builder/publish-stage-parser.ts
55448
55482
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -55474,7 +55508,7 @@ async function startPublishJob(deps, args) {
55474
55508
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
55475
55509
  }
55476
55510
  const projDir = projectDir(args.name);
55477
- const logPath = (0, import_node_path47.join)(projDir, ".publish.log");
55511
+ const logPath = (0, import_node_path48.join)(projDir, ".publish.log");
55478
55512
  let logStream = null;
55479
55513
  try {
55480
55514
  logStream = (0, import_node_fs40.createWriteStream)(logPath, { flags: "w" });
@@ -55734,7 +55768,7 @@ async function recoverInterruptedJobs(deps) {
55734
55768
 
55735
55769
  // src/handlers/app-builder.ts
55736
55770
  init_protocol();
55737
- var import_node_path48 = require("path");
55771
+ var import_node_path49 = require("path");
55738
55772
  var import_node_fs41 = require("fs");
55739
55773
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
55740
55774
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
@@ -55892,8 +55926,8 @@ function buildAppBuilderHandlers(deps) {
55892
55926
  const project = await userStore.create(f.name, reservedPorts);
55893
55927
  try {
55894
55928
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
55895
- const templateSrcDir = (0, import_node_path48.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
55896
- const scaffoldScript = (0, import_node_path48.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
55929
+ const templateSrcDir = (0, import_node_path49.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
55930
+ const scaffoldScript = (0, import_node_path49.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
55897
55931
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
55898
55932
  deps.logger?.info("app-builder.scaffold.done", {
55899
55933
  name: project.name,
@@ -56114,7 +56148,7 @@ function buildAppBuilderHandlers(deps) {
56114
56148
  await userStore.clearPublishJob(args.name);
56115
56149
  }
56116
56150
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
56117
- const scriptPath = (0, import_node_path48.join)(deps.deployKitRoot, "scripts", "publish.sh");
56151
+ const scriptPath = (0, import_node_path49.join)(deps.deployKitRoot, "scripts", "publish.sh");
56118
56152
  deps.logger?.info("app-builder.publish.start", {
56119
56153
  name: args.name,
56120
56154
  sessionId: boundSession.sessionId,
@@ -56283,7 +56317,7 @@ function buildVisitorHandlers(deps) {
56283
56317
 
56284
56318
  // src/extension/registry.ts
56285
56319
  var import_promises9 = __toESM(require("fs/promises"), 1);
56286
- var import_node_path49 = __toESM(require("path"), 1);
56320
+ var import_node_path50 = __toESM(require("path"), 1);
56287
56321
  async function loadAll(root) {
56288
56322
  let entries;
56289
56323
  try {
@@ -56296,13 +56330,13 @@ async function loadAll(root) {
56296
56330
  for (const ent of entries) {
56297
56331
  if (!ent.isDirectory()) continue;
56298
56332
  if (ent.name.startsWith(".")) continue;
56299
- records.push(await loadOne(import_node_path49.default.join(root, ent.name), ent.name));
56333
+ records.push(await loadOne(import_node_path50.default.join(root, ent.name), ent.name));
56300
56334
  }
56301
56335
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
56302
56336
  return records;
56303
56337
  }
56304
56338
  async function loadOne(dir, dirName) {
56305
- const manifestPath = import_node_path49.default.join(dir, "manifest.json");
56339
+ const manifestPath = import_node_path50.default.join(dir, "manifest.json");
56306
56340
  let raw;
56307
56341
  try {
56308
56342
  raw = await import_promises9.default.readFile(manifestPath, "utf8");
@@ -56347,7 +56381,7 @@ async function loadOne(dir, dirName) {
56347
56381
 
56348
56382
  // src/extension/uninstall.ts
56349
56383
  var import_promises10 = __toESM(require("fs/promises"), 1);
56350
- var import_node_path50 = __toESM(require("path"), 1);
56384
+ var import_node_path51 = __toESM(require("path"), 1);
56351
56385
  var UninstallError = class extends Error {
56352
56386
  constructor(code, message) {
56353
56387
  super(message);
@@ -56356,7 +56390,7 @@ var UninstallError = class extends Error {
56356
56390
  code;
56357
56391
  };
56358
56392
  async function uninstall(deps) {
56359
- const dir = import_node_path50.default.join(deps.root, deps.extId);
56393
+ const dir = import_node_path51.default.join(deps.root, deps.extId);
56360
56394
  try {
56361
56395
  await import_promises10.default.access(dir);
56362
56396
  } catch {
@@ -56925,7 +56959,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
56925
56959
 
56926
56960
  // src/extension/runtime.ts
56927
56961
  var import_node_child_process15 = require("child_process");
56928
- var import_node_path51 = __toESM(require("path"), 1);
56962
+ var import_node_path52 = __toESM(require("path"), 1);
56929
56963
  var import_promises11 = require("timers/promises");
56930
56964
 
56931
56965
  // src/extension/port-allocator.ts
@@ -57026,7 +57060,7 @@ var Runtime = class {
57026
57060
  /\$CLAWOS_EXT_PORT/g,
57027
57061
  String(port)
57028
57062
  );
57029
- const dir = import_node_path51.default.join(this.root, extId);
57063
+ const dir = import_node_path52.default.join(this.root, extId);
57030
57064
  const env = {
57031
57065
  ...process.env,
57032
57066
  CLAWOS_EXT_PORT: String(port),
@@ -57138,7 +57172,7 @@ ${handle.stderrTail}`
57138
57172
 
57139
57173
  // src/extension/published-channels.ts
57140
57174
  var import_promises12 = __toESM(require("fs/promises"), 1);
57141
- var import_node_path52 = __toESM(require("path"), 1);
57175
+ var import_node_path53 = __toESM(require("path"), 1);
57142
57176
  init_zod();
57143
57177
  var PublishedChannelsError = class extends Error {
57144
57178
  constructor(code, message) {
@@ -57237,7 +57271,7 @@ var PublishedChannelStore = class {
57237
57271
  )
57238
57272
  };
57239
57273
  const tmp = `${this.filePath}.tmp`;
57240
- await import_promises12.default.mkdir(import_node_path52.default.dirname(this.filePath), { recursive: true });
57274
+ await import_promises12.default.mkdir(import_node_path53.default.dirname(this.filePath), { recursive: true });
57241
57275
  await import_promises12.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
57242
57276
  await import_promises12.default.rename(tmp, this.filePath);
57243
57277
  }
@@ -57245,7 +57279,7 @@ var PublishedChannelStore = class {
57245
57279
 
57246
57280
  // src/extension/bundle-cache.ts
57247
57281
  var import_promises13 = __toESM(require("fs/promises"), 1);
57248
- var import_node_path53 = __toESM(require("path"), 1);
57282
+ var import_node_path54 = __toESM(require("path"), 1);
57249
57283
  var BundleCache = class {
57250
57284
  constructor(rootDir) {
57251
57285
  this.rootDir = rootDir;
@@ -57254,14 +57288,14 @@ var BundleCache = class {
57254
57288
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
57255
57289
  async write(snapshotHash, buffer) {
57256
57290
  await import_promises13.default.mkdir(this.rootDir, { recursive: true });
57257
- const file = import_node_path53.default.join(this.rootDir, `${snapshotHash}.zip`);
57291
+ const file = import_node_path54.default.join(this.rootDir, `${snapshotHash}.zip`);
57258
57292
  const tmp = `${file}.tmp`;
57259
57293
  await import_promises13.default.writeFile(tmp, buffer, { mode: 384 });
57260
57294
  await import_promises13.default.rename(tmp, file);
57261
57295
  }
57262
57296
  /** Returns the bundle bytes, or null when the file doesn't exist. */
57263
57297
  async read(snapshotHash) {
57264
- const file = import_node_path53.default.join(this.rootDir, `${snapshotHash}.zip`);
57298
+ const file = import_node_path54.default.join(this.rootDir, `${snapshotHash}.zip`);
57265
57299
  try {
57266
57300
  return await import_promises13.default.readFile(file);
57267
57301
  } catch (e) {
@@ -57271,7 +57305,7 @@ var BundleCache = class {
57271
57305
  }
57272
57306
  /** Idempotent — missing file is not an error. */
57273
57307
  async delete(snapshotHash) {
57274
- const file = import_node_path53.default.join(this.rootDir, `${snapshotHash}.zip`);
57308
+ const file = import_node_path54.default.join(this.rootDir, `${snapshotHash}.zip`);
57275
57309
  await import_promises13.default.rm(file, { force: true });
57276
57310
  }
57277
57311
  };
@@ -57292,11 +57326,11 @@ async function startDaemon(config) {
57292
57326
  },
57293
57327
  source: "daemon",
57294
57328
  sampling: logShippingCfg.sampling,
57295
- homeDir: import_node_os20.default.homedir()
57329
+ homeDir: import_node_os21.default.homedir()
57296
57330
  });
57297
57331
  const logger = createLogger({
57298
57332
  level: config.logLevel,
57299
- file: import_node_path54.default.join(config.dataDir, "clawd.log"),
57333
+ file: import_node_path55.default.join(config.dataDir, "clawd.log"),
57300
57334
  logClient
57301
57335
  });
57302
57336
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
@@ -57436,8 +57470,8 @@ async function startDaemon(config) {
57436
57470
  const agents = new AgentsScanner();
57437
57471
  const history = new ClaudeHistoryReader();
57438
57472
  let transport = null;
57439
- const personaStore = new PersonaStore(import_node_path54.default.join(config.dataDir, "personas"));
57440
- const usersRoot = import_node_path54.default.join(config.dataDir, "users");
57473
+ const personaStore = new PersonaStore(import_node_path55.default.join(config.dataDir, "personas"));
57474
+ const usersRoot = import_node_path55.default.join(config.dataDir, "users");
57441
57475
  const defaultsRoot = findDefaultsRoot(logger);
57442
57476
  if (defaultsRoot) {
57443
57477
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -57457,17 +57491,17 @@ async function startDaemon(config) {
57457
57491
  migrateCodexSandbox({ store: personaStore, logger });
57458
57492
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
57459
57493
  const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
57460
- const here = typeof __dirname === "string" ? __dirname : import_node_path54.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
57494
+ const here = typeof __dirname === "string" ? __dirname : import_node_path55.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
57461
57495
  const dispatchServerCandidates = [
57462
- import_node_path54.default.join(here, "dispatch", "mcp-server.cjs"),
57496
+ import_node_path55.default.join(here, "dispatch", "mcp-server.cjs"),
57463
57497
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
57464
- import_node_path54.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
57498
+ import_node_path55.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
57465
57499
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
57466
57500
  ];
57467
57501
  const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs42.default.existsSync(p2));
57468
57502
  let dispatchMcpConfigPath2;
57469
57503
  if (dispatchServerScriptPath) {
57470
- const dispatchLogPath = import_node_path54.default.join(config.dataDir, "dispatch-mcp-server.log");
57504
+ const dispatchLogPath = import_node_path55.default.join(config.dataDir, "dispatch-mcp-server.log");
57471
57505
  dispatchMcpConfigPath2 = writeDispatchMcpConfig({
57472
57506
  dataDir: config.dataDir,
57473
57507
  serverScriptPath: dispatchServerScriptPath,
@@ -57484,15 +57518,15 @@ async function startDaemon(config) {
57484
57518
  });
57485
57519
  }
57486
57520
  const ticketServerCandidates = [
57487
- import_node_path54.default.join(here, "ticket", "mcp-server.cjs"),
57488
- import_node_path54.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
57521
+ import_node_path55.default.join(here, "ticket", "mcp-server.cjs"),
57522
+ import_node_path55.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
57489
57523
  ];
57490
57524
  const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs42.default.existsSync(p2));
57491
57525
  const ticketOwnerUnionId = feishuIdentity?.identity.unionId ?? "";
57492
57526
  const ticketOwnerName = feishuIdentity?.identity.displayName ?? "";
57493
57527
  let ticketMcpConfigPath2;
57494
57528
  if (ticketServerScriptPath && ticketOwnerUnionId) {
57495
- const ticketLogPath = import_node_path54.default.join(config.dataDir, "ticket-mcp-server.log");
57529
+ const ticketLogPath = import_node_path55.default.join(config.dataDir, "ticket-mcp-server.log");
57496
57530
  ticketMcpConfigPath2 = writeTicketMcpConfig({
57497
57531
  dataDir: config.dataDir,
57498
57532
  serverScriptPath: ticketServerScriptPath,
@@ -57513,13 +57547,13 @@ async function startDaemon(config) {
57513
57547
  });
57514
57548
  }
57515
57549
  const shiftServerCandidates = [
57516
- import_node_path54.default.join(here, "shift", "mcp-server.cjs"),
57517
- import_node_path54.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
57550
+ import_node_path55.default.join(here, "shift", "mcp-server.cjs"),
57551
+ import_node_path55.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
57518
57552
  ];
57519
57553
  const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs42.default.existsSync(p2));
57520
57554
  let shiftMcpConfigPath2;
57521
57555
  if (shiftServerScriptPath) {
57522
- const shiftLogPath = import_node_path54.default.join(config.dataDir, "shift-mcp-server.log");
57556
+ const shiftLogPath = import_node_path55.default.join(config.dataDir, "shift-mcp-server.log");
57523
57557
  shiftMcpConfigPath2 = await writeShiftMcpConfig({
57524
57558
  dataDir: config.dataDir,
57525
57559
  serverScriptPath: shiftServerScriptPath,
@@ -57537,19 +57571,22 @@ async function startDaemon(config) {
57537
57571
  );
57538
57572
  }
57539
57573
  const inboxServerCandidates = [
57540
- import_node_path54.default.join(here, "inbox", "mcp-server.cjs"),
57541
- import_node_path54.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
57574
+ import_node_path55.default.join(here, "inbox", "mcp-server.cjs"),
57575
+ import_node_path55.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
57542
57576
  ];
57543
57577
  const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs42.default.existsSync(p2));
57544
57578
  let inboxMcpConfigPath2;
57545
57579
  if (inboxServerScriptPath) {
57580
+ const inboxLogPath = import_node_path55.default.join(config.dataDir, "inbox-mcp-server.log");
57546
57581
  inboxMcpConfigPath2 = await writeInboxMcpConfig({
57547
57582
  dataDir: config.dataDir,
57548
- serverScriptPath: inboxServerScriptPath
57583
+ serverScriptPath: inboxServerScriptPath,
57584
+ logPath: inboxLogPath
57549
57585
  });
57550
57586
  logger.info("inbox.mcp.json written", {
57551
57587
  path: inboxMcpConfigPath2,
57552
- server: inboxServerScriptPath
57588
+ server: inboxServerScriptPath,
57589
+ serverLog: inboxLogPath
57553
57590
  });
57554
57591
  } else {
57555
57592
  logger.warn(
@@ -57558,7 +57595,7 @@ async function startDaemon(config) {
57558
57595
  );
57559
57596
  }
57560
57597
  const shiftStore = createShiftStore({
57561
- filePath: import_node_path54.default.join(config.dataDir, "shift.json"),
57598
+ filePath: import_node_path55.default.join(config.dataDir, "shift.json"),
57562
57599
  ownerIdProvider: () => ownerPrincipalId,
57563
57600
  now: () => Date.now()
57564
57601
  });
@@ -57576,7 +57613,7 @@ async function startDaemon(config) {
57576
57613
  getAdapter,
57577
57614
  historyReader: history,
57578
57615
  dataDir: config.dataDir,
57579
- personaRoot: import_node_path54.default.join(config.dataDir, "personas"),
57616
+ personaRoot: import_node_path55.default.join(config.dataDir, "personas"),
57580
57617
  usersRoot,
57581
57618
  personaStore,
57582
57619
  ownerDisplayName,
@@ -57619,7 +57656,7 @@ async function startDaemon(config) {
57619
57656
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
57620
57657
  attachmentGroup: {
57621
57658
  onFileEdit: (input) => {
57622
- const absPath = import_node_path54.default.isAbsolute(input.relPath) ? input.relPath : import_node_path54.default.join(input.cwd, input.relPath);
57659
+ const absPath = import_node_path55.default.isAbsolute(input.relPath) ? input.relPath : import_node_path55.default.join(input.cwd, input.relPath);
57623
57660
  let size = 0;
57624
57661
  try {
57625
57662
  size = import_node_fs42.default.statSync(absPath).size;
@@ -57820,11 +57857,11 @@ async function startDaemon(config) {
57820
57857
  // 'persona/<pid>/owner',default 走 'default'。
57821
57858
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
57822
57859
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
57823
- personaRoot: import_node_path54.default.join(config.dataDir, "personas"),
57860
+ personaRoot: import_node_path55.default.join(config.dataDir, "personas"),
57824
57861
  usersRoot
57825
57862
  },
57826
57863
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
57827
- personaRoot: import_node_path54.default.join(config.dataDir, "personas"),
57864
+ personaRoot: import_node_path55.default.join(config.dataDir, "personas"),
57828
57865
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
57829
57866
  usersRoot,
57830
57867
  // capability:list / delete handler 依赖
@@ -57933,11 +57970,11 @@ async function startDaemon(config) {
57933
57970
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
57934
57971
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
57935
57972
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
57936
- appBuilderPersonaRoot: import_node_path54.default.join(config.dataDir, "personas", "persona-app-builder"),
57973
+ appBuilderPersonaRoot: import_node_path55.default.join(config.dataDir, "personas", "persona-app-builder"),
57937
57974
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
57938
- deployKitRoot: import_node_path54.default.join(config.dataDir, "deploy-kit"),
57975
+ deployKitRoot: import_node_path55.default.join(config.dataDir, "deploy-kit"),
57939
57976
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
57940
- resolvePersonaRoot: (personaId) => import_node_path54.default.join(config.dataDir, "personas", personaId),
57977
+ resolvePersonaRoot: (personaId) => import_node_path55.default.join(config.dataDir, "personas", personaId),
57941
57978
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
57942
57979
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
57943
57980
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -57980,8 +58017,8 @@ async function startDaemon(config) {
57980
58017
  }
57981
58018
  let sourceJsonlPath = "(no transcript yet \u2014 operate from the task description alone)";
57982
58019
  if (sourceFile && sourceFile.toolSessionId) {
57983
- sourceJsonlPath = import_node_path54.default.join(
57984
- import_node_os20.default.homedir(),
58020
+ sourceJsonlPath = import_node_path55.default.join(
58021
+ import_node_os21.default.homedir(),
57985
58022
  ".claude",
57986
58023
  "projects",
57987
58024
  cwdToHashDir(sourceFile.cwd),
@@ -58280,8 +58317,8 @@ async function startDaemon(config) {
58280
58317
  const lines = [
58281
58318
  `Tunnel: ${r.url}`,
58282
58319
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
58283
- `Frpc config: ${import_node_path54.default.join(config.dataDir, "frpc.toml")}`,
58284
- `Frpc log: ${import_node_path54.default.join(config.dataDir, "frpc.log")}`
58320
+ `Frpc config: ${import_node_path55.default.join(config.dataDir, "frpc.toml")}`,
58321
+ `Frpc log: ${import_node_path55.default.join(config.dataDir, "frpc.log")}`
58285
58322
  ];
58286
58323
  const width = Math.max(...lines.map((l) => l.length));
58287
58324
  const bar = "\u2550".repeat(width + 4);
@@ -58294,7 +58331,7 @@ ${bar}
58294
58331
 
58295
58332
  `);
58296
58333
  try {
58297
- const connectPath = import_node_path54.default.join(config.dataDir, "connect.txt");
58334
+ const connectPath = import_node_path55.default.join(config.dataDir, "connect.txt");
58298
58335
  import_node_fs42.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
58299
58336
  } catch {
58300
58337
  }
@@ -58367,7 +58404,7 @@ ${bar}
58367
58404
  };
58368
58405
  }
58369
58406
  function migrateDropPersonsDir(dataDir) {
58370
- const dir = import_node_path54.default.join(dataDir, "persons");
58407
+ const dir = import_node_path55.default.join(dataDir, "persons");
58371
58408
  try {
58372
58409
  import_node_fs42.default.rmSync(dir, { recursive: true, force: true });
58373
58410
  } catch {