@clawos-dev/clawd 0.2.53-beta.84.b617e1e → 0.2.53

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
@@ -597,8 +597,8 @@ var init_parseUtil = __esm({
597
597
  init_errors2();
598
598
  init_en();
599
599
  makeIssue = (params) => {
600
- const { data, path: path24, errorMaps, issueData } = params;
601
- const fullPath = [...path24, ...issueData.path || []];
600
+ const { data, path: path27, errorMaps, issueData } = params;
601
+ const fullPath = [...path27, ...issueData.path || []];
602
602
  const fullIssue = {
603
603
  ...issueData,
604
604
  path: fullPath
@@ -909,11 +909,11 @@ var init_types = __esm({
909
909
  init_parseUtil();
910
910
  init_util();
911
911
  ParseInputLazyPath = class {
912
- constructor(parent, value, path24, key) {
912
+ constructor(parent, value, path27, key) {
913
913
  this._cachedPath = [];
914
914
  this.parent = parent;
915
915
  this.data = value;
916
- this._path = path24;
916
+ this._path = path27;
917
917
  this._key = key;
918
918
  }
919
919
  get path() {
@@ -5223,8 +5223,8 @@ var require_req = __commonJS({
5223
5223
  if (req.originalUrl) {
5224
5224
  _req.url = req.originalUrl;
5225
5225
  } else {
5226
- const path24 = req.path;
5227
- _req.url = typeof path24 === "string" ? path24 : req.url ? req.url.path || req.url : void 0;
5226
+ const path27 = req.path;
5227
+ _req.url = typeof path27 === "string" ? path27 : req.url ? req.url.path || req.url : void 0;
5228
5228
  }
5229
5229
  if (req.query) {
5230
5230
  _req.query = req.query;
@@ -5389,14 +5389,14 @@ var require_redact = __commonJS({
5389
5389
  }
5390
5390
  return obj;
5391
5391
  }
5392
- function parsePath(path24) {
5392
+ function parsePath(path27) {
5393
5393
  const parts = [];
5394
5394
  let current = "";
5395
5395
  let inBrackets = false;
5396
5396
  let inQuotes = false;
5397
5397
  let quoteChar = "";
5398
- for (let i = 0; i < path24.length; i++) {
5399
- const char = path24[i];
5398
+ for (let i = 0; i < path27.length; i++) {
5399
+ const char = path27[i];
5400
5400
  if (!inBrackets && char === ".") {
5401
5401
  if (current) {
5402
5402
  parts.push(current);
@@ -5527,10 +5527,10 @@ var require_redact = __commonJS({
5527
5527
  return current;
5528
5528
  }
5529
5529
  function redactPaths(obj, paths, censor, remove = false) {
5530
- for (const path24 of paths) {
5531
- const parts = parsePath(path24);
5530
+ for (const path27 of paths) {
5531
+ const parts = parsePath(path27);
5532
5532
  if (parts.includes("*")) {
5533
- redactWildcardPath(obj, parts, censor, path24, remove);
5533
+ redactWildcardPath(obj, parts, censor, path27, remove);
5534
5534
  } else {
5535
5535
  if (remove) {
5536
5536
  removeKey(obj, parts);
@@ -5615,8 +5615,8 @@ var require_redact = __commonJS({
5615
5615
  }
5616
5616
  } else {
5617
5617
  if (afterWildcard.includes("*")) {
5618
- const wrappedCensor = typeof censor === "function" ? (value, path24) => {
5619
- const fullPath = [...pathArray.slice(0, pathLength), ...path24];
5618
+ const wrappedCensor = typeof censor === "function" ? (value, path27) => {
5619
+ const fullPath = [...pathArray.slice(0, pathLength), ...path27];
5620
5620
  return censor(value, fullPath);
5621
5621
  } : censor;
5622
5622
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -5651,8 +5651,8 @@ var require_redact = __commonJS({
5651
5651
  return null;
5652
5652
  }
5653
5653
  const pathStructure = /* @__PURE__ */ new Map();
5654
- for (const path24 of pathsToClone) {
5655
- const parts = parsePath(path24);
5654
+ for (const path27 of pathsToClone) {
5655
+ const parts = parsePath(path27);
5656
5656
  let current = pathStructure;
5657
5657
  for (let i = 0; i < parts.length; i++) {
5658
5658
  const part = parts[i];
@@ -5704,24 +5704,24 @@ var require_redact = __commonJS({
5704
5704
  }
5705
5705
  return cloneSelectively(obj, pathStructure);
5706
5706
  }
5707
- function validatePath(path24) {
5708
- if (typeof path24 !== "string") {
5707
+ function validatePath(path27) {
5708
+ if (typeof path27 !== "string") {
5709
5709
  throw new Error("Paths must be (non-empty) strings");
5710
5710
  }
5711
- if (path24 === "") {
5711
+ if (path27 === "") {
5712
5712
  throw new Error("Invalid redaction path ()");
5713
5713
  }
5714
- if (path24.includes("..")) {
5715
- throw new Error(`Invalid redaction path (${path24})`);
5714
+ if (path27.includes("..")) {
5715
+ throw new Error(`Invalid redaction path (${path27})`);
5716
5716
  }
5717
- if (path24.includes(",")) {
5718
- throw new Error(`Invalid redaction path (${path24})`);
5717
+ if (path27.includes(",")) {
5718
+ throw new Error(`Invalid redaction path (${path27})`);
5719
5719
  }
5720
5720
  let bracketCount = 0;
5721
5721
  let inQuotes = false;
5722
5722
  let quoteChar = "";
5723
- for (let i = 0; i < path24.length; i++) {
5724
- const char = path24[i];
5723
+ for (let i = 0; i < path27.length; i++) {
5724
+ const char = path27[i];
5725
5725
  if ((char === '"' || char === "'") && bracketCount > 0) {
5726
5726
  if (!inQuotes) {
5727
5727
  inQuotes = true;
@@ -5735,20 +5735,20 @@ var require_redact = __commonJS({
5735
5735
  } else if (char === "]" && !inQuotes) {
5736
5736
  bracketCount--;
5737
5737
  if (bracketCount < 0) {
5738
- throw new Error(`Invalid redaction path (${path24})`);
5738
+ throw new Error(`Invalid redaction path (${path27})`);
5739
5739
  }
5740
5740
  }
5741
5741
  }
5742
5742
  if (bracketCount !== 0) {
5743
- throw new Error(`Invalid redaction path (${path24})`);
5743
+ throw new Error(`Invalid redaction path (${path27})`);
5744
5744
  }
5745
5745
  }
5746
5746
  function validatePaths(paths) {
5747
5747
  if (!Array.isArray(paths)) {
5748
5748
  throw new TypeError("paths must be an array");
5749
5749
  }
5750
- for (const path24 of paths) {
5751
- validatePath(path24);
5750
+ for (const path27 of paths) {
5751
+ validatePath(path27);
5752
5752
  }
5753
5753
  }
5754
5754
  function slowRedact(options = {}) {
@@ -5916,8 +5916,8 @@ var require_redaction = __commonJS({
5916
5916
  if (shape[k] === null) {
5917
5917
  o[k] = (value) => topCensor(value, [k]);
5918
5918
  } else {
5919
- const wrappedCensor = typeof censor === "function" ? (value, path24) => {
5920
- return censor(value, [k, ...path24]);
5919
+ const wrappedCensor = typeof censor === "function" ? (value, path27) => {
5920
+ return censor(value, [k, ...path27]);
5921
5921
  } : censor;
5922
5922
  o[k] = Redact({
5923
5923
  paths: shape[k],
@@ -6135,10 +6135,10 @@ var require_atomic_sleep = __commonJS({
6135
6135
  var require_sonic_boom = __commonJS({
6136
6136
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
6137
6137
  "use strict";
6138
- var fs23 = require("fs");
6138
+ var fs25 = require("fs");
6139
6139
  var EventEmitter2 = require("events");
6140
6140
  var inherits = require("util").inherits;
6141
- var path24 = require("path");
6141
+ var path27 = require("path");
6142
6142
  var sleep = require_atomic_sleep();
6143
6143
  var assert = require("assert");
6144
6144
  var BUSY_WRITE_TIMEOUT = 100;
@@ -6192,20 +6192,20 @@ var require_sonic_boom = __commonJS({
6192
6192
  const mode = sonic.mode;
6193
6193
  if (sonic.sync) {
6194
6194
  try {
6195
- if (sonic.mkdir) fs23.mkdirSync(path24.dirname(file), { recursive: true });
6196
- const fd = fs23.openSync(file, flags, mode);
6195
+ if (sonic.mkdir) fs25.mkdirSync(path27.dirname(file), { recursive: true });
6196
+ const fd = fs25.openSync(file, flags, mode);
6197
6197
  fileOpened(null, fd);
6198
6198
  } catch (err) {
6199
6199
  fileOpened(err);
6200
6200
  throw err;
6201
6201
  }
6202
6202
  } else if (sonic.mkdir) {
6203
- fs23.mkdir(path24.dirname(file), { recursive: true }, (err) => {
6203
+ fs25.mkdir(path27.dirname(file), { recursive: true }, (err) => {
6204
6204
  if (err) return fileOpened(err);
6205
- fs23.open(file, flags, mode, fileOpened);
6205
+ fs25.open(file, flags, mode, fileOpened);
6206
6206
  });
6207
6207
  } else {
6208
- fs23.open(file, flags, mode, fileOpened);
6208
+ fs25.open(file, flags, mode, fileOpened);
6209
6209
  }
6210
6210
  }
6211
6211
  function SonicBoom(opts) {
@@ -6246,8 +6246,8 @@ var require_sonic_boom = __commonJS({
6246
6246
  this.flush = flushBuffer;
6247
6247
  this.flushSync = flushBufferSync;
6248
6248
  this._actualWrite = actualWriteBuffer;
6249
- fsWriteSync = () => fs23.writeSync(this.fd, this._writingBuf);
6250
- fsWrite = () => fs23.write(this.fd, this._writingBuf, this.release);
6249
+ fsWriteSync = () => fs25.writeSync(this.fd, this._writingBuf);
6250
+ fsWrite = () => fs25.write(this.fd, this._writingBuf, this.release);
6251
6251
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
6252
6252
  this._writingBuf = "";
6253
6253
  this.write = write;
@@ -6256,15 +6256,15 @@ var require_sonic_boom = __commonJS({
6256
6256
  this._actualWrite = actualWrite;
6257
6257
  fsWriteSync = () => {
6258
6258
  if (Buffer.isBuffer(this._writingBuf)) {
6259
- return fs23.writeSync(this.fd, this._writingBuf);
6259
+ return fs25.writeSync(this.fd, this._writingBuf);
6260
6260
  }
6261
- return fs23.writeSync(this.fd, this._writingBuf, "utf8");
6261
+ return fs25.writeSync(this.fd, this._writingBuf, "utf8");
6262
6262
  };
6263
6263
  fsWrite = () => {
6264
6264
  if (Buffer.isBuffer(this._writingBuf)) {
6265
- return fs23.write(this.fd, this._writingBuf, this.release);
6265
+ return fs25.write(this.fd, this._writingBuf, this.release);
6266
6266
  }
6267
- return fs23.write(this.fd, this._writingBuf, "utf8", this.release);
6267
+ return fs25.write(this.fd, this._writingBuf, "utf8", this.release);
6268
6268
  };
6269
6269
  } else {
6270
6270
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -6321,7 +6321,7 @@ var require_sonic_boom = __commonJS({
6321
6321
  }
6322
6322
  }
6323
6323
  if (this._fsync) {
6324
- fs23.fsyncSync(this.fd);
6324
+ fs25.fsyncSync(this.fd);
6325
6325
  }
6326
6326
  const len = this._len;
6327
6327
  if (this._reopening) {
@@ -6435,7 +6435,7 @@ var require_sonic_boom = __commonJS({
6435
6435
  const onDrain = () => {
6436
6436
  if (!this._fsync) {
6437
6437
  try {
6438
- fs23.fsync(this.fd, (err) => {
6438
+ fs25.fsync(this.fd, (err) => {
6439
6439
  this._flushPending = false;
6440
6440
  cb(err);
6441
6441
  });
@@ -6537,7 +6537,7 @@ var require_sonic_boom = __commonJS({
6537
6537
  const fd = this.fd;
6538
6538
  this.once("ready", () => {
6539
6539
  if (fd !== this.fd) {
6540
- fs23.close(fd, (err) => {
6540
+ fs25.close(fd, (err) => {
6541
6541
  if (err) {
6542
6542
  return this.emit("error", err);
6543
6543
  }
@@ -6586,7 +6586,7 @@ var require_sonic_boom = __commonJS({
6586
6586
  buf = this._bufs[0];
6587
6587
  }
6588
6588
  try {
6589
- const n = Buffer.isBuffer(buf) ? fs23.writeSync(this.fd, buf) : fs23.writeSync(this.fd, buf, "utf8");
6589
+ const n = Buffer.isBuffer(buf) ? fs25.writeSync(this.fd, buf) : fs25.writeSync(this.fd, buf, "utf8");
6590
6590
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
6591
6591
  buf = releasedBufObj.writingBuf;
6592
6592
  this._len = releasedBufObj.len;
@@ -6602,7 +6602,7 @@ var require_sonic_boom = __commonJS({
6602
6602
  }
6603
6603
  }
6604
6604
  try {
6605
- fs23.fsyncSync(this.fd);
6605
+ fs25.fsyncSync(this.fd);
6606
6606
  } catch {
6607
6607
  }
6608
6608
  }
@@ -6623,7 +6623,7 @@ var require_sonic_boom = __commonJS({
6623
6623
  buf = mergeBuf(this._bufs[0], this._lens[0]);
6624
6624
  }
6625
6625
  try {
6626
- const n = fs23.writeSync(this.fd, buf);
6626
+ const n = fs25.writeSync(this.fd, buf);
6627
6627
  buf = buf.subarray(n);
6628
6628
  this._len = Math.max(this._len - n, 0);
6629
6629
  if (buf.length <= 0) {
@@ -6651,13 +6651,13 @@ var require_sonic_boom = __commonJS({
6651
6651
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
6652
6652
  if (this.sync) {
6653
6653
  try {
6654
- const written = Buffer.isBuffer(this._writingBuf) ? fs23.writeSync(this.fd, this._writingBuf) : fs23.writeSync(this.fd, this._writingBuf, "utf8");
6654
+ const written = Buffer.isBuffer(this._writingBuf) ? fs25.writeSync(this.fd, this._writingBuf) : fs25.writeSync(this.fd, this._writingBuf, "utf8");
6655
6655
  release(null, written);
6656
6656
  } catch (err) {
6657
6657
  release(err);
6658
6658
  }
6659
6659
  } else {
6660
- fs23.write(this.fd, this._writingBuf, release);
6660
+ fs25.write(this.fd, this._writingBuf, release);
6661
6661
  }
6662
6662
  }
6663
6663
  function actualWriteBuffer() {
@@ -6666,7 +6666,7 @@ var require_sonic_boom = __commonJS({
6666
6666
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
6667
6667
  if (this.sync) {
6668
6668
  try {
6669
- const written = fs23.writeSync(this.fd, this._writingBuf);
6669
+ const written = fs25.writeSync(this.fd, this._writingBuf);
6670
6670
  release(null, written);
6671
6671
  } catch (err) {
6672
6672
  release(err);
@@ -6675,7 +6675,7 @@ var require_sonic_boom = __commonJS({
6675
6675
  if (kCopyBuffer) {
6676
6676
  this._writingBuf = Buffer.from(this._writingBuf);
6677
6677
  }
6678
- fs23.write(this.fd, this._writingBuf, release);
6678
+ fs25.write(this.fd, this._writingBuf, release);
6679
6679
  }
6680
6680
  }
6681
6681
  function actualClose(sonic) {
@@ -6691,12 +6691,12 @@ var require_sonic_boom = __commonJS({
6691
6691
  sonic._lens = [];
6692
6692
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
6693
6693
  try {
6694
- fs23.fsync(sonic.fd, closeWrapped);
6694
+ fs25.fsync(sonic.fd, closeWrapped);
6695
6695
  } catch {
6696
6696
  }
6697
6697
  function closeWrapped() {
6698
6698
  if (sonic.fd !== 1 && sonic.fd !== 2) {
6699
- fs23.close(sonic.fd, done);
6699
+ fs25.close(sonic.fd, done);
6700
6700
  } else {
6701
6701
  done();
6702
6702
  }
@@ -6953,7 +6953,7 @@ var require_thread_stream = __commonJS({
6953
6953
  var { version: version2 } = require_package();
6954
6954
  var { EventEmitter: EventEmitter2 } = require("events");
6955
6955
  var { Worker } = require("worker_threads");
6956
- var { join: join3 } = require("path");
6956
+ var { join: join4 } = require("path");
6957
6957
  var { pathToFileURL } = require("url");
6958
6958
  var { wait } = require_wait();
6959
6959
  var {
@@ -6989,7 +6989,7 @@ var require_thread_stream = __commonJS({
6989
6989
  function createWorker(stream, opts) {
6990
6990
  const { filename, workerData } = opts;
6991
6991
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
6992
- const toExecute = bundlerOverrides["thread-stream-worker"] || join3(__dirname, "lib", "worker.js");
6992
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join4(__dirname, "lib", "worker.js");
6993
6993
  const worker = new Worker(toExecute, {
6994
6994
  ...opts.workerOpts,
6995
6995
  trackUnmanagedFds: false,
@@ -7375,7 +7375,7 @@ var require_transport = __commonJS({
7375
7375
  "use strict";
7376
7376
  var { createRequire } = require("module");
7377
7377
  var getCallers = require_caller();
7378
- var { join: join3, isAbsolute, sep } = require("path");
7378
+ var { join: join4, isAbsolute, sep } = require("path");
7379
7379
  var sleep = require_atomic_sleep();
7380
7380
  var onExit = require_on_exit_leak_free();
7381
7381
  var ThreadStream = require_thread_stream();
@@ -7438,7 +7438,7 @@ var require_transport = __commonJS({
7438
7438
  throw new Error("only one of target or targets can be specified");
7439
7439
  }
7440
7440
  if (targets) {
7441
- target = bundlerOverrides["pino-worker"] || join3(__dirname, "worker.js");
7441
+ target = bundlerOverrides["pino-worker"] || join4(__dirname, "worker.js");
7442
7442
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
7443
7443
  return {
7444
7444
  ...dest,
@@ -7456,7 +7456,7 @@ var require_transport = __commonJS({
7456
7456
  });
7457
7457
  });
7458
7458
  } else if (pipeline2) {
7459
- target = bundlerOverrides["pino-worker"] || join3(__dirname, "worker.js");
7459
+ target = bundlerOverrides["pino-worker"] || join4(__dirname, "worker.js");
7460
7460
  options.pipelines = [pipeline2.map((dest) => {
7461
7461
  return {
7462
7462
  ...dest,
@@ -7478,7 +7478,7 @@ var require_transport = __commonJS({
7478
7478
  return origin;
7479
7479
  }
7480
7480
  if (origin === "pino/file") {
7481
- return join3(__dirname, "..", "file.js");
7481
+ return join4(__dirname, "..", "file.js");
7482
7482
  }
7483
7483
  let fixTarget2;
7484
7484
  for (const filePath of callers) {
@@ -8468,7 +8468,7 @@ var require_safe_stable_stringify = __commonJS({
8468
8468
  return circularValue;
8469
8469
  }
8470
8470
  let res = "";
8471
- let join3 = ",";
8471
+ let join4 = ",";
8472
8472
  const originalIndentation = indentation;
8473
8473
  if (Array.isArray(value)) {
8474
8474
  if (value.length === 0) {
@@ -8482,7 +8482,7 @@ var require_safe_stable_stringify = __commonJS({
8482
8482
  indentation += spacer;
8483
8483
  res += `
8484
8484
  ${indentation}`;
8485
- join3 = `,
8485
+ join4 = `,
8486
8486
  ${indentation}`;
8487
8487
  }
8488
8488
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -8490,13 +8490,13 @@ ${indentation}`;
8490
8490
  for (; i < maximumValuesToStringify - 1; i++) {
8491
8491
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
8492
8492
  res += tmp2 !== void 0 ? tmp2 : "null";
8493
- res += join3;
8493
+ res += join4;
8494
8494
  }
8495
8495
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
8496
8496
  res += tmp !== void 0 ? tmp : "null";
8497
8497
  if (value.length - 1 > maximumBreadth) {
8498
8498
  const removedKeys = value.length - maximumBreadth - 1;
8499
- res += `${join3}"... ${getItemCount(removedKeys)} not stringified"`;
8499
+ res += `${join4}"... ${getItemCount(removedKeys)} not stringified"`;
8500
8500
  }
8501
8501
  if (spacer !== "") {
8502
8502
  res += `
@@ -8517,7 +8517,7 @@ ${originalIndentation}`;
8517
8517
  let separator = "";
8518
8518
  if (spacer !== "") {
8519
8519
  indentation += spacer;
8520
- join3 = `,
8520
+ join4 = `,
8521
8521
  ${indentation}`;
8522
8522
  whitespace = " ";
8523
8523
  }
@@ -8531,13 +8531,13 @@ ${indentation}`;
8531
8531
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
8532
8532
  if (tmp !== void 0) {
8533
8533
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
8534
- separator = join3;
8534
+ separator = join4;
8535
8535
  }
8536
8536
  }
8537
8537
  if (keyLength > maximumBreadth) {
8538
8538
  const removedKeys = keyLength - maximumBreadth;
8539
8539
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
8540
- separator = join3;
8540
+ separator = join4;
8541
8541
  }
8542
8542
  if (spacer !== "" && separator.length > 1) {
8543
8543
  res = `
@@ -8578,7 +8578,7 @@ ${originalIndentation}`;
8578
8578
  }
8579
8579
  const originalIndentation = indentation;
8580
8580
  let res = "";
8581
- let join3 = ",";
8581
+ let join4 = ",";
8582
8582
  if (Array.isArray(value)) {
8583
8583
  if (value.length === 0) {
8584
8584
  return "[]";
@@ -8591,7 +8591,7 @@ ${originalIndentation}`;
8591
8591
  indentation += spacer;
8592
8592
  res += `
8593
8593
  ${indentation}`;
8594
- join3 = `,
8594
+ join4 = `,
8595
8595
  ${indentation}`;
8596
8596
  }
8597
8597
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -8599,13 +8599,13 @@ ${indentation}`;
8599
8599
  for (; i < maximumValuesToStringify - 1; i++) {
8600
8600
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
8601
8601
  res += tmp2 !== void 0 ? tmp2 : "null";
8602
- res += join3;
8602
+ res += join4;
8603
8603
  }
8604
8604
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
8605
8605
  res += tmp !== void 0 ? tmp : "null";
8606
8606
  if (value.length - 1 > maximumBreadth) {
8607
8607
  const removedKeys = value.length - maximumBreadth - 1;
8608
- res += `${join3}"... ${getItemCount(removedKeys)} not stringified"`;
8608
+ res += `${join4}"... ${getItemCount(removedKeys)} not stringified"`;
8609
8609
  }
8610
8610
  if (spacer !== "") {
8611
8611
  res += `
@@ -8618,7 +8618,7 @@ ${originalIndentation}`;
8618
8618
  let whitespace = "";
8619
8619
  if (spacer !== "") {
8620
8620
  indentation += spacer;
8621
- join3 = `,
8621
+ join4 = `,
8622
8622
  ${indentation}`;
8623
8623
  whitespace = " ";
8624
8624
  }
@@ -8627,7 +8627,7 @@ ${indentation}`;
8627
8627
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
8628
8628
  if (tmp !== void 0) {
8629
8629
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
8630
- separator = join3;
8630
+ separator = join4;
8631
8631
  }
8632
8632
  }
8633
8633
  if (spacer !== "" && separator.length > 1) {
@@ -8685,20 +8685,20 @@ ${originalIndentation}`;
8685
8685
  indentation += spacer;
8686
8686
  let res2 = `
8687
8687
  ${indentation}`;
8688
- const join4 = `,
8688
+ const join5 = `,
8689
8689
  ${indentation}`;
8690
8690
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
8691
8691
  let i = 0;
8692
8692
  for (; i < maximumValuesToStringify - 1; i++) {
8693
8693
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
8694
8694
  res2 += tmp2 !== void 0 ? tmp2 : "null";
8695
- res2 += join4;
8695
+ res2 += join5;
8696
8696
  }
8697
8697
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
8698
8698
  res2 += tmp !== void 0 ? tmp : "null";
8699
8699
  if (value.length - 1 > maximumBreadth) {
8700
8700
  const removedKeys = value.length - maximumBreadth - 1;
8701
- res2 += `${join4}"... ${getItemCount(removedKeys)} not stringified"`;
8701
+ res2 += `${join5}"... ${getItemCount(removedKeys)} not stringified"`;
8702
8702
  }
8703
8703
  res2 += `
8704
8704
  ${originalIndentation}`;
@@ -8714,16 +8714,16 @@ ${originalIndentation}`;
8714
8714
  return '"[Object]"';
8715
8715
  }
8716
8716
  indentation += spacer;
8717
- const join3 = `,
8717
+ const join4 = `,
8718
8718
  ${indentation}`;
8719
8719
  let res = "";
8720
8720
  let separator = "";
8721
8721
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
8722
8722
  if (isTypedArrayWithEntries(value)) {
8723
- res += stringifyTypedArray(value, join3, maximumBreadth);
8723
+ res += stringifyTypedArray(value, join4, maximumBreadth);
8724
8724
  keys = keys.slice(value.length);
8725
8725
  maximumPropertiesToStringify -= value.length;
8726
- separator = join3;
8726
+ separator = join4;
8727
8727
  }
8728
8728
  if (deterministic) {
8729
8729
  keys = sort(keys, comparator);
@@ -8734,13 +8734,13 @@ ${indentation}`;
8734
8734
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
8735
8735
  if (tmp !== void 0) {
8736
8736
  res += `${separator}${strEscape(key2)}: ${tmp}`;
8737
- separator = join3;
8737
+ separator = join4;
8738
8738
  }
8739
8739
  }
8740
8740
  if (keyLength > maximumBreadth) {
8741
8741
  const removedKeys = keyLength - maximumBreadth;
8742
8742
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
8743
- separator = join3;
8743
+ separator = join4;
8744
8744
  }
8745
8745
  if (separator !== "") {
8746
8746
  res = `
@@ -9060,7 +9060,7 @@ var require_multistream = __commonJS({
9060
9060
  var require_pino = __commonJS({
9061
9061
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
9062
9062
  "use strict";
9063
- var os15 = require("os");
9063
+ var os16 = require("os");
9064
9064
  var stdSerializers = require_pino_std_serializers();
9065
9065
  var caller = require_caller();
9066
9066
  var redaction = require_redaction();
@@ -9107,7 +9107,7 @@ var require_pino = __commonJS({
9107
9107
  } = symbols;
9108
9108
  var { epochTime, nullTime } = time;
9109
9109
  var { pid } = process;
9110
- var hostname = os15.hostname();
9110
+ var hostname = os16.hostname();
9111
9111
  var defaultErrorSerializer = stdSerializers.err;
9112
9112
  var defaultOptions = {
9113
9113
  level: "info",
@@ -9831,11 +9831,11 @@ var init_lib = __esm({
9831
9831
  }
9832
9832
  }
9833
9833
  },
9834
- addToPath: function addToPath(path24, added, removed, oldPosInc, options) {
9835
- var last = path24.lastComponent;
9834
+ addToPath: function addToPath(path27, added, removed, oldPosInc, options) {
9835
+ var last = path27.lastComponent;
9836
9836
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
9837
9837
  return {
9838
- oldPos: path24.oldPos + oldPosInc,
9838
+ oldPos: path27.oldPos + oldPosInc,
9839
9839
  lastComponent: {
9840
9840
  count: last.count + 1,
9841
9841
  added,
@@ -9845,7 +9845,7 @@ var init_lib = __esm({
9845
9845
  };
9846
9846
  } else {
9847
9847
  return {
9848
- oldPos: path24.oldPos + oldPosInc,
9848
+ oldPos: path27.oldPos + oldPosInc,
9849
9849
  lastComponent: {
9850
9850
  count: 1,
9851
9851
  added,
@@ -9903,7 +9903,7 @@ var init_lib = __esm({
9903
9903
  tokenize: function tokenize(value) {
9904
9904
  return Array.from(value);
9905
9905
  },
9906
- join: function join2(chars) {
9906
+ join: function join3(chars) {
9907
9907
  return chars.join("");
9908
9908
  },
9909
9909
  postProcess: function postProcess(changeObjects) {
@@ -10276,10 +10276,10 @@ function attachmentToHistoryMessage(o, ts) {
10276
10276
  const memories = raw.map((m) => {
10277
10277
  if (!m || typeof m !== "object") return null;
10278
10278
  const rec = m;
10279
- const path24 = typeof rec.path === "string" ? rec.path : null;
10279
+ const path27 = typeof rec.path === "string" ? rec.path : null;
10280
10280
  const content = typeof rec.content === "string" ? rec.content : null;
10281
- if (!path24 || content == null) return null;
10282
- const entry = { path: path24, content };
10281
+ if (!path27 || content == null) return null;
10282
+ const entry = { path: path27, content };
10283
10283
  if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
10284
10284
  return entry;
10285
10285
  }).filter((m) => m !== null);
@@ -10316,7 +10316,7 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
10316
10316
  if (backupFileName === null) return null;
10317
10317
  try {
10318
10318
  return import_node_fs6.default.readFileSync(
10319
- import_node_path6.default.join(fileHistoryRoot, toolSessionId, backupFileName),
10319
+ import_node_path7.default.join(fileHistoryRoot, toolSessionId, backupFileName),
10320
10320
  "utf8"
10321
10321
  );
10322
10322
  } catch {
@@ -10331,13 +10331,13 @@ function readCurrentContent(filePath) {
10331
10331
  return null;
10332
10332
  }
10333
10333
  }
10334
- var import_node_fs6, import_node_os2, import_node_path6, 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;
10334
+ var import_node_fs6, import_node_os2, import_node_path7, 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;
10335
10335
  var init_claude_history = __esm({
10336
10336
  "src/tools/claude-history.ts"() {
10337
10337
  "use strict";
10338
10338
  import_node_fs6 = __toESM(require("fs"), 1);
10339
10339
  import_node_os2 = __toESM(require("os"), 1);
10340
- import_node_path6 = __toESM(require("path"), 1);
10340
+ import_node_path7 = __toESM(require("path"), 1);
10341
10341
  init_lib();
10342
10342
  init_tool_result_extra();
10343
10343
  TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
@@ -10361,9 +10361,9 @@ var init_claude_history = __esm({
10361
10361
  // 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
10362
10362
  fileHistoryRoot;
10363
10363
  constructor(opts = {}) {
10364
- const base = opts.baseDir ?? import_node_path6.default.join(import_node_os2.default.homedir(), ".claude");
10365
- this.projectsRoot = import_node_path6.default.join(base, "projects");
10366
- this.fileHistoryRoot = import_node_path6.default.join(base, "file-history");
10364
+ const base = opts.baseDir ?? import_node_path7.default.join(import_node_os2.default.homedir(), ".claude");
10365
+ this.projectsRoot = import_node_path7.default.join(base, "projects");
10366
+ this.fileHistoryRoot = import_node_path7.default.join(base, "file-history");
10367
10367
  }
10368
10368
  async listProjects() {
10369
10369
  let entries;
@@ -10376,9 +10376,9 @@ var init_claude_history = __esm({
10376
10376
  const out = [];
10377
10377
  for (const ent of entries) {
10378
10378
  if (!ent.isDirectory()) continue;
10379
- const dir = import_node_path6.default.join(this.projectsRoot, ent.name);
10379
+ const dir = import_node_path7.default.join(this.projectsRoot, ent.name);
10380
10380
  const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
10381
- const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path6.default.join(dir, f))), 0);
10381
+ const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path7.default.join(dir, f))), 0);
10382
10382
  out.push({
10383
10383
  projectPath: hashDirToCwd(ent.name),
10384
10384
  hashDir: ent.name,
@@ -10390,7 +10390,7 @@ var init_claude_history = __esm({
10390
10390
  return out;
10391
10391
  }
10392
10392
  async listSessions(args) {
10393
- const dir = import_node_path6.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
10393
+ const dir = import_node_path7.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
10394
10394
  let files;
10395
10395
  try {
10396
10396
  files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
@@ -10400,7 +10400,7 @@ var init_claude_history = __esm({
10400
10400
  }
10401
10401
  const out = [];
10402
10402
  for (const f of files) {
10403
- const full = import_node_path6.default.join(dir, f);
10403
+ const full = import_node_path7.default.join(dir, f);
10404
10404
  const toolSessionId = f.slice(0, -".jsonl".length);
10405
10405
  const lines = readJsonlLines(full);
10406
10406
  let summary = "";
@@ -10455,7 +10455,7 @@ var init_claude_history = __esm({
10455
10455
  return out;
10456
10456
  }
10457
10457
  async read(args) {
10458
- const file = import_node_path6.default.join(
10458
+ const file = import_node_path7.default.join(
10459
10459
  this.projectsRoot,
10460
10460
  cwdToHashDir(args.cwd),
10461
10461
  `${args.toolSessionId}.jsonl`
@@ -10488,7 +10488,7 @@ var init_claude_history = __esm({
10488
10488
  // 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
10489
10489
  // 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
10490
10490
  listSubagentsFromDirectory(cwd, toolSessionId) {
10491
- const dir = import_node_path6.default.join(
10491
+ const dir = import_node_path7.default.join(
10492
10492
  this.projectsRoot,
10493
10493
  cwdToHashDir(cwd),
10494
10494
  toolSessionId,
@@ -10506,7 +10506,7 @@ var init_claude_history = __esm({
10506
10506
  if (!e.isFile()) continue;
10507
10507
  if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
10508
10508
  const subagentId = e.name.slice("agent-".length, -".jsonl".length);
10509
- const filePath = import_node_path6.default.join(dir, e.name);
10509
+ const filePath = import_node_path7.default.join(dir, e.name);
10510
10510
  const lines = readJsonlLines(filePath);
10511
10511
  let firstText = "";
10512
10512
  let messageCount = 0;
@@ -10523,7 +10523,7 @@ var init_claude_history = __esm({
10523
10523
  return out;
10524
10524
  }
10525
10525
  listSubagentsFromMainJsonl(cwd, toolSessionId) {
10526
- const file = import_node_path6.default.join(
10526
+ const file = import_node_path7.default.join(
10527
10527
  this.projectsRoot,
10528
10528
  cwdToHashDir(cwd),
10529
10529
  `${toolSessionId}.jsonl`
@@ -10558,7 +10558,7 @@ var init_claude_history = __esm({
10558
10558
  }
10559
10559
  // 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
10560
10560
  readSubagentFromFile(cwd, toolSessionId, subagentId) {
10561
- const file = import_node_path6.default.join(
10561
+ const file = import_node_path7.default.join(
10562
10562
  this.projectsRoot,
10563
10563
  cwdToHashDir(cwd),
10564
10564
  toolSessionId,
@@ -10586,7 +10586,7 @@ var init_claude_history = __esm({
10586
10586
  * "那一刻每个 tracked 文件对应的 backup 文件名"
10587
10587
  */
10588
10588
  readFileHistorySnapshots(args) {
10589
- const file = import_node_path6.default.join(
10589
+ const file = import_node_path7.default.join(
10590
10590
  this.projectsRoot,
10591
10591
  cwdToHashDir(args.cwd),
10592
10592
  `${args.toolSessionId}.jsonl`
@@ -10631,7 +10631,7 @@ var init_claude_history = __esm({
10631
10631
  for (const [anchorId, target] of snapshots) {
10632
10632
  let hasAny = false;
10633
10633
  for (const [rawPath, backup] of Object.entries(target)) {
10634
- const absPath = import_node_path6.default.isAbsolute(rawPath) ? rawPath : import_node_path6.default.join(args.cwd, rawPath);
10634
+ const absPath = import_node_path7.default.isAbsolute(rawPath) ? rawPath : import_node_path7.default.join(args.cwd, rawPath);
10635
10635
  const backupContent = readBackupContent(
10636
10636
  this.fileHistoryRoot,
10637
10637
  args.toolSessionId,
@@ -10671,7 +10671,7 @@ var init_claude_history = __esm({
10671
10671
  let totalInsertions = 0;
10672
10672
  let totalDeletions = 0;
10673
10673
  for (const [rawPath, backup] of Object.entries(target)) {
10674
- const absPath = import_node_path6.default.isAbsolute(rawPath) ? rawPath : import_node_path6.default.join(args.cwd, rawPath);
10674
+ const absPath = import_node_path7.default.isAbsolute(rawPath) ? rawPath : import_node_path7.default.join(args.cwd, rawPath);
10675
10675
  const backupContent = readBackupContent(
10676
10676
  this.fileHistoryRoot,
10677
10677
  args.toolSessionId,
@@ -10718,7 +10718,7 @@ var init_claude_history = __esm({
10718
10718
  };
10719
10719
  }
10720
10720
  readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
10721
- const file = import_node_path6.default.join(
10721
+ const file = import_node_path7.default.join(
10722
10722
  this.projectsRoot,
10723
10723
  cwdToHashDir(cwd),
10724
10724
  `${toolSessionId}.jsonl`
@@ -10742,7 +10742,7 @@ var init_claude_history = __esm({
10742
10742
  // src/tools/claude.ts
10743
10743
  function macOSDesktopCandidates(home) {
10744
10744
  return [
10745
- import_node_path7.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
10745
+ import_node_path8.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
10746
10746
  "/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
10747
10747
  ];
10748
10748
  }
@@ -10804,6 +10804,7 @@ function buildSpawnArgs(ctx) {
10804
10804
  }
10805
10805
  }
10806
10806
  if (ctx.extraSettings) args.push("--settings", ctx.extraSettings);
10807
+ if (ctx.extraSystemPrompt) args.push("--append-system-prompt", ctx.extraSystemPrompt);
10807
10808
  if (ctx.effort) args.push("--effort", ctx.effort);
10808
10809
  if (ctx.toolSessionId) args.push("--resume", ctx.toolSessionId);
10809
10810
  return args;
@@ -11082,10 +11083,10 @@ function parseAttachment(obj) {
11082
11083
  const memories = raw.map((m) => {
11083
11084
  if (!m || typeof m !== "object") return null;
11084
11085
  const rec = m;
11085
- const path24 = typeof rec.path === "string" ? rec.path : null;
11086
+ const path27 = typeof rec.path === "string" ? rec.path : null;
11086
11087
  const content = typeof rec.content === "string" ? rec.content : null;
11087
- if (!path24 || content == null) return null;
11088
- const out = { path: path24, content };
11088
+ if (!path27 || content == null) return null;
11089
+ const out = { path: path27, content };
11089
11090
  if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
11090
11091
  return out;
11091
11092
  }).filter((m) => m !== null);
@@ -11189,7 +11190,7 @@ function encodeClaudeStdin(text) {
11189
11190
  };
11190
11191
  return JSON.stringify(frame) + "\n";
11191
11192
  }
11192
- var import_node_child_process, import_node_child_process2, import_node_fs7, import_node_os3, import_node_path7, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
11193
+ var import_node_child_process, import_node_child_process2, import_node_fs7, import_node_os3, import_node_path8, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
11193
11194
  var init_claude = __esm({
11194
11195
  "src/tools/claude.ts"() {
11195
11196
  "use strict";
@@ -11197,7 +11198,7 @@ var init_claude = __esm({
11197
11198
  import_node_child_process2 = require("child_process");
11198
11199
  import_node_fs7 = __toESM(require("fs"), 1);
11199
11200
  import_node_os3 = __toESM(require("os"), 1);
11200
- import_node_path7 = __toESM(require("path"), 1);
11201
+ import_node_path8 = __toESM(require("path"), 1);
11201
11202
  init_protocol();
11202
11203
  init_claude_history();
11203
11204
  init_tool_result_extra();
@@ -20456,22 +20457,22 @@ var require_websocket_server = __commonJS({
20456
20457
  // src/run-case/recorder.ts
20457
20458
  function startRunCaseRecorder(opts) {
20458
20459
  const now = opts.now ?? Date.now;
20459
- const dir = import_node_path21.default.dirname(opts.recordPath);
20460
+ const dir = import_node_path23.default.dirname(opts.recordPath);
20460
20461
  let stream = null;
20461
20462
  let closing = false;
20462
20463
  let closedSettled = false;
20463
20464
  let closedResolve;
20464
- const closed = new Promise((resolve) => {
20465
+ const closed = new Promise((resolve2) => {
20465
20466
  closedResolve = () => {
20466
20467
  if (closedSettled) return;
20467
20468
  closedSettled = true;
20468
- resolve();
20469
+ resolve2();
20469
20470
  };
20470
20471
  });
20471
20472
  const ensureStream = () => {
20472
20473
  if (stream) return stream;
20473
- import_node_fs21.default.mkdirSync(dir, { recursive: true });
20474
- stream = import_node_fs21.default.createWriteStream(opts.recordPath, { flags: "a" });
20474
+ import_node_fs22.default.mkdirSync(dir, { recursive: true });
20475
+ stream = import_node_fs22.default.createWriteStream(opts.recordPath, { flags: "a" });
20475
20476
  stream.on("close", () => closedResolve());
20476
20477
  return stream;
20477
20478
  };
@@ -20496,12 +20497,12 @@ function startRunCaseRecorder(opts) {
20496
20497
  };
20497
20498
  return { tap, close, closed };
20498
20499
  }
20499
- var import_node_fs21, import_node_path21;
20500
+ var import_node_fs22, import_node_path23;
20500
20501
  var init_recorder = __esm({
20501
20502
  "src/run-case/recorder.ts"() {
20502
20503
  "use strict";
20503
- import_node_fs21 = __toESM(require("fs"), 1);
20504
- import_node_path21 = __toESM(require("path"), 1);
20504
+ import_node_fs22 = __toESM(require("fs"), 1);
20505
+ import_node_path23 = __toESM(require("path"), 1);
20505
20506
  }
20506
20507
  });
20507
20508
 
@@ -20544,7 +20545,7 @@ var init_wire = __esm({
20544
20545
  // src/run-case/controller.ts
20545
20546
  async function runController(opts) {
20546
20547
  const now = opts.now ?? Date.now;
20547
- const cwd = opts.cwd ?? (0, import_node_fs22.mkdtempSync)(import_node_path22.default.join(import_node_os14.default.tmpdir(), "clawd-runcase-"));
20548
+ const cwd = opts.cwd ?? (0, import_node_fs23.mkdtempSync)(import_node_path24.default.join(import_node_os15.default.tmpdir(), "clawd-runcase-"));
20548
20549
  const ownsCwd = opts.cwd === void 0;
20549
20550
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
20550
20551
  const spawnCtx = { cwd };
@@ -20557,8 +20558,8 @@ async function runController(opts) {
20557
20558
  let exitCode = null;
20558
20559
  let procExited = false;
20559
20560
  let resolveProcExit;
20560
- const procExitPromise = new Promise((resolve) => {
20561
- resolveProcExit = resolve;
20561
+ const procExitPromise = new Promise((resolve2) => {
20562
+ resolveProcExit = resolve2;
20562
20563
  });
20563
20564
  const writeEvent = (event) => {
20564
20565
  try {
@@ -20705,19 +20706,19 @@ async function runController(opts) {
20705
20706
  if (sigintHandler) process.off("SIGINT", sigintHandler);
20706
20707
  if (ownsCwd) {
20707
20708
  try {
20708
- (0, import_node_fs22.rmSync)(cwd, { recursive: true, force: true });
20709
+ (0, import_node_fs23.rmSync)(cwd, { recursive: true, force: true });
20709
20710
  } catch {
20710
20711
  }
20711
20712
  }
20712
20713
  return exitCode ?? 0;
20713
20714
  }
20714
- var import_node_fs22, import_node_os14, import_node_path22;
20715
+ var import_node_fs23, import_node_os15, import_node_path24;
20715
20716
  var init_controller = __esm({
20716
20717
  "src/run-case/controller.ts"() {
20717
20718
  "use strict";
20718
- import_node_fs22 = require("fs");
20719
- import_node_os14 = __toESM(require("os"), 1);
20720
- import_node_path22 = __toESM(require("path"), 1);
20719
+ import_node_fs23 = require("fs");
20720
+ import_node_os15 = __toESM(require("os"), 1);
20721
+ import_node_path24 = __toESM(require("path"), 1);
20721
20722
  init_claude();
20722
20723
  init_stdout_splitter();
20723
20724
  init_permission_stdio();
@@ -20949,8 +20950,8 @@ Env (advanced):
20949
20950
  `;
20950
20951
 
20951
20952
  // src/index.ts
20952
- var import_node_path20 = __toESM(require("path"), 1);
20953
- var import_node_fs20 = __toESM(require("fs"), 1);
20953
+ var import_node_path22 = __toESM(require("path"), 1);
20954
+ var import_node_fs21 = __toESM(require("fs"), 1);
20954
20955
 
20955
20956
  // src/logger.ts
20956
20957
  var import_node_fs2 = __toESM(require("fs"), 1);
@@ -20989,9 +20990,30 @@ function createLogger(opts = {}) {
20989
20990
 
20990
20991
  // src/session/store.ts
20991
20992
  var import_node_fs3 = __toESM(require("fs"), 1);
20992
- var import_node_path3 = __toESM(require("path"), 1);
20993
+ var import_node_path4 = __toESM(require("path"), 1);
20993
20994
  init_protocol();
20994
- var DEFAULT_AGENT_ID = "default";
20995
+
20996
+ // src/session/scope.ts
20997
+ var import_node_path3 = __toESM(require("path"), 1);
20998
+ function scopeKey(scope) {
20999
+ return scope.kind === "default" ? "default" : `persona:${scope.personaId}:${scope.mode}`;
21000
+ }
21001
+ function scopeSubPath(scope) {
21002
+ return scope.kind === "default" ? ["default"] : [scope.personaId, scope.mode];
21003
+ }
21004
+ function metaFromScope(scope, personaRoot) {
21005
+ if (scope.kind === "default") return void 0;
21006
+ if (scope.mode === "owner") {
21007
+ return { idleKillEnabled: false, personaMode: "owner" };
21008
+ }
21009
+ return {
21010
+ idleKillEnabled: true,
21011
+ personaMode: "listener",
21012
+ extraSettings: import_node_path3.default.join(personaRoot, scope.personaId, ".clawd", "sandbox-settings.json")
21013
+ };
21014
+ }
21015
+
21016
+ // src/session/store.ts
20995
21017
  function safeFileName(sessionId) {
20996
21018
  const base = sessionId.replace(/[^a-zA-Z0-9_\-.]/g, "_");
20997
21019
  const cleaned = base.replace(/^\.+/, (dots) => "_".repeat(dots.length));
@@ -21003,20 +21025,15 @@ function safeFileName(sessionId) {
21003
21025
  var SessionStore = class {
21004
21026
  root;
21005
21027
  constructor(opts) {
21006
- const agentId = opts.agentId ?? DEFAULT_AGENT_ID;
21007
- if (agentId !== DEFAULT_AGENT_ID) {
21008
- if (!opts.personaRoot) {
21009
- throw new Error(
21010
- `SessionStore: personaRoot is required for non-default agentId='${agentId}'. Bootstrap must wire personaRoot when constructing SessionStore for persona agents.`
21011
- );
21012
- }
21013
- this.root = import_node_path3.default.join(opts.personaRoot, safeFileName(agentId), ".clawd", "sub-sessions");
21014
- } else {
21015
- this.root = import_node_path3.default.join(opts.dataDir, "sessions", agentId);
21016
- }
21028
+ const scope = opts.scope ?? { kind: "default" };
21029
+ this.root = import_node_path4.default.join(
21030
+ opts.dataDir,
21031
+ "sessions",
21032
+ ...scopeSubPath(scope).map(safeFileName)
21033
+ );
21017
21034
  }
21018
21035
  filePath(sessionId) {
21019
- return import_node_path3.default.join(this.root, `${safeFileName(sessionId)}.json`);
21036
+ return import_node_path4.default.join(this.root, `${safeFileName(sessionId)}.json`);
21020
21037
  }
21021
21038
  ensureDir() {
21022
21039
  import_node_fs3.default.mkdirSync(this.root, { recursive: true });
@@ -21064,7 +21081,7 @@ var SessionStore = class {
21064
21081
  for (const name of entries) {
21065
21082
  if (!name.endsWith(".json")) continue;
21066
21083
  if (name.includes(".tmp-")) continue;
21067
- const full = import_node_path3.default.join(this.root, name);
21084
+ const full = import_node_path4.default.join(this.root, name);
21068
21085
  try {
21069
21086
  const raw = import_node_fs3.default.readFileSync(full, "utf8");
21070
21087
  const parsed = JSON.parse(raw);
@@ -21080,7 +21097,7 @@ var SessionStore = class {
21080
21097
 
21081
21098
  // src/session/manager.ts
21082
21099
  var import_node_fs5 = __toESM(require("fs"), 1);
21083
- var import_node_path5 = __toESM(require("path"), 1);
21100
+ var import_node_path6 = __toESM(require("path"), 1);
21084
21101
 
21085
21102
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
21086
21103
  var byteToHex = [];
@@ -21167,6 +21184,20 @@ function buildRule(tool, input) {
21167
21184
 
21168
21185
  // src/session/reducer.ts
21169
21186
  init_permission_stdio();
21187
+
21188
+ // src/persona/connection-prompt.ts
21189
+ var OWNER_TEMPLATE = `# \u8FDE\u63A5\u4E0A\u4E0B\u6587
21190
+ \u4F60\u73B0\u5728\u4EE5 Owner \u8EAB\u4EFD\u88AB\u8FDE\u63A5\uFF0C\u5BF9\u65B9\u5C31\u662F owner \u672C\u4EBA\uFF08{ownerLabel}\uFF09\u3002
21191
+ \u81EA\u6211\u4ECB\u7ECD\u65F6\u4F7F\u7528\u7B2C\u4E00/\u7B2C\u4E8C\u4EBA\u79F0\uFF0C\u4F8B\u5982\u300C\u6211\u662F\u60A8\u7684 xxx \u52A9\u624B\u300D\u3002`;
21192
+ var LISTENER_TEMPLATE = `# \u8FDE\u63A5\u4E0A\u4E0B\u6587
21193
+ \u4F60\u73B0\u5728\u4EE5 Listener \u8EAB\u4EFD\u88AB\u8FDE\u63A5\uFF0C\u672C persona \u7684 owner \u662F\u300C{ownerLabel}\u300D\uFF0C\u4F46\u5F53\u524D\u5BF9\u8BDD\u7684\u5BF9\u65B9\u4E0D\u662F owner \u672C\u4EBA\u3002
21194
+ \u81EA\u6211\u4ECB\u7ECD\u65F6\u4F7F\u7528\u7B2C\u4E09\u4EBA\u79F0\u6307\u4EE3 owner\uFF0C\u4F8B\u5982\u300C\u6211\u662F {ownerLabel} \u7684 xxx \u52A9\u624B\uFF0C\u4F60\u53EF\u4EE5\u901A\u8FC7\u6211\u770B\u5230\u4ED6\u7684 xxx\u300D\u3002\u4E0D\u8981\u628A\u5BF9\u65B9\u5F53\u6210 owner\uFF0C\u4E0D\u8981\u66FF owner \u505A\u51FA\u627F\u8BFA\u3002`;
21195
+ function buildConnectionPrompt(args) {
21196
+ const template = args.mode === "owner" ? OWNER_TEMPLATE : LISTENER_TEMPLATE;
21197
+ return template.replace(/\{ownerLabel\}/g, args.ownerLabel);
21198
+ }
21199
+
21200
+ // src/session/reducer.ts
21170
21201
  function cloneState(s) {
21171
21202
  return {
21172
21203
  file: s.file,
@@ -21216,7 +21247,7 @@ function emitSessionEvent(sessionId, event, target) {
21216
21247
  };
21217
21248
  return target ? { kind: "emit-frame", frame, target } : { kind: "emit-frame", frame };
21218
21249
  }
21219
- function buildSpawnContext(state) {
21250
+ function buildSpawnContext(state, deps) {
21220
21251
  const file = state.file;
21221
21252
  const ctx = {
21222
21253
  cwd: file.cwd,
@@ -21228,6 +21259,10 @@ function buildSpawnContext(state) {
21228
21259
  const meta = state.subSessionMeta;
21229
21260
  if (meta?.personaMode) {
21230
21261
  ctx.personaMode = meta.personaMode;
21262
+ ctx.extraSystemPrompt = buildConnectionPrompt({
21263
+ mode: meta.personaMode,
21264
+ ownerLabel: deps.ownerDisplayName
21265
+ });
21231
21266
  }
21232
21267
  if (meta?.extraSettings) {
21233
21268
  ctx.extraSettings = meta.extraSettings;
@@ -21416,7 +21451,7 @@ function applyCommand(state, command, deps) {
21416
21451
  next.nextSeq = 0;
21417
21452
  next.turnOpen = false;
21418
21453
  next.status = "running";
21419
- effects.push({ kind: "spawn", ctx: buildSpawnContext(next) });
21454
+ effects.push({ kind: "spawn", ctx: buildSpawnContext(next, deps) });
21420
21455
  effects.push({
21421
21456
  kind: "emit-frame",
21422
21457
  frame: {
@@ -21468,7 +21503,7 @@ function applyCommand(state, command, deps) {
21468
21503
  next.nextSeq = 0;
21469
21504
  next.turnOpen = false;
21470
21505
  next.status = "running";
21471
- effects.push({ kind: "spawn", ctx: buildSpawnContext(next) });
21506
+ effects.push({ kind: "spawn", ctx: buildSpawnContext(next, deps) });
21472
21507
  effects.push({
21473
21508
  kind: "emit-frame",
21474
21509
  frame: { type: "session:status", sessionId, status: "running" }
@@ -21790,7 +21825,7 @@ init_stdout_splitter();
21790
21825
 
21791
21826
  // src/ipc-recorder.ts
21792
21827
  var import_node_fs4 = __toESM(require("fs"), 1);
21793
- var import_node_path4 = __toESM(require("path"), 1);
21828
+ var import_node_path5 = __toESM(require("path"), 1);
21794
21829
  function tsForFilename(ms) {
21795
21830
  return new Date(ms).toISOString().replace(/[:.]/g, "-");
21796
21831
  }
@@ -21801,12 +21836,12 @@ function startRecorder(opts) {
21801
21836
  return null;
21802
21837
  }
21803
21838
  const now = opts.now ?? Date.now;
21804
- const dir = import_node_path4.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
21805
- const filePath = import_node_path4.default.join(dir, `${tsForFilename(now())}.jsonl`);
21839
+ const dir = import_node_path5.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
21840
+ const filePath = import_node_path5.default.join(dir, `${tsForFilename(now())}.jsonl`);
21806
21841
  let stream = null;
21807
21842
  let closedResolve;
21808
- const closed = new Promise((resolve) => {
21809
- closedResolve = resolve;
21843
+ const closed = new Promise((resolve2) => {
21844
+ closedResolve = resolve2;
21810
21845
  });
21811
21846
  let exited = false;
21812
21847
  const ensureStream = () => {
@@ -21930,7 +21965,8 @@ var SessionRunner = class {
21930
21965
  bufferCap: this.hooks.bufferCap ?? 500,
21931
21966
  now: this.hooks.now ?? Date.now,
21932
21967
  resolveContextWindow: this.hooks.resolveContextWindow,
21933
- genUuid: this.hooks.genUuid ?? v4_default
21968
+ genUuid: this.hooks.genUuid ?? v4_default,
21969
+ ownerDisplayName: this.hooks.ownerDisplayName
21934
21970
  };
21935
21971
  const { state, effects } = reduceSession(this.state, inputMsg, deps);
21936
21972
  this.state = state;
@@ -21946,13 +21982,13 @@ var SessionRunner = class {
21946
21982
  // 已经停止则立即 resolve;超时(默认 3000ms)抛错由上层透传成 RPC error
21947
21983
  async waitUntilStopped(timeoutMs = DEFAULT_WAIT_STOP_TIMEOUT_MS) {
21948
21984
  if (!this.state.procAlive) return;
21949
- return new Promise((resolve, reject) => {
21985
+ return new Promise((resolve2, reject) => {
21950
21986
  let settled = false;
21951
21987
  const onStop = () => {
21952
21988
  if (settled) return;
21953
21989
  settled = true;
21954
21990
  clearTimeout(timer);
21955
- resolve();
21991
+ resolve2();
21956
21992
  };
21957
21993
  const timer = setTimeout(() => {
21958
21994
  if (settled) return;
@@ -21997,7 +22033,7 @@ var SessionRunner = class {
21997
22033
  };
21998
22034
  const payload = JSON.stringify(frame) + "\n";
21999
22035
  const timeoutMs = opts.timeoutMs ?? DEFAULT_CONTROL_REQUEST_TIMEOUT_MS;
22000
- return new Promise((resolve, reject) => {
22036
+ return new Promise((resolve2, reject) => {
22001
22037
  const timer = setTimeout(() => {
22002
22038
  const pending = this.pendingControlRequests.get(requestId);
22003
22039
  if (!pending) return;
@@ -22005,7 +22041,7 @@ var SessionRunner = class {
22005
22041
  reject(new Error(`control_request timeout: ${subtype}`));
22006
22042
  }, timeoutMs);
22007
22043
  timer.unref?.();
22008
- this.pendingControlRequests.set(requestId, { resolve, reject, timer });
22044
+ this.pendingControlRequests.set(requestId, { resolve: resolve2, reject, timer });
22009
22045
  try {
22010
22046
  proc.stdin?.write(payload);
22011
22047
  this.recorder?.tapStdinWrite(payload);
@@ -22243,7 +22279,6 @@ function makeInitialState(file, subSessionMeta) {
22243
22279
  var SessionManager = class {
22244
22280
  constructor(deps) {
22245
22281
  this.deps = deps;
22246
- this.storesByAgent.set(DEFAULT_AGENT_ID, deps.store);
22247
22282
  }
22248
22283
  deps;
22249
22284
  // sessionId → SessionRunner;在 send / ensureSession 时按需创建
@@ -22259,12 +22294,11 @@ var SessionManager = class {
22259
22294
  // 由 observer 监听 jsonl user 行后调 recordRealUserUuid 建立映射;rewind 系列 RPC 在
22260
22295
  // 入参 / 出参做转译,保证 UI 看到的 uuid 始终是 events 流里的 synth uuid
22261
22296
  realUuidBySynth = /* @__PURE__ */ new Map();
22262
- // persona sub-session 路径:按 agentId 派生 SessionStore(root = dataDir/sessions/<agentId>/)。
22263
- // 'default' 直接复用 deps.store;其它 agentId 第一次访问时按需创建并缓存
22264
- storesByAgent = /* @__PURE__ */ new Map();
22265
- // sub-session 创建时记录的 subSessionMeta;ensureSession / runner 创建时塞入 reducer state。
22266
- // 不进 SessionFile schema(避免破坏现有 zod parse),仅运行时缓存
22267
- subSessionMetaBySid = /* @__PURE__ */ new Map();
22297
+ // SessionStore scope 派生(root = <dataDir>/sessions/<scopeSubPath>/)。
22298
+ // default scope 直接复用 deps.store;persona scope(owner / listener)第一次访问时按需创建并缓存。
22299
+ // 取代旧的 storesByAgent —— agentId 概念由 SessionScope 取代,路径即身份,
22300
+ // SubSessionMeta scope 派生(metaFromScope),不再需要运行时 cache ownerPersonaId 兜底。
22301
+ storesByScope = /* @__PURE__ */ new Map();
22268
22302
  // persona-bound transport 订阅器:sessionId → Set<listener>。
22269
22303
  // 透传 owner 路径白名单 EventFrame(routeFromRunner 决定哪些 type 进入),listener 端按
22270
22304
  // `frame.type` narrow 出 'session:event'(ParsedEvent)/ 'session:status'(procAlive 同步)等。
@@ -22289,22 +22323,18 @@ var SessionManager = class {
22289
22323
  attachObserver(observer) {
22290
22324
  this.attachedObserver = observer;
22291
22325
  }
22292
- // 按 agentId 拿对应的 SessionStore;persona-* agentId 使用 personaRoot 路径。
22293
- // 'default' 直接复用 deps.store;其它 agentId 第一次访问时按需创建并缓存。
22294
- // personaRoot 必须与 PersonaStore 同源,两者共享相同的 persona 目录层级
22295
- storeFor(agentId) {
22296
- const cached = this.storesByAgent.get(agentId);
22326
+ // 按 scope 拿对应的 SessionStore。default scope 复用 deps.store(保证与
22327
+ // bootstrap 注入的 store 一致);persona scope 第一次访问时按需创建并缓存。
22328
+ storeFor(scope) {
22329
+ if (scope.kind === "default") return this.deps.store;
22330
+ const key = scopeKey(scope);
22331
+ const cached = this.storesByScope.get(key);
22297
22332
  if (cached) return cached;
22298
22333
  if (!this.deps.dataDir) {
22299
- throw new Error(`SessionManager: dataDir required to route agentId='${agentId}'`);
22334
+ throw new Error(`SessionManager: dataDir required to construct SessionStore for scope=${key}`);
22300
22335
  }
22301
- if (!this.deps.personaRoot) {
22302
- throw new Error(
22303
- `SessionManager: personaRoot is required to route agentId='${agentId}'. Bootstrap must wire personaRoot when constructing SessionManager for persona sub-sessions.`
22304
- );
22305
- }
22306
- const st = new SessionStore({ dataDir: this.deps.dataDir, agentId, personaRoot: this.deps.personaRoot });
22307
- this.storesByAgent.set(agentId, st);
22336
+ const st = new SessionStore({ dataDir: this.deps.dataDir, scope });
22337
+ this.storesByScope.set(key, st);
22308
22338
  return st;
22309
22339
  }
22310
22340
  async getCapabilities(tool) {
@@ -22315,26 +22345,80 @@ var SessionManager = class {
22315
22345
  this.capabilitiesCache.set(tool, caps);
22316
22346
  return caps;
22317
22347
  }
22318
- // 按优先级解析 SubSessionMeta:subSessionMetaBySid 缓存(内存,首次 create/registerSubSession 写入)
22319
- // SessionFile.ownerPersonaId 派生(持久化兜底,daemon 重启后 subSessionMetaBySid 丢失时生效)
22320
- // undefined(普通 session)
22321
- resolveSubSessionMeta(file) {
22322
- const cached = this.subSessionMetaBySid.get(file.sessionId);
22323
- if (cached) return cached;
22324
- if (file.ownerPersonaId) {
22325
- return { idleKillEnabled: false, personaMode: "owner" };
22348
+ // SessionFile.ownerPersonaId schema 字段推回写入 scope。
22349
+ // ownerPersonaId 由 create({ownerPersonaId}) schema 落盘时记入,永远只反映
22350
+ // session 出身(不可变);此函数只用于 SessionStore 的写入路由,不参与运行时行为
22351
+ // 决策(personaMode='owner' 等由路径 → scope → metaFromScope 派生)。
22352
+ // 仅覆盖 owner + default 两类——listener sub-session 不会从 default RPC 路径进来。
22353
+ scopeForFile(file) {
22354
+ return file.ownerPersonaId ? { kind: "persona", personaId: file.ownerPersonaId, mode: "owner" } : { kind: "default" };
22355
+ }
22356
+ // 扫 <dataDir>/sessions/ 列出所有 persona 命名空间(不含 'default')。
22357
+ // 用于 findOwnedSession / listAllOwned 跨 scope 查询。
22358
+ listPersonaIdsOnDisk() {
22359
+ if (!this.deps.dataDir) return [];
22360
+ const root = import_node_path6.default.join(this.deps.dataDir, "sessions");
22361
+ let entries;
22362
+ try {
22363
+ entries = import_node_fs5.default.readdirSync(root, { withFileTypes: true });
22364
+ } catch (err) {
22365
+ const code = err?.code;
22366
+ if (code === "ENOENT") return [];
22367
+ throw err;
22326
22368
  }
22327
- return void 0;
22369
+ return entries.filter((e) => e.isDirectory() && e.name !== "default").map((e) => e.name);
22370
+ }
22371
+ // owner / default 两个分类下按 sessionId 找文件——前端只传 sessionId 不带 scope,
22372
+ // SessionManager 在这里扫盘定位(default 直接试,未命中再轮询所有 persona owner 目录)。
22373
+ // listener sub-session 不走这条——transport 始终明确传 (personaId, sessionId)。
22374
+ findOwnedSession(sessionId) {
22375
+ const dflt = this.deps.store.read(sessionId);
22376
+ if (dflt) return dflt;
22377
+ for (const personaId of this.listPersonaIdsOnDisk()) {
22378
+ const ownerStore = this.storeFor({ kind: "persona", personaId, mode: "owner" });
22379
+ const file = ownerStore.read(sessionId);
22380
+ if (file) return file;
22381
+ }
22382
+ return null;
22383
+ }
22384
+ // 合并 default + 所有 persona owner 的 SessionFile —— 桌面 App 主 session 列表入口。
22385
+ // 同样不含 listener sub-session(listener 走 persona:listSubSessions RPC 单独入口)。
22386
+ listAllOwned() {
22387
+ const out = [];
22388
+ out.push(...this.deps.store.list());
22389
+ for (const personaId of this.listPersonaIdsOnDisk()) {
22390
+ const ownerStore = this.storeFor({ kind: "persona", personaId, mode: "owner" });
22391
+ out.push(...ownerStore.list());
22392
+ }
22393
+ return out.sort(
22394
+ (a, b) => a.updatedAt > b.updatedAt ? -1 : a.updatedAt < b.updatedAt ? 1 : 0
22395
+ );
22396
+ }
22397
+ // 写回 SessionFile,自动根据 ownerPersonaId 派生写入 scope。
22398
+ // 调用方原先都是 `deps.store.write(updated)`,全部走这里收口路由。
22399
+ writeOwned(file) {
22400
+ return this.storeFor(this.scopeForFile(file)).write(file);
22401
+ }
22402
+ // 删除 owned SessionFile(default 或 persona/owner),与 findOwnedSession 对称扫盘。
22403
+ deleteOwned(sessionId) {
22404
+ if (this.deps.store.delete(sessionId)) return true;
22405
+ for (const personaId of this.listPersonaIdsOnDisk()) {
22406
+ const ownerStore = this.storeFor({ kind: "persona", personaId, mode: "owner" });
22407
+ if (ownerStore.delete(sessionId)) return true;
22408
+ }
22409
+ return false;
22328
22410
  }
22329
22411
  // 创建 runner 时包一层 broadcast hook:所有外出 frame 统一走 routeFromRunner,
22330
- // 经过 compressFrameForWire 后决定是 push collector 还是走 deps.broadcastFrame
22331
- // store:默认 deps.store;persona sub-session 路径下传该 personaId 对应的 SessionStore
22332
- // subSessionMeta:listener { idleKillEnabled: true, personaMode: 'listener' };
22333
- // owner { idleKillEnabled: false, personaMode: 'owner' };普通 session 不传
22334
- newRunner(file, opts = {}) {
22412
+ // 经过 compressFrameForWire 后决定是 push collector 还是走 deps.broadcastFrame
22413
+ // scope 决定两件事:SessionStore 路由 + SubSessionMeta 派生(metaFromScope)。
22414
+ // - default 复用 deps.store,无 subSessionMeta(普通 session)
22415
+ // - persona/owner <dataDir>/sessions/<personaId>/owner/,meta={idleKillEnabled:false, personaMode:'owner'}
22416
+ // - persona/listener → <dataDir>/sessions/<personaId>/listener/,meta={idleKillEnabled:true, personaMode:'listener', extraSettings:<sandbox>}
22417
+ newRunner(file, scope) {
22335
22418
  const adapter = this.deps.getAdapter(file.tool ?? "claude");
22336
- const store = opts.store ?? this.deps.store;
22337
- const runner = new SessionRunner(makeInitialState(file, opts.subSessionMeta), {
22419
+ const store = this.storeFor(scope);
22420
+ const subSessionMeta = metaFromScope(scope, this.deps.personaRoot ?? "");
22421
+ const runner = new SessionRunner(makeInitialState(file, subSessionMeta), {
22338
22422
  broadcastFrame: (frame, target) => this.routeFromRunner(frame, target),
22339
22423
  store,
22340
22424
  adapter,
@@ -22345,7 +22429,8 @@ var SessionManager = class {
22345
22429
  // adapter 自己持有模型表 + 兜底逻辑(contains / opus-1M / [1m] 等),manager 不再 cache 转发
22346
22430
  resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId),
22347
22431
  dataDir: this.deps.dataDir,
22348
- personaStore: this.deps.personaStore
22432
+ personaStore: this.deps.personaStore,
22433
+ ownerDisplayName: this.deps.ownerDisplayName
22349
22434
  });
22350
22435
  if (this.deps.mode === "tui" && !file.toolSessionId) {
22351
22436
  const newTsid = v4_default();
@@ -22438,7 +22523,7 @@ var SessionManager = class {
22438
22523
  if (!this.deps.personaRoot) {
22439
22524
  throw new Error("personaRoot required to derive cwd from ownerPersonaId");
22440
22525
  }
22441
- cwd = import_node_path5.default.join(this.deps.personaRoot, safeFileName(args.ownerPersonaId));
22526
+ cwd = import_node_path6.default.join(this.deps.personaRoot, safeFileName(args.ownerPersonaId));
22442
22527
  }
22443
22528
  if (!cwd) {
22444
22529
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "cwd required when ownerPersonaId is absent");
@@ -22470,13 +22555,8 @@ var SessionManager = class {
22470
22555
  createdAt: iso,
22471
22556
  updatedAt: iso
22472
22557
  };
22473
- const written = this.deps.store.write(file);
22474
- if (args.ownerPersonaId) {
22475
- this.subSessionMetaBySid.set(written.sessionId, {
22476
- idleKillEnabled: false,
22477
- personaMode: "owner"
22478
- });
22479
- }
22558
+ const scope = args.ownerPersonaId ? { kind: "persona", personaId: args.ownerPersonaId, mode: "owner" } : { kind: "default" };
22559
+ const written = this.storeFor(scope).write(file);
22480
22560
  return { response: written, broadcast: [] };
22481
22561
  }
22482
22562
  pin(args) {
@@ -22491,13 +22571,13 @@ var SessionManager = class {
22491
22571
  return { response: value, broadcast };
22492
22572
  }
22493
22573
  const updated = { ...existing, pinnedAt };
22494
- this.deps.store.write(updated);
22574
+ this.writeOwned(updated);
22495
22575
  return { response: updated, broadcast: [] };
22496
22576
  }
22497
22577
  // sidebar 拖拽完成 → 整体重写 pinned root 的 pinSortOrder(按 orderedIds 下标 0,1,2...)
22498
22578
  // orderedIds 必须正好覆盖所有当前 pinned root(既不能漏,也不能含 unpinned id)
22499
22579
  reorderPins(args) {
22500
- const all = this.deps.store.list();
22580
+ const all = this.listAllOwned();
22501
22581
  const currentPinnedIds = new Set(
22502
22582
  all.filter((f) => typeof f.pinnedAt === "number").map((f) => f.sessionId)
22503
22583
  );
@@ -22527,14 +22607,14 @@ var SessionManager = class {
22527
22607
  } else {
22528
22608
  const existing = this.getFile(sessionId);
22529
22609
  const updated = { ...existing, pinSortOrder: index };
22530
- this.deps.store.write(updated);
22610
+ this.writeOwned(updated);
22531
22611
  updatedFiles.push(updated);
22532
22612
  }
22533
22613
  });
22534
22614
  return { response: { sessions: updatedFiles }, broadcast };
22535
22615
  }
22536
22616
  list() {
22537
- return { response: { sessions: this.deps.store.list() }, broadcast: [] };
22617
+ return { response: { sessions: this.listAllOwned() }, broadcast: [] };
22538
22618
  }
22539
22619
  get(args) {
22540
22620
  const file = this.getFile(args.sessionId);
@@ -22587,10 +22667,11 @@ var SessionManager = class {
22587
22667
  for (const [synth, real] of map) reverse.set(real, synth);
22588
22668
  return realUuids.map((r) => reverse.get(r) ?? r);
22589
22669
  }
22590
- // 内部帮手:不走 ManagerResult 的 get,直接拿 SessionFile
22670
+ // 内部帮手:不走 ManagerResult 的 get,直接拿 SessionFile
22671
+ // 优先 runner cache(hot path);冷态走 findOwnedSession 跨 default + 所有 persona owner 扫盘。
22591
22672
  getFile(sessionId) {
22592
22673
  const runner = this.runners.get(sessionId);
22593
- const existing = runner?.getState().file ?? this.deps.store.read(sessionId);
22674
+ const existing = runner?.getState().file ?? this.findOwnedSession(sessionId);
22594
22675
  if (!existing) throw new ClawdError(ERROR_CODES.SESSION_NOT_FOUND, sessionId);
22595
22676
  return existing;
22596
22677
  }
@@ -22605,11 +22686,11 @@ var SessionManager = class {
22605
22686
  return { response: value, broadcast };
22606
22687
  }
22607
22688
  const updated = { ...existing, ...args.patch, updatedAt: nowIso2(this.deps) };
22608
- this.deps.store.write(updated);
22689
+ this.writeOwned(updated);
22609
22690
  return { response: updated, broadcast: [] };
22610
22691
  }
22611
22692
  delete(args) {
22612
- const existing = this.deps.store.read(args.sessionId);
22693
+ const existing = this.findOwnedSession(args.sessionId);
22613
22694
  if (!existing) throw new ClawdError(ERROR_CODES.SESSION_NOT_FOUND, args.sessionId);
22614
22695
  const runner = this.runners.get(args.sessionId);
22615
22696
  if (runner) {
@@ -22620,7 +22701,7 @@ var SessionManager = class {
22620
22701
  this.realUuidBySynth.delete(args.sessionId);
22621
22702
  return { response: { sessionId: args.sessionId }, broadcast };
22622
22703
  }
22623
- this.deps.store.delete(args.sessionId);
22704
+ this.deleteOwned(args.sessionId);
22624
22705
  return {
22625
22706
  response: { sessionId: args.sessionId },
22626
22707
  broadcast: [
@@ -22632,8 +22713,7 @@ var SessionManager = class {
22632
22713
  const existing = this.getFile(args.sessionId);
22633
22714
  let runner = this.runners.get(args.sessionId);
22634
22715
  if (!runner) {
22635
- const subSessionMeta = this.resolveSubSessionMeta(existing);
22636
- runner = this.newRunner(existing, { subSessionMeta });
22716
+ runner = this.newRunner(existing, this.scopeForFile(existing));
22637
22717
  this.runners.set(args.sessionId, runner);
22638
22718
  }
22639
22719
  const { broadcast } = this.withCollector(() => {
@@ -22727,8 +22807,7 @@ var SessionManager = class {
22727
22807
  const file = this.getFile(args.sessionId);
22728
22808
  let runner = this.runners.get(args.sessionId);
22729
22809
  if (!runner) {
22730
- const subSessionMeta = this.resolveSubSessionMeta(file);
22731
- runner = this.newRunner(file, { subSessionMeta });
22810
+ runner = this.newRunner(file, this.scopeForFile(file));
22732
22811
  this.runners.set(args.sessionId, runner);
22733
22812
  }
22734
22813
  if (!runner.getState().procAlive) {
@@ -22779,7 +22858,7 @@ var SessionManager = class {
22779
22858
  });
22780
22859
  return { response: value, broadcast };
22781
22860
  }
22782
- const existing = this.deps.store.read(args.sessionId);
22861
+ const existing = this.findOwnedSession(args.sessionId);
22783
22862
  const {
22784
22863
  toolSessionId: _drop,
22785
22864
  contextUsage: _ctx,
@@ -22794,7 +22873,7 @@ var SessionManager = class {
22794
22873
  void _branch;
22795
22874
  void _model;
22796
22875
  const updated = { ...rest, updatedAt: nowIso2(this.deps) };
22797
- return { response: this.deps.store.write(updated), broadcast: [] };
22876
+ return { response: this.writeOwned(updated), broadcast: [] };
22798
22877
  }
22799
22878
  resume(args) {
22800
22879
  this.getFile(args.sessionId);
@@ -22809,13 +22888,13 @@ var SessionManager = class {
22809
22888
  });
22810
22889
  return { response: value, broadcast };
22811
22890
  }
22812
- const existing = this.deps.store.read(args.sessionId);
22891
+ const existing = this.findOwnedSession(args.sessionId);
22813
22892
  const updated = {
22814
22893
  ...existing,
22815
22894
  toolSessionId: args.toolSessionId,
22816
22895
  updatedAt: nowIso2(this.deps)
22817
22896
  };
22818
- return { response: this.deps.store.write(updated), broadcast: [] };
22897
+ return { response: this.writeOwned(updated), broadcast: [] };
22819
22898
  }
22820
22899
  getEvents(args) {
22821
22900
  const runner = this.runners.get(args.sessionId);
@@ -22883,39 +22962,44 @@ var SessionManager = class {
22883
22962
  if (!runner) return "idle";
22884
22963
  return compressStatus(runner.getState().status);
22885
22964
  }
22886
- // 给 observer 用:保证有 runner 但不 spawn(仅创建 state 容器)
22965
+ // 给 observer 用:保证有 runner 但不 spawn(仅创建 state 容器)。
22966
+ // observer 喂事件路径只走 default + owner(普通 + owner persona session)
22967
+ // ——listener sub-session 的 observer 路径走 ensureRunnerForScope。
22887
22968
  ensureSession(file) {
22888
22969
  let r = this.runners.get(file.sessionId);
22889
22970
  if (r) return r;
22890
- const subSessionMeta = this.resolveSubSessionMeta(file);
22891
- r = this.newRunner(file, { subSessionMeta });
22971
+ r = this.newRunner(file, this.scopeForFile(file));
22892
22972
  this.runners.set(file.sessionId, r);
22893
22973
  return r;
22894
22974
  }
22895
- // ---------------- persona / sub-session 专用 API ----------------
22975
+ // ---------------- persona / listener sub-session 专用 API ----------------
22896
22976
  //
22897
- // PersonaManager 是 SessionManager 之上的薄编排层,sub-session 的持久化(SessionFile)
22898
- // 仍由 SessionManager 持有。区别于普通 session:
22899
- // - SessionFile 落到 <personaRoot>/<personaId>/.clawd/sub-sessions/ 而非 sessions/default/
22977
+ // PersonaManager 是 SessionManager 之上的薄编排层,listener sub-session 的持久化
22978
+ // (SessionFile)仍由 SessionManager 持有。区别于普通 / owner session:
22979
+ // - SessionFile 落到 <dataDir>/sessions/<personaId>/listener/(拓扑分类)
22900
22980
  // - reducer state.subSessionMeta.idleKillEnabled = true(turn_end 自动 idle-kill)
22901
22981
  // - sessionId 由 PersonaManager 派生(personaId-<tokenHash>),不走自动 newSessionId
22902
- /** 按 agentId 读取 SessionFile;不存在返回 null */
22903
- readForAgent(sessionId, agentId) {
22904
- return this.storeFor(agentId).read(sessionId);
22982
+ //
22983
+ // 这些 API 接 SessionScope 参数(不再是单参 agentId)—— transport 始终明确传
22984
+ // {kind:'persona', personaId, mode:'listener'},与 owner / default 分类隔离。
22985
+ /** 按 scope 读取 SessionFile;不存在返回 null */
22986
+ readForScope(sessionId, scope) {
22987
+ return this.storeFor(scope).read(sessionId);
22905
22988
  }
22906
22989
  /**
22907
- * agentId 列出该命名空间下所有 SessionFile(persona:listSubSessions 入口)。
22908
- * agentId 还未访问过 → storeFor 第一次创建对应 SessionStore(root 不存在则 list 返回 [])
22990
+ * 列出指定 persona 在指定 mode 下的所有 SessionFile
22991
+ * persona:listSubSessions RPC 入口(mode='listener');
22992
+ * 路径下还未写过任何 session 时 list() 返回空数组(SessionStore.list 内部 ENOENT 处理)
22909
22993
  */
22910
- listForAgent(agentId) {
22911
- return this.storeFor(agentId).list();
22994
+ listPersonaSessions(personaId, mode) {
22995
+ return this.storeFor({ kind: "persona", personaId, mode }).list();
22912
22996
  }
22913
22997
  /**
22914
22998
  * 创建 sub-session 的 SessionFile + 准备 runner(不 spawn)。
22915
- * subSessionMeta 不进 SessionFile schema,仅缓存进 runner state。
22916
- * 同一 sessionId 重复调用:抛错(PersonaManager 应先调 readForAgent 命中复用)
22999
+ * SubSessionMeta 不进 SessionFile schema,运行时由 scope → metaFromScope 派生。
23000
+ * 同一 sessionId 重复调用:抛错(PersonaManager 应先调 readForScope 命中复用)
22917
23001
  */
22918
- createForAgent(args) {
23002
+ createForScope(args) {
22919
23003
  try {
22920
23004
  const stat = import_node_fs5.default.statSync(args.cwd);
22921
23005
  if (!stat.isDirectory()) throw new Error("not dir");
@@ -22924,9 +23008,11 @@ var SessionManager = class {
22924
23008
  }
22925
23009
  const tool = args.tool ?? "claude";
22926
23010
  this.deps.getAdapter(tool);
22927
- const store = this.storeFor(args.agentId);
23011
+ const store = this.storeFor(args.scope);
22928
23012
  if (store.read(args.sessionId)) {
22929
- throw new Error(`session already exists for agent ${args.agentId}: ${args.sessionId}`);
23013
+ throw new Error(
23014
+ `session already exists for scope ${scopeKey(args.scope)}: ${args.sessionId}`
23015
+ );
22930
23016
  }
22931
23017
  const iso = nowIso2(this.deps);
22932
23018
  const file = {
@@ -22939,11 +23025,7 @@ var SessionManager = class {
22939
23025
  createdAt: iso,
22940
23026
  updatedAt: iso
22941
23027
  };
22942
- const written = store.write(file);
22943
- if (args.subSessionMeta) {
22944
- this.subSessionMetaBySid.set(args.sessionId, args.subSessionMeta);
22945
- }
22946
- return written;
23028
+ return store.write(file);
22947
23029
  }
22948
23030
  /**
22949
23031
  * persona-bound transport 用:读取 sub-session 的历史 ParsedEvent[]。
@@ -22954,22 +23036,21 @@ var SessionManager = class {
22954
23036
  * 不读 jsonl:
22955
23037
  * 1. observer 路径在 spawn 后会自动接管 jsonl 回灌,进 reducer buffer。
22956
23038
  * 2. 第一次握手时 sub-session 还没 spawn → toolSessionId 为空 → jsonl 不存在。
22957
- * sessionFile 不存在抛 SESSION_NOT_FOUND;上层应先调 createForAgent
23039
+ * sessionFile 不存在抛 SESSION_NOT_FOUND;上层应先调 createForScope
22958
23040
  */
22959
- readHistoryEvents(sessionId, agentId) {
22960
- const store = this.storeFor(agentId);
22961
- const file = store.read(sessionId);
23041
+ readHistoryEventsForScope(sessionId, scope) {
23042
+ const file = this.storeFor(scope).read(sessionId);
22962
23043
  if (!file) {
22963
23044
  throw new ClawdError(
22964
23045
  ERROR_CODES.SESSION_NOT_FOUND,
22965
- `sub-session not found: ${agentId}/${sessionId}`
23046
+ `sub-session not found: ${scopeKey(scope)}/${sessionId}`
22966
23047
  );
22967
23048
  }
22968
- const runner = this.ensureRunnerFor(file, agentId);
23049
+ const runner = this.ensureRunnerForScope(file, scope);
22969
23050
  return runner.getState().buffer.map((e) => e.event);
22970
23051
  }
22971
23052
  /**
22972
- * persona-bound transport 用:基于 readHistoryEvents 的 buffer 切片视图,支持分页。
23053
+ * persona-bound transport 用:基于 readHistoryEventsForScope 的 buffer 切片视图,支持分页。
22973
23054
  *
22974
23055
  * Why a new method instead of reusing `history:read` RPC handler:
22975
23056
  * - `history:read` 走 HandlerDeps.history.read(),读 CC 写盘的 jsonl 文件
@@ -22977,18 +23058,15 @@ var SessionManager = class {
22977
23058
  * 两条路径数据形态、时序、字段不同,不能共享 helper。persona-bound 客户端必须
22978
23059
  * 走 buffer 路径,才能保证首屏回放和实时帧无 gap、无重复。
22979
23060
  *
22980
- * Why not 改 readHistoryEvents 加 limit/offset:现有 readHistoryEvents 的语义是
22981
- * "返回 buffer 全部",被其它路径(rewind uuid 转译等)依赖;保留它不动,新加分页方法。
22982
- *
22983
23061
  * 切片语义:clip 安全边界,response.offset 保留请求值便于客户端识别越界请求。
22984
23062
  * - offset >= total → events: [], offset: 请求值, total: 当前 buffer 长度
22985
23063
  * - offset + limit > total → 返回 tail [offset, total),长度 = total - offset
22986
23064
  * - 正常 → 返回 [offset, offset + limit)
22987
23065
  *
22988
- * SESSION_NOT_FOUND 行为继承 readHistoryEvents(store.read 返回 null 即抛)。
23066
+ * SESSION_NOT_FOUND 行为继承 readHistoryEventsForScope(store.read 返回 null 即抛)。
22989
23067
  */
22990
- readHistoryPage(sessionId, agentId, limit, offset) {
22991
- const all = this.readHistoryEvents(sessionId, agentId);
23068
+ readHistoryPageForScope(sessionId, scope, limit, offset) {
23069
+ const all = this.readHistoryEventsForScope(sessionId, scope);
22992
23070
  const total = all.length;
22993
23071
  const start = Math.min(offset, total);
22994
23072
  const end = Math.min(start + limit, total);
@@ -23001,36 +23079,34 @@ var SessionManager = class {
23001
23079
  * 返回 unsubscribe;不破坏现有 wire 广播路径——routeFromRunner 同时 fan-out 到
23002
23080
  * eventSubscribers 和 deps.broadcastFrame
23003
23081
  */
23004
- subscribe(_sessionId, _agentId, listener) {
23005
- const sid = _sessionId;
23006
- let subs = this.eventSubscribers.get(sid);
23082
+ subscribe(sessionId, _scope, listener) {
23083
+ let subs = this.eventSubscribers.get(sessionId);
23007
23084
  if (!subs) {
23008
23085
  subs = /* @__PURE__ */ new Set();
23009
- this.eventSubscribers.set(sid, subs);
23086
+ this.eventSubscribers.set(sessionId, subs);
23010
23087
  }
23011
23088
  subs.add(listener);
23012
23089
  return () => {
23013
- const cur = this.eventSubscribers.get(sid);
23090
+ const cur = this.eventSubscribers.get(sessionId);
23014
23091
  if (!cur) return;
23015
23092
  cur.delete(listener);
23016
- if (cur.size === 0) this.eventSubscribers.delete(sid);
23093
+ if (cur.size === 0) this.eventSubscribers.delete(sessionId);
23017
23094
  };
23018
23095
  }
23019
23096
  /**
23020
- * persona-bound transport 用:sub-session 路径的 send(按 agentId 路由 SessionStore)。
23021
- * 现状 send(args.sessionId, args.text) 默认 'default' agent;这里按 agentId 拿对应 store
23022
- * + ensureRunnerFor 保证 runner 用同一个 store 写盘
23097
+ * persona-bound transport 用:sub-session 路径的 send(按 scope 路由 SessionStore)。
23098
+ * 区别于 default scope 走 SessionManager.send:transport hello 已知 personaId mode,
23099
+ * 显式传 scope 避免跨命名空间 sessionId 撞车。
23023
23100
  */
23024
- sendForAgent(args) {
23025
- const store = this.storeFor(args.agentId);
23026
- const file = store.read(args.sessionId);
23101
+ sendForScope(args) {
23102
+ const file = this.storeFor(args.scope).read(args.sessionId);
23027
23103
  if (!file) {
23028
23104
  throw new ClawdError(
23029
23105
  ERROR_CODES.SESSION_NOT_FOUND,
23030
- `sub-session not found: ${args.agentId}/${args.sessionId}`
23106
+ `sub-session not found: ${scopeKey(args.scope)}/${args.sessionId}`
23031
23107
  );
23032
23108
  }
23033
- const runner = this.ensureRunnerFor(file, args.agentId);
23109
+ const runner = this.ensureRunnerForScope(file, args.scope);
23034
23110
  const { broadcast } = this.withCollector(() => {
23035
23111
  runner.input({ kind: "command", command: { kind: "send", text: args.text } });
23036
23112
  });
@@ -23040,53 +23116,47 @@ var SessionManager = class {
23040
23116
  * persona-bound transport 用:sub-session reset。
23041
23117
  * 复用 reducer 'new' 命令:清 toolSessionId / buffer / nextSeq / pending* + kill proc + emit
23042
23118
  * session:cleared。语义上等价 alice 端"清空当前会话上下文"。
23043
- * 归档已写盘的 jsonl 不在本路径处理(CC 后续 spawn 会写新的 toolSessionId.jsonl,旧的留盘);
23044
- * 物理归档可在后续单独 task 加(spec § 6 待 plan 决定项)。
23119
+ * 归档已写盘的 jsonl 不在本路径处理(CC 后续 spawn 会写新的 toolSessionId.jsonl,旧的留盘)。
23045
23120
  */
23046
- resetForAgent(args) {
23047
- const store = this.storeFor(args.agentId);
23048
- const file = store.read(args.sessionId);
23121
+ resetForScope(args) {
23122
+ const file = this.storeFor(args.scope).read(args.sessionId);
23049
23123
  if (!file) {
23050
23124
  throw new ClawdError(
23051
23125
  ERROR_CODES.SESSION_NOT_FOUND,
23052
- `sub-session not found: ${args.agentId}/${args.sessionId}`
23126
+ `sub-session not found: ${scopeKey(args.scope)}/${args.sessionId}`
23053
23127
  );
23054
23128
  }
23055
- const runner = this.ensureRunnerFor(file, args.agentId);
23129
+ const runner = this.ensureRunnerForScope(file, args.scope);
23056
23130
  const { broadcast } = this.withCollector(() => {
23057
23131
  runner.input({ kind: "command", command: { kind: "new" } });
23058
23132
  });
23059
23133
  return { response: { ok: true }, broadcast };
23060
23134
  }
23061
- /** ensureSession 的 agentId-aware 版本:复用现有 runner 或按 agentId 派生 store 创建 */
23062
- ensureRunnerFor(file, agentId) {
23135
+ /** ensureSession 的 scope-aware 版本:复用现有 runner 或按 scope 创建(含 metaFromScope 派生 meta) */
23136
+ ensureRunnerForScope(file, scope) {
23063
23137
  const existing = this.runners.get(file.sessionId);
23064
23138
  if (existing) return existing;
23065
- const store = this.storeFor(agentId);
23066
- const subSessionMeta = this.resolveSubSessionMeta(file);
23067
- const runner = this.newRunner(file, { store, subSessionMeta });
23139
+ const runner = this.newRunner(file, scope);
23068
23140
  this.runners.set(file.sessionId, runner);
23069
23141
  return runner;
23070
23142
  }
23071
23143
  /**
23072
23144
  * 老板插话:把 'inject-owner-text' input 喂给对应 runner,
23073
- * runner 不存在时按 ensureSession 路径懒创建(以 subSessionMeta 缓存为准)。
23145
+ * runner 不存在时按 scope 懒创建。
23074
23146
  * frames 走异步路径(broadcastFrame):调用方一般在 PersonaManager.appendOwnerMessage
23075
23147
  * 内部走 RPC 处理流,没有同步 collector 上下文
23076
23148
  */
23077
23149
  injectOwnerMessage(args) {
23078
- const store = this.storeFor(args.agentId);
23079
- const file = store.read(args.sessionId);
23150
+ const file = this.storeFor(args.scope).read(args.sessionId);
23080
23151
  if (!file) {
23081
23152
  throw new ClawdError(
23082
23153
  ERROR_CODES.SESSION_NOT_FOUND,
23083
- `sub-session not found: ${args.agentId}/${args.sessionId}`
23154
+ `sub-session not found: ${scopeKey(args.scope)}/${args.sessionId}`
23084
23155
  );
23085
23156
  }
23086
23157
  let runner = this.runners.get(args.sessionId);
23087
23158
  if (!runner) {
23088
- const subSessionMeta = this.resolveSubSessionMeta(file);
23089
- runner = this.newRunner(file, { store, subSessionMeta });
23159
+ runner = this.newRunner(file, args.scope);
23090
23160
  this.runners.set(args.sessionId, runner);
23091
23161
  }
23092
23162
  runner.input({ kind: "inject-owner-text", text: args.text });
@@ -23305,7 +23375,7 @@ var SessionManager = class {
23305
23375
 
23306
23376
  // src/persona/store.ts
23307
23377
  var fs6 = __toESM(require("fs"), 1);
23308
- var path6 = __toESM(require("path"), 1);
23378
+ var path7 = __toESM(require("path"), 1);
23309
23379
  init_protocol();
23310
23380
  var DEFAULT_SETTINGS = {
23311
23381
  permissions: {
@@ -23334,13 +23404,13 @@ var PersonaStore = class {
23334
23404
  }
23335
23405
  root;
23336
23406
  personaDir(personaId) {
23337
- return path6.join(this.root, safeFileName(personaId));
23407
+ return path7.join(this.root, safeFileName(personaId));
23338
23408
  }
23339
23409
  metaPath(personaId) {
23340
- return path6.join(this.personaDir(personaId), ".clawd", "persona.json");
23410
+ return path7.join(this.personaDir(personaId), ".clawd", "persona.json");
23341
23411
  }
23342
23412
  claudeMdPath(personaId) {
23343
- return path6.join(this.personaDir(personaId), "CLAUDE.md");
23413
+ return path7.join(this.personaDir(personaId), "CLAUDE.md");
23344
23414
  }
23345
23415
  /**
23346
23416
  * Sandbox settings 落盘路径 —— 故意放在 `.clawd/` 而不是 `.claude/`,让 CC 的
@@ -23350,11 +23420,11 @@ var PersonaStore = class {
23350
23420
  * 加载 persona 人格,只有 listener 多一层 OS sandbox。
23351
23421
  */
23352
23422
  sandboxSettingsPath(personaId) {
23353
- return path6.join(this.personaDir(personaId), ".clawd", "sandbox-settings.json");
23423
+ return path7.join(this.personaDir(personaId), ".clawd", "sandbox-settings.json");
23354
23424
  }
23355
23425
  write(persona, personality) {
23356
23426
  const dir = this.personaDir(persona.personaId);
23357
- fs6.mkdirSync(path6.join(dir, ".clawd"), { recursive: true });
23427
+ fs6.mkdirSync(path7.join(dir, ".clawd"), { recursive: true });
23358
23428
  this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
23359
23429
  this.atomicWrite(
23360
23430
  this.sandboxSettingsPath(persona.personaId),
@@ -23385,7 +23455,7 @@ var PersonaStore = class {
23385
23455
  list() {
23386
23456
  if (!fs6.existsSync(this.root)) return [];
23387
23457
  return fs6.readdirSync(this.root).filter((name) => {
23388
- return fs6.existsSync(path6.join(this.root, name, ".clawd", "persona.json"));
23458
+ return fs6.existsSync(path7.join(this.root, name, ".clawd", "persona.json"));
23389
23459
  });
23390
23460
  }
23391
23461
  remove(personaId) {
@@ -23547,27 +23617,20 @@ var PersonaManager = class {
23547
23617
  const persona = this.deps.registry.get(personaId);
23548
23618
  if (!persona) throw new Error(`persona not found: ${personaId}`);
23549
23619
  const subSessionId = this.deriveSubSessionId(personaId, token);
23550
- const existing = this.deps.sessionManager.readForAgent(subSessionId, personaId);
23620
+ const scope = { kind: "persona", personaId, mode: "listener" };
23621
+ const existing = this.deps.sessionManager.readForScope(subSessionId, scope);
23551
23622
  if (existing) {
23552
23623
  return { sessionFile: existing, isNew: false };
23553
23624
  }
23554
23625
  const tokenEntry = persona.tokenMap[token];
23555
23626
  const subLabel = tokenEntry?.label ?? "unknown";
23556
- const sessionFile = this.deps.sessionManager.createForAgent({
23627
+ const sessionFile = this.deps.sessionManager.createForScope({
23557
23628
  sessionId: subSessionId,
23558
- agentId: personaId,
23629
+ scope,
23559
23630
  cwd: this.deps.store.personaDirPath(personaId),
23560
23631
  tool: "claude",
23561
23632
  label: subLabel,
23562
- model: persona.model,
23563
- // listener 走 OS sandbox:sandbox JSON 不在 project 自动发现路径上(PersonaStore 把它
23564
- // 落在 .clawd/sandbox-settings.json),靠 extraSettings 透传到 spawn 的 `--settings <file>`
23565
- // 显式拉回。owner 路径不传 extraSettings,天然无 sandbox。
23566
- subSessionMeta: {
23567
- idleKillEnabled: true,
23568
- personaMode: "listener",
23569
- extraSettings: this.deps.store.sandboxSettingsPath(personaId)
23570
- }
23633
+ model: persona.model
23571
23634
  });
23572
23635
  return { sessionFile, isNew: true };
23573
23636
  }
@@ -23578,7 +23641,7 @@ var PersonaManager = class {
23578
23641
  appendOwnerMessage(personaId, subSessionId, text) {
23579
23642
  this.deps.sessionManager.injectOwnerMessage({
23580
23643
  sessionId: subSessionId,
23581
- agentId: personaId,
23644
+ scope: { kind: "persona", personaId, mode: "listener" },
23582
23645
  text
23583
23646
  });
23584
23647
  }
@@ -23605,13 +23668,123 @@ var PersonaManager = class {
23605
23668
  }
23606
23669
  };
23607
23670
 
23671
+ // src/persona/seed.ts
23672
+ var fs7 = __toESM(require("fs"), 1);
23673
+ var path8 = __toESM(require("path"), 1);
23674
+ var import_node_url = require("url");
23675
+ var import_meta = {};
23676
+ var DEFAULT_PERSONAS = [
23677
+ {
23678
+ personaId: "persona-researcher",
23679
+ label: "\u8C03\u7814\u5458",
23680
+ model: "opus",
23681
+ iconKey: "research",
23682
+ public: false
23683
+ },
23684
+ {
23685
+ personaId: "persona-knowledge-base",
23686
+ label: "\u77E5\u8BC6\u5E93\u7BA1\u7406\u5458",
23687
+ model: "opus",
23688
+ iconKey: "reading",
23689
+ public: false
23690
+ },
23691
+ {
23692
+ personaId: "persona-clawd-helper",
23693
+ label: "clawd\u4F7F\u7528\u52A9\u624B",
23694
+ model: "opus",
23695
+ iconKey: "assist",
23696
+ public: false
23697
+ },
23698
+ {
23699
+ personaId: "persona-feishu-assistant",
23700
+ label: "\u98DE\u4E66\u52A9\u7406",
23701
+ model: "opus",
23702
+ iconKey: "assist",
23703
+ public: false
23704
+ }
23705
+ ];
23706
+ function findDefaultsRoot() {
23707
+ const candidates = [];
23708
+ try {
23709
+ const here = path8.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
23710
+ candidates.push(path8.resolve(here, "defaults"));
23711
+ candidates.push(path8.resolve(here, "persona-defaults"));
23712
+ } catch {
23713
+ }
23714
+ if (process.argv[1]) {
23715
+ const argvDir = path8.dirname(process.argv[1]);
23716
+ candidates.push(path8.resolve(argvDir, "persona-defaults"));
23717
+ }
23718
+ for (const c of candidates) {
23719
+ try {
23720
+ if (fs7.statSync(c).isDirectory()) return c;
23721
+ } catch {
23722
+ }
23723
+ }
23724
+ return null;
23725
+ }
23726
+ function seedDefaultPersonas(args) {
23727
+ const entries = args.entries ?? DEFAULT_PERSONAS;
23728
+ for (const entry of entries) {
23729
+ if (args.store.has(entry.personaId)) {
23730
+ args.logger.info("persona.seed.skip", { personaId: entry.personaId, reason: "exists" });
23731
+ continue;
23732
+ }
23733
+ const bundleDir = path8.join(args.defaultsRoot, entry.personaId);
23734
+ if (!fs7.existsSync(bundleDir)) {
23735
+ args.logger.warn("persona.seed.skip", {
23736
+ personaId: entry.personaId,
23737
+ reason: "bundle-missing",
23738
+ bundleDir
23739
+ });
23740
+ continue;
23741
+ }
23742
+ const claudeMdPath = path8.join(bundleDir, "CLAUDE.md");
23743
+ if (!fs7.existsSync(claudeMdPath)) {
23744
+ args.logger.warn("persona.seed.skip", {
23745
+ personaId: entry.personaId,
23746
+ reason: "no-CLAUDE.md",
23747
+ bundleDir
23748
+ });
23749
+ continue;
23750
+ }
23751
+ const personality = fs7.readFileSync(claudeMdPath, "utf8");
23752
+ const now = Date.now();
23753
+ const persona = {
23754
+ personaId: entry.personaId,
23755
+ label: entry.label,
23756
+ model: entry.model,
23757
+ public: entry.public,
23758
+ iconKey: entry.iconKey,
23759
+ tokenMap: {},
23760
+ createdAt: now,
23761
+ updatedAt: now
23762
+ };
23763
+ args.store.write(persona, personality);
23764
+ copyBundleExtras(bundleDir, args.store.personaDirPath(entry.personaId));
23765
+ args.logger.info("persona.seed.created", { personaId: entry.personaId });
23766
+ }
23767
+ }
23768
+ function copyBundleExtras(srcDir, dstDir) {
23769
+ for (const entry of fs7.readdirSync(srcDir, { withFileTypes: true })) {
23770
+ if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
23771
+ const srcPath = path8.join(srcDir, entry.name);
23772
+ const dstPath = path8.join(dstDir, entry.name);
23773
+ if (entry.isDirectory()) {
23774
+ fs7.cpSync(srcPath, dstPath, { recursive: true, dereference: true });
23775
+ } else if (entry.isFile()) {
23776
+ fs7.copyFileSync(srcPath, dstPath);
23777
+ }
23778
+ }
23779
+ }
23780
+
23608
23781
  // src/index.ts
23609
23782
  init_claude();
23610
23783
 
23611
23784
  // src/tools/claude-tui.ts
23612
23785
  var import_node_fs8 = __toESM(require("fs"), 1);
23613
23786
  var import_node_os4 = __toESM(require("os"), 1);
23614
- var import_node_path8 = __toESM(require("path"), 1);
23787
+ var import_node_path9 = __toESM(require("path"), 1);
23615
23788
  var headlessNs = __toESM(require_xterm_headless(), 1);
23616
23789
  var serializeNs = __toESM(require_addon_serialize(), 1);
23617
23790
  init_claude();
@@ -23845,10 +24018,10 @@ function createPopupDetector(opts) {
23845
24018
  return visible;
23846
24019
  },
23847
24020
  writeBytes(data) {
23848
- return new Promise((resolve) => {
24021
+ return new Promise((resolve2) => {
23849
24022
  term.write(data, () => {
23850
24023
  tick();
23851
- resolve();
24024
+ resolve2();
23852
24025
  });
23853
24026
  });
23854
24027
  },
@@ -24065,7 +24238,7 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
24065
24238
  function jsonlExistsForCtx(ctx) {
24066
24239
  if (!ctx.toolSessionId) return false;
24067
24240
  const home = import_node_os4.default.homedir();
24068
- const file = import_node_path8.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
24241
+ const file = import_node_path9.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
24069
24242
  try {
24070
24243
  return import_node_fs8.default.statSync(file).isFile();
24071
24244
  } catch {
@@ -24079,14 +24252,14 @@ init_claude_history();
24079
24252
  // src/workspace/browser.ts
24080
24253
  var import_node_fs9 = __toESM(require("fs"), 1);
24081
24254
  var import_node_os5 = __toESM(require("os"), 1);
24082
- var import_node_path9 = __toESM(require("path"), 1);
24255
+ var import_node_path10 = __toESM(require("path"), 1);
24083
24256
  init_protocol();
24084
24257
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
24085
24258
  function resolveInsideCwd(cwd, subpath) {
24086
- const absCwd = import_node_path9.default.resolve(cwd);
24087
- const joined = import_node_path9.default.resolve(absCwd, subpath ?? ".");
24088
- const rel = import_node_path9.default.relative(absCwd, joined);
24089
- if (rel.startsWith("..") || import_node_path9.default.isAbsolute(rel)) {
24259
+ const absCwd = import_node_path10.default.resolve(cwd);
24260
+ const joined = import_node_path10.default.resolve(absCwd, subpath ?? ".");
24261
+ const rel = import_node_path10.default.relative(absCwd, joined);
24262
+ if (rel.startsWith("..") || import_node_path10.default.isAbsolute(rel)) {
24090
24263
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
24091
24264
  }
24092
24265
  return joined;
@@ -24117,7 +24290,7 @@ var WorkspaceBrowser = class {
24117
24290
  mtime: ""
24118
24291
  };
24119
24292
  try {
24120
- const st = import_node_fs9.default.statSync(import_node_path9.default.join(full, d.name));
24293
+ const st = import_node_fs9.default.statSync(import_node_path10.default.join(full, d.name));
24121
24294
  entry.mtime = new Date(st.mtimeMs).toISOString();
24122
24295
  if (d.isFile()) entry.size = st.size;
24123
24296
  } catch {
@@ -24164,7 +24337,7 @@ var WorkspaceBrowser = class {
24164
24337
  // src/skills/scanner.ts
24165
24338
  var import_node_fs10 = __toESM(require("fs"), 1);
24166
24339
  var import_node_os6 = __toESM(require("os"), 1);
24167
- var import_node_path10 = __toESM(require("path"), 1);
24340
+ var import_node_path11 = __toESM(require("path"), 1);
24168
24341
 
24169
24342
  // src/skills/frontmatter.ts
24170
24343
  var STRIP_QUOTES = /^["']|["']$/g;
@@ -24286,14 +24459,14 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
24286
24459
  return;
24287
24460
  }
24288
24461
  for (const ent of entries) {
24289
- const entryPath = import_node_path10.default.join(dir, ent.name);
24462
+ const entryPath = import_node_path11.default.join(dir, ent.name);
24290
24463
  if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
24291
24464
  let content;
24292
24465
  try {
24293
- content = import_node_fs10.default.readFileSync(import_node_path10.default.join(entryPath, "SKILL.md"), "utf8");
24466
+ content = import_node_fs10.default.readFileSync(import_node_path11.default.join(entryPath, "SKILL.md"), "utf8");
24294
24467
  } catch {
24295
24468
  try {
24296
- content = import_node_fs10.default.readFileSync(import_node_path10.default.join(entryPath, "skill.md"), "utf8");
24469
+ content = import_node_fs10.default.readFileSync(import_node_path11.default.join(entryPath, "skill.md"), "utf8");
24297
24470
  } catch {
24298
24471
  continue;
24299
24472
  }
@@ -24316,7 +24489,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
24316
24489
  return;
24317
24490
  }
24318
24491
  for (const ent of entries) {
24319
- const entryPath = import_node_path10.default.join(dir, ent.name);
24492
+ const entryPath = import_node_path11.default.join(dir, ent.name);
24320
24493
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
24321
24494
  const ns = ent.name;
24322
24495
  let subEntries;
@@ -24327,7 +24500,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
24327
24500
  }
24328
24501
  for (const se of subEntries) {
24329
24502
  if (!se.name.endsWith(".md")) continue;
24330
- const sePath = import_node_path10.default.join(entryPath, se.name);
24503
+ const sePath = import_node_path11.default.join(entryPath, se.name);
24331
24504
  let content;
24332
24505
  try {
24333
24506
  content = import_node_fs10.default.readFileSync(sePath, "utf8");
@@ -24363,7 +24536,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
24363
24536
  }
24364
24537
  }
24365
24538
  function readInstalledPlugins(home) {
24366
- const file = import_node_path10.default.join(home, ".claude", "plugins", "installed_plugins.json");
24539
+ const file = import_node_path11.default.join(home, ".claude", "plugins", "installed_plugins.json");
24367
24540
  let raw;
24368
24541
  try {
24369
24542
  raw = import_node_fs10.default.readFileSync(file, "utf8");
@@ -24414,14 +24587,14 @@ var SkillsScanner = class {
24414
24587
  });
24415
24588
  }
24416
24589
  const fsBlock = [];
24417
- scanSkillDir(import_node_path10.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
24418
- scanCommandDir(import_node_path10.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
24419
- scanSkillDir(import_node_path10.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
24420
- scanCommandDir(import_node_path10.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
24590
+ scanSkillDir(import_node_path11.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
24591
+ scanCommandDir(import_node_path11.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
24592
+ scanSkillDir(import_node_path11.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
24593
+ scanCommandDir(import_node_path11.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
24421
24594
  const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
24422
24595
  for (const { name, root } of plugins) {
24423
- scanSkillDir(import_node_path10.default.join(root, "skills"), "plugin", seen, fsBlock, name);
24424
- scanCommandDir(import_node_path10.default.join(root, "commands"), "plugin", seen, fsBlock, name);
24596
+ scanSkillDir(import_node_path11.default.join(root, "skills"), "plugin", seen, fsBlock, name);
24597
+ scanCommandDir(import_node_path11.default.join(root, "commands"), "plugin", seen, fsBlock, name);
24425
24598
  }
24426
24599
  fsBlock.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
24427
24600
  return [...builtinBlock, ...fsBlock];
@@ -24431,7 +24604,7 @@ var SkillsScanner = class {
24431
24604
  // src/skills/agents-scanner.ts
24432
24605
  var import_node_fs11 = __toESM(require("fs"), 1);
24433
24606
  var import_node_os7 = __toESM(require("os"), 1);
24434
- var import_node_path11 = __toESM(require("path"), 1);
24607
+ var import_node_path12 = __toESM(require("path"), 1);
24435
24608
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
24436
24609
  function isDirLikeSync2(p) {
24437
24610
  try {
@@ -24469,10 +24642,10 @@ function scanAgentsDir(dir, source, seen, out) {
24469
24642
  }
24470
24643
  for (const ent of entries) {
24471
24644
  if (!ent.name.endsWith(".md")) continue;
24472
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path11.default.join(dir, ent.name)))) {
24645
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path12.default.join(dir, ent.name)))) {
24473
24646
  continue;
24474
24647
  }
24475
- const filePath = import_node_path11.default.join(dir, ent.name);
24648
+ const filePath = import_node_path12.default.join(dir, ent.name);
24476
24649
  const baseName = ent.name.replace(/\.md$/, "");
24477
24650
  if (seen.has(baseName)) continue;
24478
24651
  seen.add(baseName);
@@ -24495,7 +24668,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
24495
24668
  return;
24496
24669
  }
24497
24670
  for (const ent of entries) {
24498
- const childPath = import_node_path11.default.join(dir, ent.name);
24671
+ const childPath = import_node_path12.default.join(dir, ent.name);
24499
24672
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
24500
24673
  walk(childPath, [...namespaces, ent.name]);
24501
24674
  continue;
@@ -24520,9 +24693,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
24520
24693
  walk(root, []);
24521
24694
  }
24522
24695
  function readInstalledPlugins2(home) {
24523
- const pluginsDir = import_node_path11.default.join(home, ".claude", "plugins");
24524
- const v2 = import_node_path11.default.join(pluginsDir, "installed_plugins_v2.json");
24525
- const v1 = import_node_path11.default.join(pluginsDir, "installed_plugins.json");
24696
+ const pluginsDir = import_node_path12.default.join(home, ".claude", "plugins");
24697
+ const v2 = import_node_path12.default.join(pluginsDir, "installed_plugins_v2.json");
24698
+ const v1 = import_node_path12.default.join(pluginsDir, "installed_plugins.json");
24526
24699
  let raw = null;
24527
24700
  for (const candidate of [v2, v1]) {
24528
24701
  try {
@@ -24551,19 +24724,19 @@ function readInstalledPlugins2(home) {
24551
24724
  return out;
24552
24725
  }
24553
24726
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
24554
- let cur = import_node_path11.default.resolve(startCwd);
24555
- const fsRoot = import_node_path11.default.parse(cur).root;
24727
+ let cur = import_node_path12.default.resolve(startCwd);
24728
+ const fsRoot = import_node_path12.default.parse(cur).root;
24556
24729
  while (true) {
24557
- scanAgentsDir(import_node_path11.default.join(cur, ".claude", "agents"), "project", seen, out);
24730
+ scanAgentsDir(import_node_path12.default.join(cur, ".claude", "agents"), "project", seen, out);
24558
24731
  let hasGit = false;
24559
24732
  try {
24560
- hasGit = import_node_fs11.default.existsSync(import_node_path11.default.join(cur, ".git"));
24733
+ hasGit = import_node_fs11.default.existsSync(import_node_path12.default.join(cur, ".git"));
24561
24734
  } catch {
24562
24735
  }
24563
24736
  if (hasGit) return;
24564
24737
  if (cur === home) return;
24565
24738
  if (cur === fsRoot) return;
24566
- const parent = import_node_path11.default.dirname(cur);
24739
+ const parent = import_node_path12.default.dirname(cur);
24567
24740
  if (parent === cur) return;
24568
24741
  cur = parent;
24569
24742
  }
@@ -24598,7 +24771,7 @@ var AgentsScanner = class {
24598
24771
  }
24599
24772
  const fsBlock = [];
24600
24773
  scanAgentsDir(
24601
- import_node_path11.default.join(this.home, ".claude", "agents"),
24774
+ import_node_path12.default.join(this.home, ".claude", "agents"),
24602
24775
  "global",
24603
24776
  seen,
24604
24777
  fsBlock
@@ -24612,7 +24785,7 @@ var AgentsScanner = class {
24612
24785
  ...this.extraPluginRoots
24613
24786
  ];
24614
24787
  for (const { name, root } of plugins) {
24615
- const agentsRoot = import_node_path11.default.join(root, "agents");
24788
+ const agentsRoot = import_node_path12.default.join(root, "agents");
24616
24789
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
24617
24790
  }
24618
24791
  return [...builtinBlock, ...fsBlock];
@@ -24622,7 +24795,7 @@ var AgentsScanner = class {
24622
24795
  // src/observer/session-observer.ts
24623
24796
  var import_node_fs12 = __toESM(require("fs"), 1);
24624
24797
  var import_node_os8 = __toESM(require("os"), 1);
24625
- var import_node_path12 = __toESM(require("path"), 1);
24798
+ var import_node_path13 = __toESM(require("path"), 1);
24626
24799
  init_claude_history();
24627
24800
  var SessionObserver = class {
24628
24801
  constructor(opts) {
@@ -24634,7 +24807,7 @@ var SessionObserver = class {
24634
24807
  watches = /* @__PURE__ */ new Map();
24635
24808
  resolveJsonlPath(cwd, toolSessionId, override) {
24636
24809
  if (override) return override;
24637
- return import_node_path12.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
24810
+ return import_node_path13.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
24638
24811
  }
24639
24812
  start(args) {
24640
24813
  this.stop(args.sessionId);
@@ -24654,10 +24827,10 @@ var SessionObserver = class {
24654
24827
  adapter: args.adapter
24655
24828
  };
24656
24829
  try {
24657
- import_node_fs12.default.mkdirSync(import_node_path12.default.dirname(filePath), { recursive: true });
24830
+ import_node_fs12.default.mkdirSync(import_node_path13.default.dirname(filePath), { recursive: true });
24658
24831
  } catch {
24659
24832
  }
24660
- w.watcher = import_node_fs12.default.watch(import_node_path12.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
24833
+ w.watcher = import_node_fs12.default.watch(import_node_path13.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
24661
24834
  if (!changedName || !filePath.endsWith(changedName)) return;
24662
24835
  this.poll(w);
24663
24836
  });
@@ -24839,7 +25012,7 @@ var LocalWsServer = class {
24839
25012
  pingIntervalMs;
24840
25013
  async start() {
24841
25014
  const host = this.opts.host ?? "127.0.0.1";
24842
- await new Promise((resolve, reject) => {
25015
+ await new Promise((resolve2, reject) => {
24843
25016
  const wss = new import_websocket_server.default({
24844
25017
  host,
24845
25018
  port: this.opts.port,
@@ -24847,7 +25020,7 @@ var LocalWsServer = class {
24847
25020
  });
24848
25021
  wss.on("listening", () => {
24849
25022
  this.logger?.info("ws listening", { host, port: this.opts.port });
24850
- resolve();
25023
+ resolve2();
24851
25024
  });
24852
25025
  wss.on("error", (err) => {
24853
25026
  this.logger?.error("ws server error", { err: err.message });
@@ -24867,8 +25040,8 @@ var LocalWsServer = class {
24867
25040
  if (c.pingTimer) clearInterval(c.pingTimer);
24868
25041
  }
24869
25042
  this.clients.clear();
24870
- await new Promise((resolve) => {
24871
- this.wss?.close(() => resolve());
25043
+ await new Promise((resolve2) => {
25044
+ this.wss?.close(() => resolve2());
24872
25045
  });
24873
25046
  this.wss = null;
24874
25047
  }
@@ -25179,13 +25352,18 @@ var PersonaBoundHandler = class {
25179
25352
  }
25180
25353
  return true;
25181
25354
  };
25355
+ const listenerScope = () => ({
25356
+ kind: "persona",
25357
+ personaId: scope.personaId,
25358
+ mode: "listener"
25359
+ });
25182
25360
  switch (type) {
25183
25361
  case "session:subscribe": {
25184
25362
  if (!requireScopedSession()) return;
25185
25363
  if (unsubscribe) unsubscribe();
25186
25364
  unsubscribe = this.deps.sessionManager.subscribe(
25187
25365
  scope.subSessionId,
25188
- scope.personaId,
25366
+ listenerScope(),
25189
25367
  (eventFrame) => send(eventFrame)
25190
25368
  );
25191
25369
  if (requestId)
@@ -25215,9 +25393,9 @@ var PersonaBoundHandler = class {
25215
25393
  return;
25216
25394
  }
25217
25395
  try {
25218
- this.deps.sessionManager.sendForAgent({
25396
+ this.deps.sessionManager.sendForScope({
25219
25397
  sessionId: scope.subSessionId,
25220
- agentId: scope.personaId,
25398
+ scope: listenerScope(),
25221
25399
  text
25222
25400
  });
25223
25401
  if (requestId) send({ type: "session:send", ok: true, requestId });
@@ -25230,9 +25408,9 @@ var PersonaBoundHandler = class {
25230
25408
  case "session:new": {
25231
25409
  if (!requireScopedSession()) return;
25232
25410
  try {
25233
- this.deps.sessionManager.resetForAgent({
25411
+ this.deps.sessionManager.resetForScope({
25234
25412
  sessionId: scope.subSessionId,
25235
- agentId: scope.personaId
25413
+ scope: listenerScope()
25236
25414
  });
25237
25415
  if (requestId) send({ type: "session:info", sessionId: scope.subSessionId, requestId });
25238
25416
  } catch (err) {
@@ -25246,9 +25424,9 @@ var PersonaBoundHandler = class {
25246
25424
  const limit = typeof frame.limit === "number" && frame.limit > 0 ? frame.limit : 50;
25247
25425
  const offset = typeof frame.offset === "number" && frame.offset >= 0 ? frame.offset : 0;
25248
25426
  try {
25249
- const page = this.deps.sessionManager.readHistoryPage(
25427
+ const page = this.deps.sessionManager.readHistoryPageForScope(
25250
25428
  scope.subSessionId,
25251
- scope.personaId,
25429
+ listenerScope(),
25252
25430
  limit,
25253
25431
  offset
25254
25432
  );
@@ -25379,9 +25557,9 @@ function isLocalhost(addr) {
25379
25557
 
25380
25558
  // src/discovery/state-file.ts
25381
25559
  var import_node_fs13 = __toESM(require("fs"), 1);
25382
- var import_node_path13 = __toESM(require("path"), 1);
25560
+ var import_node_path14 = __toESM(require("path"), 1);
25383
25561
  function defaultStateFilePath(dataDir) {
25384
- return import_node_path13.default.join(dataDir, "state.json");
25562
+ return import_node_path14.default.join(dataDir, "state.json");
25385
25563
  }
25386
25564
  function isPidAlive(pid) {
25387
25565
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -25417,7 +25595,7 @@ var StateFileManager = class {
25417
25595
  return { status: "stale", existing };
25418
25596
  }
25419
25597
  write(state) {
25420
- import_node_fs13.default.mkdirSync(import_node_path13.default.dirname(this.file), { recursive: true });
25598
+ import_node_fs13.default.mkdirSync(import_node_path14.default.dirname(this.file), { recursive: true });
25421
25599
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
25422
25600
  import_node_fs13.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
25423
25601
  import_node_fs13.default.renameSync(tmp, this.file);
@@ -25438,13 +25616,13 @@ var StateFileManager = class {
25438
25616
 
25439
25617
  // src/tunnel/tunnel-manager.ts
25440
25618
  var import_node_fs16 = __toESM(require("fs"), 1);
25441
- var import_node_path16 = __toESM(require("path"), 1);
25619
+ var import_node_path17 = __toESM(require("path"), 1);
25442
25620
  var import_node_crypto4 = __toESM(require("crypto"), 1);
25443
25621
  var import_node_child_process4 = require("child_process");
25444
25622
 
25445
25623
  // src/tunnel/tunnel-store.ts
25446
25624
  var import_node_fs14 = __toESM(require("fs"), 1);
25447
- var import_node_path14 = __toESM(require("path"), 1);
25625
+ var import_node_path15 = __toESM(require("path"), 1);
25448
25626
  var TunnelStore = class {
25449
25627
  constructor(filePath) {
25450
25628
  this.filePath = filePath;
@@ -25463,7 +25641,7 @@ var TunnelStore = class {
25463
25641
  }
25464
25642
  }
25465
25643
  async set(v) {
25466
- const dir = import_node_path14.default.dirname(this.filePath);
25644
+ const dir = import_node_path15.default.dirname(this.filePath);
25467
25645
  await import_node_fs14.default.promises.mkdir(dir, { recursive: true });
25468
25646
  const data = JSON.stringify(v, null, 2);
25469
25647
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
@@ -25575,7 +25753,7 @@ function escape(v) {
25575
25753
  // src/tunnel/frpc-binary.ts
25576
25754
  var import_node_fs15 = __toESM(require("fs"), 1);
25577
25755
  var import_node_os9 = __toESM(require("os"), 1);
25578
- var import_node_path15 = __toESM(require("path"), 1);
25756
+ var import_node_path16 = __toESM(require("path"), 1);
25579
25757
  var import_node_child_process3 = require("child_process");
25580
25758
  var import_node_stream2 = require("stream");
25581
25759
  var import_promises = require("stream/promises");
@@ -25614,13 +25792,13 @@ async function ensureFrpcBinary(opts) {
25614
25792
  }
25615
25793
  const version2 = opts.version ?? FRPC_VERSION;
25616
25794
  const platform = opts.platform ?? detectPlatform();
25617
- const binDir = import_node_path15.default.join(opts.dataDir, "bin");
25795
+ const binDir = import_node_path16.default.join(opts.dataDir, "bin");
25618
25796
  import_node_fs15.default.mkdirSync(binDir, { recursive: true });
25619
25797
  cleanupStaleArtifacts(binDir);
25620
- const stableBin = import_node_path15.default.join(binDir, "frpc");
25798
+ const stableBin = import_node_path16.default.join(binDir, "frpc");
25621
25799
  if (import_node_fs15.default.existsSync(stableBin)) return stableBin;
25622
25800
  const partialBin = `${stableBin}.partial`;
25623
- const tarballPath = import_node_path15.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
25801
+ const tarballPath = import_node_path16.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
25624
25802
  try {
25625
25803
  const url = frpcDownloadUrl(version2, platform);
25626
25804
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -25646,7 +25824,7 @@ function cleanupStaleArtifacts(binDir) {
25646
25824
  }
25647
25825
  for (const name of entries) {
25648
25826
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
25649
- const full = import_node_path15.default.join(binDir, name);
25827
+ const full = import_node_path16.default.join(binDir, name);
25650
25828
  try {
25651
25829
  import_node_fs15.default.rmSync(full, { recursive: true, force: true });
25652
25830
  } catch {
@@ -25672,16 +25850,16 @@ async function downloadToFile(url, dest, fetchImpl) {
25672
25850
  await (0, import_promises.pipeline)(nodeStream, out);
25673
25851
  }
25674
25852
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
25675
- const work = import_node_path15.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
25853
+ const work = import_node_path16.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
25676
25854
  import_node_fs15.default.mkdirSync(work, { recursive: true });
25677
25855
  try {
25678
- await new Promise((resolve, reject) => {
25856
+ await new Promise((resolve2, reject) => {
25679
25857
  const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
25680
25858
  proc.on("error", reject);
25681
- proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
25859
+ proc.on("exit", (code) => code === 0 ? resolve2() : reject(new Error(`tar exited ${code}`)));
25682
25860
  });
25683
25861
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
25684
- const src = import_node_path15.default.join(work, dirName, "frpc");
25862
+ const src = import_node_path16.default.join(work, dirName, "frpc");
25685
25863
  if (!import_node_fs15.default.existsSync(src)) {
25686
25864
  throw new Error(`frpc not found inside tarball at ${src}`);
25687
25865
  }
@@ -25696,7 +25874,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
25696
25874
  var TunnelManager = class {
25697
25875
  constructor(deps) {
25698
25876
  this.deps = deps;
25699
- this.store = deps.store ?? new TunnelStore(import_node_path16.default.join(deps.dataDir, "tunnel.json"));
25877
+ this.store = deps.store ?? new TunnelStore(import_node_path17.default.join(deps.dataDir, "tunnel.json"));
25700
25878
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
25701
25879
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
25702
25880
  }
@@ -25756,17 +25934,17 @@ var TunnelManager = class {
25756
25934
  this.proc = null;
25757
25935
  if (!proc) return;
25758
25936
  proc.kill("SIGTERM");
25759
- await new Promise((resolve) => {
25937
+ await new Promise((resolve2) => {
25760
25938
  const t = setTimeout(() => {
25761
25939
  try {
25762
25940
  proc.kill("SIGKILL");
25763
25941
  } catch {
25764
25942
  }
25765
- resolve();
25943
+ resolve2();
25766
25944
  }, 5e3);
25767
25945
  proc.once("exit", () => {
25768
25946
  clearTimeout(t);
25769
- resolve();
25947
+ resolve2();
25770
25948
  });
25771
25949
  });
25772
25950
  }
@@ -25813,7 +25991,7 @@ var TunnelManager = class {
25813
25991
  dataDir: this.deps.dataDir,
25814
25992
  override: this.deps.frpcBinaryOverride ?? void 0
25815
25993
  });
25816
- const tomlPath = import_node_path16.default.join(this.deps.dataDir, "frpc.toml");
25994
+ const tomlPath = import_node_path17.default.join(this.deps.dataDir, "frpc.toml");
25817
25995
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto4.default.randomBytes(3).toString("hex")}`;
25818
25996
  const toml = buildFrpcToml({
25819
25997
  serverAddr: t.frpsHost,
@@ -25828,7 +26006,7 @@ var TunnelManager = class {
25828
26006
  const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
25829
26007
  stdio: ["ignore", "pipe", "pipe"]
25830
26008
  });
25831
- const logFilePath = import_node_path16.default.join(this.deps.dataDir, "frpc.log");
26009
+ const logFilePath = import_node_path17.default.join(this.deps.dataDir, "frpc.log");
25832
26010
  const logStream = import_node_fs16.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
25833
26011
  logStream.on("error", () => {
25834
26012
  });
@@ -25867,14 +26045,14 @@ function formatFrpcTail(raw, maxLines = 12) {
25867
26045
  return ["\u2500\u2500\u2500 frpc output (last lines) \u2500\u2500\u2500", tail, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"].join("\n");
25868
26046
  }
25869
26047
  async function waitForFrpcReady(proc, timeoutMs) {
25870
- return new Promise((resolve) => {
26048
+ return new Promise((resolve2) => {
25871
26049
  let settled = false;
25872
26050
  let buf = "";
25873
26051
  const finish = (r) => {
25874
26052
  if (settled) return;
25875
26053
  settled = true;
25876
26054
  cleanup();
25877
- resolve(r);
26055
+ resolve2(r);
25878
26056
  };
25879
26057
  const onData = (chunk) => {
25880
26058
  buf += String(chunk);
@@ -25922,11 +26100,11 @@ function deriveStableDeviceKey(opts = {}) {
25922
26100
 
25923
26101
  // src/auth-store.ts
25924
26102
  var import_node_fs17 = __toESM(require("fs"), 1);
25925
- var import_node_path17 = __toESM(require("path"), 1);
26103
+ var import_node_path18 = __toESM(require("path"), 1);
25926
26104
  var import_node_crypto6 = __toESM(require("crypto"), 1);
25927
26105
  var AUTH_FILE_NAME = "auth.json";
25928
26106
  function authFilePath(dataDir) {
25929
- return import_node_path17.default.join(dataDir, AUTH_FILE_NAME);
26107
+ return import_node_path18.default.join(dataDir, AUTH_FILE_NAME);
25930
26108
  }
25931
26109
  function loadOrCreateAuthToken(opts) {
25932
26110
  const file = authFilePath(opts.dataDir);
@@ -25958,7 +26136,7 @@ function readAuthFile(file) {
25958
26136
  }
25959
26137
  }
25960
26138
  function writeAuthFile(file, content) {
25961
- import_node_fs17.default.mkdirSync(import_node_path17.default.dirname(file), { recursive: true });
26139
+ import_node_fs17.default.mkdirSync(import_node_path18.default.dirname(file), { recursive: true });
25962
26140
  import_node_fs17.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
25963
26141
  try {
25964
26142
  import_node_fs17.default.chmodSync(file, 384);
@@ -25966,6 +26144,38 @@ function writeAuthFile(file, content) {
25966
26144
  }
25967
26145
  }
25968
26146
 
26147
+ // src/owner-profile.ts
26148
+ var import_node_fs18 = __toESM(require("fs"), 1);
26149
+ var import_node_os11 = __toESM(require("os"), 1);
26150
+ var import_node_path19 = __toESM(require("path"), 1);
26151
+ var PROFILE_FILENAME = "profile.json";
26152
+ function loadOwnerDisplayName(dataDir) {
26153
+ const fallback = import_node_os11.default.userInfo().username;
26154
+ const profilePath = import_node_path19.default.join(dataDir, PROFILE_FILENAME);
26155
+ let raw;
26156
+ try {
26157
+ raw = import_node_fs18.default.readFileSync(profilePath, "utf8");
26158
+ } catch {
26159
+ return fallback;
26160
+ }
26161
+ let parsed;
26162
+ try {
26163
+ parsed = JSON.parse(raw);
26164
+ } catch (err) {
26165
+ console.warn(`[owner-profile] ${PROFILE_FILENAME} parse failed, falling back to OS username:`, err);
26166
+ return fallback;
26167
+ }
26168
+ if (!parsed || typeof parsed !== "object") return fallback;
26169
+ const displayName = parsed.displayName;
26170
+ if (typeof displayName !== "string" || displayName.length === 0) {
26171
+ if (displayName !== void 0) {
26172
+ console.warn(`[owner-profile] displayName must be non-empty string, falling back to OS username`);
26173
+ }
26174
+ return fallback;
26175
+ }
26176
+ return displayName;
26177
+ }
26178
+
25969
26179
  // src/index.ts
25970
26180
  init_protocol();
25971
26181
 
@@ -25973,12 +26183,12 @@ init_protocol();
25973
26183
  init_protocol();
25974
26184
 
25975
26185
  // src/session/fork.ts
25976
- var import_node_fs18 = __toESM(require("fs"), 1);
25977
- var import_node_os11 = __toESM(require("os"), 1);
25978
- var import_node_path18 = __toESM(require("path"), 1);
26186
+ var import_node_fs19 = __toESM(require("fs"), 1);
26187
+ var import_node_os12 = __toESM(require("os"), 1);
26188
+ var import_node_path20 = __toESM(require("path"), 1);
25979
26189
  init_claude_history();
25980
26190
  function readJsonlEntries(file) {
25981
- const raw = import_node_fs18.default.readFileSync(file, "utf8");
26191
+ const raw = import_node_fs19.default.readFileSync(file, "utf8");
25982
26192
  const out = [];
25983
26193
  for (const line of raw.split("\n")) {
25984
26194
  const t = line.trim();
@@ -25991,10 +26201,10 @@ function readJsonlEntries(file) {
25991
26201
  return out;
25992
26202
  }
25993
26203
  function forkSession(input) {
25994
- const baseDir = input.baseDir ?? import_node_path18.default.join(import_node_os11.default.homedir(), ".claude");
25995
- const projectDir = import_node_path18.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
25996
- const sourceFile = import_node_path18.default.join(projectDir, `${input.toolSessionId}.jsonl`);
25997
- if (!import_node_fs18.default.existsSync(sourceFile)) {
26204
+ const baseDir = input.baseDir ?? import_node_path20.default.join(import_node_os12.default.homedir(), ".claude");
26205
+ const projectDir = import_node_path20.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
26206
+ const sourceFile = import_node_path20.default.join(projectDir, `${input.toolSessionId}.jsonl`);
26207
+ if (!import_node_fs19.default.existsSync(sourceFile)) {
25998
26208
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
25999
26209
  }
26000
26210
  const entries = readJsonlEntries(sourceFile);
@@ -26024,9 +26234,9 @@ function forkSession(input) {
26024
26234
  }
26025
26235
  forkedLines.push(JSON.stringify(forked));
26026
26236
  }
26027
- const forkedFilePath = import_node_path18.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
26028
- import_node_fs18.default.mkdirSync(projectDir, { recursive: true });
26029
- import_node_fs18.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
26237
+ const forkedFilePath = import_node_path20.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
26238
+ import_node_fs19.default.mkdirSync(projectDir, { recursive: true });
26239
+ import_node_fs19.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
26030
26240
  return { forkedToolSessionId, forkedFilePath };
26031
26241
  }
26032
26242
 
@@ -26347,9 +26557,9 @@ init_protocol();
26347
26557
 
26348
26558
  // src/workspace/git.ts
26349
26559
  var import_node_child_process5 = require("child_process");
26350
- var import_node_fs19 = __toESM(require("fs"), 1);
26351
- var import_node_os12 = __toESM(require("os"), 1);
26352
- var import_node_path19 = __toESM(require("path"), 1);
26560
+ var import_node_fs20 = __toESM(require("fs"), 1);
26561
+ var import_node_os13 = __toESM(require("os"), 1);
26562
+ var import_node_path21 = __toESM(require("path"), 1);
26353
26563
  var import_node_util = require("util");
26354
26564
  var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
26355
26565
  function formatChildProcessError(err) {
@@ -26364,9 +26574,9 @@ function formatChildProcessError(err) {
26364
26574
  return e.message ?? "unknown error";
26365
26575
  }
26366
26576
  function normalizePath(p) {
26367
- const resolved = import_node_path19.default.resolve(p);
26577
+ const resolved = import_node_path21.default.resolve(p);
26368
26578
  try {
26369
- return import_node_fs19.default.realpathSync(resolved);
26579
+ return import_node_fs20.default.realpathSync(resolved);
26370
26580
  } catch {
26371
26581
  return resolved;
26372
26582
  }
@@ -26453,7 +26663,7 @@ function sanitizeLabel(raw) {
26453
26663
  function computePrefix() {
26454
26664
  let username;
26455
26665
  try {
26456
- username = import_node_os12.default.userInfo().username;
26666
+ username = import_node_os13.default.userInfo().username;
26457
26667
  } catch {
26458
26668
  username = void 0;
26459
26669
  }
@@ -26467,13 +26677,13 @@ function flattenToDirName(branch) {
26467
26677
  }
26468
26678
  function encodeClaudeProjectDir(absPath) {
26469
26679
  if (!absPath || typeof absPath !== "string") return "";
26470
- let canonical = import_node_path19.default.resolve(absPath);
26680
+ let canonical = import_node_path21.default.resolve(absPath);
26471
26681
  try {
26472
- canonical = import_node_fs19.default.realpathSync(canonical);
26682
+ canonical = import_node_fs20.default.realpathSync(canonical);
26473
26683
  } catch {
26474
26684
  try {
26475
- const parent = import_node_fs19.default.realpathSync(import_node_path19.default.dirname(canonical));
26476
- canonical = import_node_path19.default.join(parent, import_node_path19.default.basename(canonical));
26685
+ const parent = import_node_fs20.default.realpathSync(import_node_path21.default.dirname(canonical));
26686
+ canonical = import_node_path21.default.join(parent, import_node_path21.default.basename(canonical));
26477
26687
  } catch {
26478
26688
  }
26479
26689
  }
@@ -26497,11 +26707,11 @@ async function createWorktree(input) {
26497
26707
  if (!isGitRoot) {
26498
26708
  throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
26499
26709
  }
26500
- const parent = import_node_path19.default.dirname(import_node_path19.default.resolve(cwd));
26501
- if (parent === "/" || parent === import_node_path19.default.resolve(cwd)) {
26710
+ const parent = import_node_path21.default.dirname(import_node_path21.default.resolve(cwd));
26711
+ if (parent === "/" || parent === import_node_path21.default.resolve(cwd)) {
26502
26712
  throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
26503
26713
  }
26504
- const worktreeRoot = import_node_path19.default.join(parent, dirName);
26714
+ const worktreeRoot = import_node_path21.default.join(parent, dirName);
26505
26715
  try {
26506
26716
  await pexec("git", ["-C", cwd, "fetch", "origin", baseBranch, "--no-tags"], {
26507
26717
  timeout: 3e4
@@ -26520,7 +26730,7 @@ async function createWorktree(input) {
26520
26730
  const msg = err.message;
26521
26731
  if (msg.startsWith("\u5206\u652F ")) throw err;
26522
26732
  }
26523
- if (import_node_fs19.default.existsSync(worktreeRoot)) {
26733
+ if (import_node_fs20.default.existsSync(worktreeRoot)) {
26524
26734
  throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
26525
26735
  }
26526
26736
  try {
@@ -26548,8 +26758,8 @@ async function removeWorktree(input) {
26548
26758
  );
26549
26759
  const gitCommonDir = stdout.trim();
26550
26760
  if (!gitCommonDir) throw new Error("empty git-common-dir");
26551
- const absGitCommon = import_node_path19.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path19.default.resolve(worktreeRoot, gitCommonDir);
26552
- repoRoot = import_node_path19.default.dirname(absGitCommon);
26761
+ const absGitCommon = import_node_path21.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path21.default.resolve(worktreeRoot, gitCommonDir);
26762
+ repoRoot = import_node_path21.default.dirname(absGitCommon);
26553
26763
  } catch {
26554
26764
  repoRoot = null;
26555
26765
  }
@@ -26561,7 +26771,7 @@ async function removeWorktree(input) {
26561
26771
  } catch (err) {
26562
26772
  const stderr = err.stderr ?? "";
26563
26773
  const lower = stderr.toLowerCase();
26564
- const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs19.default.existsSync(worktreeRoot);
26774
+ const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs20.default.existsSync(worktreeRoot);
26565
26775
  if (!vanished) {
26566
26776
  throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
26567
26777
  }
@@ -26580,10 +26790,10 @@ async function removeWorktree(input) {
26580
26790
  try {
26581
26791
  const encoded = encodeClaudeProjectDir(worktreeRoot);
26582
26792
  if (encoded) {
26583
- const projectsRoot = import_node_path19.default.join(import_node_os12.default.homedir(), ".claude", "projects");
26584
- const target = import_node_path19.default.resolve(projectsRoot, encoded);
26585
- if (target.startsWith(projectsRoot + import_node_path19.default.sep) && target !== projectsRoot) {
26586
- import_node_fs19.default.rmSync(target, { recursive: true, force: true });
26793
+ const projectsRoot = import_node_path21.default.join(import_node_os13.default.homedir(), ".claude", "projects");
26794
+ const target = import_node_path21.default.resolve(projectsRoot, encoded);
26795
+ if (target.startsWith(projectsRoot + import_node_path21.default.sep) && target !== projectsRoot) {
26796
+ import_node_fs20.default.rmSync(target, { recursive: true, force: true });
26587
26797
  }
26588
26798
  }
26589
26799
  } catch {
@@ -26655,7 +26865,7 @@ function buildCapabilitiesHandlers(deps) {
26655
26865
  }
26656
26866
 
26657
26867
  // src/handlers/meta.ts
26658
- var import_node_os13 = __toESM(require("os"), 1);
26868
+ var import_node_os14 = __toESM(require("os"), 1);
26659
26869
  init_protocol();
26660
26870
 
26661
26871
  // src/version.ts
@@ -26677,7 +26887,7 @@ function buildReadyFrame(deps) {
26677
26887
  return {
26678
26888
  version,
26679
26889
  protocolVersion: PROTOCOL_VERSION,
26680
- hostname: import_node_os13.default.hostname(),
26890
+ hostname: import_node_os14.default.hostname(),
26681
26891
  os: process.platform,
26682
26892
  tools,
26683
26893
  runningSessions: info.runningSessions,
@@ -26752,7 +26962,7 @@ function buildPersonaHandlers(deps) {
26752
26962
  };
26753
26963
  const listSubSessions = async (frame) => {
26754
26964
  const args = PersonaIdArgsSchema.parse(frame);
26755
- const sessions = sessionManager.listForAgent(args.personaId);
26965
+ const sessions = sessionManager.listPersonaSessions(args.personaId, "listener");
26756
26966
  return {
26757
26967
  response: { type: "persona:subSessions", sessions }
26758
26968
  };
@@ -26799,7 +27009,7 @@ function buildMethodHandlers(deps) {
26799
27009
  async function startDaemon(config) {
26800
27010
  const logger = createLogger({
26801
27011
  level: config.logLevel,
26802
- file: import_node_path20.default.join(config.dataDir, "clawd.log")
27012
+ file: import_node_path22.default.join(config.dataDir, "clawd.log")
26803
27013
  });
26804
27014
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
26805
27015
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
@@ -26831,15 +27041,23 @@ async function startDaemon(config) {
26831
27041
  const agents = new AgentsScanner();
26832
27042
  const history = new ClaudeHistoryReader();
26833
27043
  let transport = null;
26834
- const personaStore = new PersonaStore(import_node_path20.default.join(config.dataDir, "personas"));
27044
+ const personaStore = new PersonaStore(import_node_path22.default.join(config.dataDir, "personas"));
27045
+ const defaultsRoot = findDefaultsRoot();
27046
+ if (defaultsRoot) {
27047
+ seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
27048
+ } else {
27049
+ logger.warn("persona.seed.skip", { reason: "defaults-root-not-found" });
27050
+ }
27051
+ const ownerDisplayName = loadOwnerDisplayName(config.dataDir);
26835
27052
  const manager = new SessionManager({
26836
27053
  store,
26837
27054
  logger,
26838
27055
  getAdapter,
26839
27056
  historyReader: history,
26840
27057
  dataDir: config.dataDir,
26841
- personaRoot: import_node_path20.default.join(config.dataDir, "personas"),
27058
+ personaRoot: import_node_path22.default.join(config.dataDir, "personas"),
26842
27059
  personaStore,
27060
+ ownerDisplayName,
26843
27061
  mode: config.mode,
26844
27062
  broadcastFrame: (frame, target) => {
26845
27063
  if (target === "all") {
@@ -27050,8 +27268,8 @@ async function startDaemon(config) {
27050
27268
  const lines = [
27051
27269
  `Tunnel: ${r.url}`,
27052
27270
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
27053
- `Frpc config: ${import_node_path20.default.join(config.dataDir, "frpc.toml")}`,
27054
- `Frpc log: ${import_node_path20.default.join(config.dataDir, "frpc.log")}`
27271
+ `Frpc config: ${import_node_path22.default.join(config.dataDir, "frpc.toml")}`,
27272
+ `Frpc log: ${import_node_path22.default.join(config.dataDir, "frpc.log")}`
27055
27273
  ];
27056
27274
  const width = Math.max(...lines.map((l) => l.length));
27057
27275
  const bar = "\u2550".repeat(width + 4);
@@ -27064,8 +27282,8 @@ ${bar}
27064
27282
 
27065
27283
  `);
27066
27284
  try {
27067
- const connectPath = import_node_path20.default.join(config.dataDir, "connect.txt");
27068
- import_node_fs20.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
27285
+ const connectPath = import_node_path22.default.join(config.dataDir, "connect.txt");
27286
+ import_node_fs21.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
27069
27287
  } catch {
27070
27288
  }
27071
27289
  } catch (err) {