@clawos-dev/clawd 0.2.79-beta.149.201b46d → 0.2.80-beta.150.2767f59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.cjs +324 -201
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -646,8 +646,8 @@ var init_parseUtil = __esm({
646
646
  init_errors2();
647
647
  init_en();
648
648
  makeIssue = (params) => {
649
- const { data, path: path39, errorMaps, issueData } = params;
650
- const fullPath = [...path39, ...issueData.path || []];
649
+ const { data, path: path42, errorMaps, issueData } = params;
650
+ const fullPath = [...path42, ...issueData.path || []];
651
651
  const fullIssue = {
652
652
  ...issueData,
653
653
  path: fullPath
@@ -958,11 +958,11 @@ var init_types = __esm({
958
958
  init_parseUtil();
959
959
  init_util();
960
960
  ParseInputLazyPath = class {
961
- constructor(parent, value, path39, key) {
961
+ constructor(parent, value, path42, key) {
962
962
  this._cachedPath = [];
963
963
  this.parent = parent;
964
964
  this.data = value;
965
- this._path = path39;
965
+ this._path = path42;
966
966
  this._key = key;
967
967
  }
968
968
  get path() {
@@ -5564,8 +5564,8 @@ var require_req = __commonJS({
5564
5564
  if (req.originalUrl) {
5565
5565
  _req.url = req.originalUrl;
5566
5566
  } else {
5567
- const path39 = req.path;
5568
- _req.url = typeof path39 === "string" ? path39 : req.url ? req.url.path || req.url : void 0;
5567
+ const path42 = req.path;
5568
+ _req.url = typeof path42 === "string" ? path42 : req.url ? req.url.path || req.url : void 0;
5569
5569
  }
5570
5570
  if (req.query) {
5571
5571
  _req.query = req.query;
@@ -5730,14 +5730,14 @@ var require_redact = __commonJS({
5730
5730
  }
5731
5731
  return obj;
5732
5732
  }
5733
- function parsePath(path39) {
5733
+ function parsePath(path42) {
5734
5734
  const parts = [];
5735
5735
  let current = "";
5736
5736
  let inBrackets = false;
5737
5737
  let inQuotes = false;
5738
5738
  let quoteChar = "";
5739
- for (let i = 0; i < path39.length; i++) {
5740
- const char = path39[i];
5739
+ for (let i = 0; i < path42.length; i++) {
5740
+ const char = path42[i];
5741
5741
  if (!inBrackets && char === ".") {
5742
5742
  if (current) {
5743
5743
  parts.push(current);
@@ -5868,10 +5868,10 @@ var require_redact = __commonJS({
5868
5868
  return current;
5869
5869
  }
5870
5870
  function redactPaths(obj, paths, censor, remove = false) {
5871
- for (const path39 of paths) {
5872
- const parts = parsePath(path39);
5871
+ for (const path42 of paths) {
5872
+ const parts = parsePath(path42);
5873
5873
  if (parts.includes("*")) {
5874
- redactWildcardPath(obj, parts, censor, path39, remove);
5874
+ redactWildcardPath(obj, parts, censor, path42, remove);
5875
5875
  } else {
5876
5876
  if (remove) {
5877
5877
  removeKey(obj, parts);
@@ -5956,8 +5956,8 @@ var require_redact = __commonJS({
5956
5956
  }
5957
5957
  } else {
5958
5958
  if (afterWildcard.includes("*")) {
5959
- const wrappedCensor = typeof censor === "function" ? (value, path39) => {
5960
- const fullPath = [...pathArray.slice(0, pathLength), ...path39];
5959
+ const wrappedCensor = typeof censor === "function" ? (value, path42) => {
5960
+ const fullPath = [...pathArray.slice(0, pathLength), ...path42];
5961
5961
  return censor(value, fullPath);
5962
5962
  } : censor;
5963
5963
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -5992,8 +5992,8 @@ var require_redact = __commonJS({
5992
5992
  return null;
5993
5993
  }
5994
5994
  const pathStructure = /* @__PURE__ */ new Map();
5995
- for (const path39 of pathsToClone) {
5996
- const parts = parsePath(path39);
5995
+ for (const path42 of pathsToClone) {
5996
+ const parts = parsePath(path42);
5997
5997
  let current = pathStructure;
5998
5998
  for (let i = 0; i < parts.length; i++) {
5999
5999
  const part = parts[i];
@@ -6045,24 +6045,24 @@ var require_redact = __commonJS({
6045
6045
  }
6046
6046
  return cloneSelectively(obj, pathStructure);
6047
6047
  }
6048
- function validatePath(path39) {
6049
- if (typeof path39 !== "string") {
6048
+ function validatePath(path42) {
6049
+ if (typeof path42 !== "string") {
6050
6050
  throw new Error("Paths must be (non-empty) strings");
6051
6051
  }
6052
- if (path39 === "") {
6052
+ if (path42 === "") {
6053
6053
  throw new Error("Invalid redaction path ()");
6054
6054
  }
6055
- if (path39.includes("..")) {
6056
- throw new Error(`Invalid redaction path (${path39})`);
6055
+ if (path42.includes("..")) {
6056
+ throw new Error(`Invalid redaction path (${path42})`);
6057
6057
  }
6058
- if (path39.includes(",")) {
6059
- throw new Error(`Invalid redaction path (${path39})`);
6058
+ if (path42.includes(",")) {
6059
+ throw new Error(`Invalid redaction path (${path42})`);
6060
6060
  }
6061
6061
  let bracketCount = 0;
6062
6062
  let inQuotes = false;
6063
6063
  let quoteChar = "";
6064
- for (let i = 0; i < path39.length; i++) {
6065
- const char = path39[i];
6064
+ for (let i = 0; i < path42.length; i++) {
6065
+ const char = path42[i];
6066
6066
  if ((char === '"' || char === "'") && bracketCount > 0) {
6067
6067
  if (!inQuotes) {
6068
6068
  inQuotes = true;
@@ -6076,20 +6076,20 @@ var require_redact = __commonJS({
6076
6076
  } else if (char === "]" && !inQuotes) {
6077
6077
  bracketCount--;
6078
6078
  if (bracketCount < 0) {
6079
- throw new Error(`Invalid redaction path (${path39})`);
6079
+ throw new Error(`Invalid redaction path (${path42})`);
6080
6080
  }
6081
6081
  }
6082
6082
  }
6083
6083
  if (bracketCount !== 0) {
6084
- throw new Error(`Invalid redaction path (${path39})`);
6084
+ throw new Error(`Invalid redaction path (${path42})`);
6085
6085
  }
6086
6086
  }
6087
6087
  function validatePaths(paths) {
6088
6088
  if (!Array.isArray(paths)) {
6089
6089
  throw new TypeError("paths must be an array");
6090
6090
  }
6091
- for (const path39 of paths) {
6092
- validatePath(path39);
6091
+ for (const path42 of paths) {
6092
+ validatePath(path42);
6093
6093
  }
6094
6094
  }
6095
6095
  function slowRedact(options = {}) {
@@ -6257,8 +6257,8 @@ var require_redaction = __commonJS({
6257
6257
  if (shape[k2] === null) {
6258
6258
  o[k2] = (value) => topCensor(value, [k2]);
6259
6259
  } else {
6260
- const wrappedCensor = typeof censor === "function" ? (value, path39) => {
6261
- return censor(value, [k2, ...path39]);
6260
+ const wrappedCensor = typeof censor === "function" ? (value, path42) => {
6261
+ return censor(value, [k2, ...path42]);
6262
6262
  } : censor;
6263
6263
  o[k2] = Redact({
6264
6264
  paths: shape[k2],
@@ -6476,10 +6476,10 @@ var require_atomic_sleep = __commonJS({
6476
6476
  var require_sonic_boom = __commonJS({
6477
6477
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
6478
6478
  "use strict";
6479
- var fs34 = require("fs");
6479
+ var fs33 = require("fs");
6480
6480
  var EventEmitter2 = require("events");
6481
6481
  var inherits = require("util").inherits;
6482
- var path39 = require("path");
6482
+ var path42 = require("path");
6483
6483
  var sleep = require_atomic_sleep();
6484
6484
  var assert = require("assert");
6485
6485
  var BUSY_WRITE_TIMEOUT = 100;
@@ -6533,20 +6533,20 @@ var require_sonic_boom = __commonJS({
6533
6533
  const mode = sonic.mode;
6534
6534
  if (sonic.sync) {
6535
6535
  try {
6536
- if (sonic.mkdir) fs34.mkdirSync(path39.dirname(file), { recursive: true });
6537
- const fd = fs34.openSync(file, flags, mode);
6536
+ if (sonic.mkdir) fs33.mkdirSync(path42.dirname(file), { recursive: true });
6537
+ const fd = fs33.openSync(file, flags, mode);
6538
6538
  fileOpened(null, fd);
6539
6539
  } catch (err) {
6540
6540
  fileOpened(err);
6541
6541
  throw err;
6542
6542
  }
6543
6543
  } else if (sonic.mkdir) {
6544
- fs34.mkdir(path39.dirname(file), { recursive: true }, (err) => {
6544
+ fs33.mkdir(path42.dirname(file), { recursive: true }, (err) => {
6545
6545
  if (err) return fileOpened(err);
6546
- fs34.open(file, flags, mode, fileOpened);
6546
+ fs33.open(file, flags, mode, fileOpened);
6547
6547
  });
6548
6548
  } else {
6549
- fs34.open(file, flags, mode, fileOpened);
6549
+ fs33.open(file, flags, mode, fileOpened);
6550
6550
  }
6551
6551
  }
6552
6552
  function SonicBoom(opts) {
@@ -6587,8 +6587,8 @@ var require_sonic_boom = __commonJS({
6587
6587
  this.flush = flushBuffer;
6588
6588
  this.flushSync = flushBufferSync;
6589
6589
  this._actualWrite = actualWriteBuffer;
6590
- fsWriteSync = () => fs34.writeSync(this.fd, this._writingBuf);
6591
- fsWrite = () => fs34.write(this.fd, this._writingBuf, this.release);
6590
+ fsWriteSync = () => fs33.writeSync(this.fd, this._writingBuf);
6591
+ fsWrite = () => fs33.write(this.fd, this._writingBuf, this.release);
6592
6592
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
6593
6593
  this._writingBuf = "";
6594
6594
  this.write = write;
@@ -6597,15 +6597,15 @@ var require_sonic_boom = __commonJS({
6597
6597
  this._actualWrite = actualWrite;
6598
6598
  fsWriteSync = () => {
6599
6599
  if (Buffer.isBuffer(this._writingBuf)) {
6600
- return fs34.writeSync(this.fd, this._writingBuf);
6600
+ return fs33.writeSync(this.fd, this._writingBuf);
6601
6601
  }
6602
- return fs34.writeSync(this.fd, this._writingBuf, "utf8");
6602
+ return fs33.writeSync(this.fd, this._writingBuf, "utf8");
6603
6603
  };
6604
6604
  fsWrite = () => {
6605
6605
  if (Buffer.isBuffer(this._writingBuf)) {
6606
- return fs34.write(this.fd, this._writingBuf, this.release);
6606
+ return fs33.write(this.fd, this._writingBuf, this.release);
6607
6607
  }
6608
- return fs34.write(this.fd, this._writingBuf, "utf8", this.release);
6608
+ return fs33.write(this.fd, this._writingBuf, "utf8", this.release);
6609
6609
  };
6610
6610
  } else {
6611
6611
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -6662,7 +6662,7 @@ var require_sonic_boom = __commonJS({
6662
6662
  }
6663
6663
  }
6664
6664
  if (this._fsync) {
6665
- fs34.fsyncSync(this.fd);
6665
+ fs33.fsyncSync(this.fd);
6666
6666
  }
6667
6667
  const len = this._len;
6668
6668
  if (this._reopening) {
@@ -6776,7 +6776,7 @@ var require_sonic_boom = __commonJS({
6776
6776
  const onDrain = () => {
6777
6777
  if (!this._fsync) {
6778
6778
  try {
6779
- fs34.fsync(this.fd, (err) => {
6779
+ fs33.fsync(this.fd, (err) => {
6780
6780
  this._flushPending = false;
6781
6781
  cb(err);
6782
6782
  });
@@ -6878,7 +6878,7 @@ var require_sonic_boom = __commonJS({
6878
6878
  const fd = this.fd;
6879
6879
  this.once("ready", () => {
6880
6880
  if (fd !== this.fd) {
6881
- fs34.close(fd, (err) => {
6881
+ fs33.close(fd, (err) => {
6882
6882
  if (err) {
6883
6883
  return this.emit("error", err);
6884
6884
  }
@@ -6927,7 +6927,7 @@ var require_sonic_boom = __commonJS({
6927
6927
  buf = this._bufs[0];
6928
6928
  }
6929
6929
  try {
6930
- const n = Buffer.isBuffer(buf) ? fs34.writeSync(this.fd, buf) : fs34.writeSync(this.fd, buf, "utf8");
6930
+ const n = Buffer.isBuffer(buf) ? fs33.writeSync(this.fd, buf) : fs33.writeSync(this.fd, buf, "utf8");
6931
6931
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
6932
6932
  buf = releasedBufObj.writingBuf;
6933
6933
  this._len = releasedBufObj.len;
@@ -6943,7 +6943,7 @@ var require_sonic_boom = __commonJS({
6943
6943
  }
6944
6944
  }
6945
6945
  try {
6946
- fs34.fsyncSync(this.fd);
6946
+ fs33.fsyncSync(this.fd);
6947
6947
  } catch {
6948
6948
  }
6949
6949
  }
@@ -6964,7 +6964,7 @@ var require_sonic_boom = __commonJS({
6964
6964
  buf = mergeBuf(this._bufs[0], this._lens[0]);
6965
6965
  }
6966
6966
  try {
6967
- const n = fs34.writeSync(this.fd, buf);
6967
+ const n = fs33.writeSync(this.fd, buf);
6968
6968
  buf = buf.subarray(n);
6969
6969
  this._len = Math.max(this._len - n, 0);
6970
6970
  if (buf.length <= 0) {
@@ -6992,13 +6992,13 @@ var require_sonic_boom = __commonJS({
6992
6992
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
6993
6993
  if (this.sync) {
6994
6994
  try {
6995
- const written = Buffer.isBuffer(this._writingBuf) ? fs34.writeSync(this.fd, this._writingBuf) : fs34.writeSync(this.fd, this._writingBuf, "utf8");
6995
+ const written = Buffer.isBuffer(this._writingBuf) ? fs33.writeSync(this.fd, this._writingBuf) : fs33.writeSync(this.fd, this._writingBuf, "utf8");
6996
6996
  release(null, written);
6997
6997
  } catch (err) {
6998
6998
  release(err);
6999
6999
  }
7000
7000
  } else {
7001
- fs34.write(this.fd, this._writingBuf, release);
7001
+ fs33.write(this.fd, this._writingBuf, release);
7002
7002
  }
7003
7003
  }
7004
7004
  function actualWriteBuffer() {
@@ -7007,7 +7007,7 @@ var require_sonic_boom = __commonJS({
7007
7007
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
7008
7008
  if (this.sync) {
7009
7009
  try {
7010
- const written = fs34.writeSync(this.fd, this._writingBuf);
7010
+ const written = fs33.writeSync(this.fd, this._writingBuf);
7011
7011
  release(null, written);
7012
7012
  } catch (err) {
7013
7013
  release(err);
@@ -7016,7 +7016,7 @@ var require_sonic_boom = __commonJS({
7016
7016
  if (kCopyBuffer) {
7017
7017
  this._writingBuf = Buffer.from(this._writingBuf);
7018
7018
  }
7019
- fs34.write(this.fd, this._writingBuf, release);
7019
+ fs33.write(this.fd, this._writingBuf, release);
7020
7020
  }
7021
7021
  }
7022
7022
  function actualClose(sonic) {
@@ -7032,12 +7032,12 @@ var require_sonic_boom = __commonJS({
7032
7032
  sonic._lens = [];
7033
7033
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
7034
7034
  try {
7035
- fs34.fsync(sonic.fd, closeWrapped);
7035
+ fs33.fsync(sonic.fd, closeWrapped);
7036
7036
  } catch {
7037
7037
  }
7038
7038
  function closeWrapped() {
7039
7039
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7040
- fs34.close(sonic.fd, done);
7040
+ fs33.close(sonic.fd, done);
7041
7041
  } else {
7042
7042
  done();
7043
7043
  }
@@ -7716,7 +7716,7 @@ var require_transport = __commonJS({
7716
7716
  "use strict";
7717
7717
  var { createRequire } = require("module");
7718
7718
  var getCallers = require_caller();
7719
- var { join: join11, isAbsolute, sep: sep2 } = require("path");
7719
+ var { join: join11, isAbsolute: isAbsolute2, sep: sep3 } = require("path");
7720
7720
  var sleep = require_atomic_sleep();
7721
7721
  var onExit = require_on_exit_leak_free();
7722
7722
  var ThreadStream = require_thread_stream();
@@ -7815,7 +7815,7 @@ var require_transport = __commonJS({
7815
7815
  return buildStream(fixTarget(target), options, worker, sync);
7816
7816
  function fixTarget(origin) {
7817
7817
  origin = bundlerOverrides[origin] || origin;
7818
- if (isAbsolute(origin) || origin.indexOf("file://") === 0) {
7818
+ if (isAbsolute2(origin) || origin.indexOf("file://") === 0) {
7819
7819
  return origin;
7820
7820
  }
7821
7821
  if (origin === "pino/file") {
@@ -7824,7 +7824,7 @@ var require_transport = __commonJS({
7824
7824
  let fixTarget2;
7825
7825
  for (const filePath of callers) {
7826
7826
  try {
7827
- const context = filePath === "node:repl" ? process.cwd() + sep2 : filePath;
7827
+ const context = filePath === "node:repl" ? process.cwd() + sep3 : filePath;
7828
7828
  fixTarget2 = createRequire(context).resolve(origin);
7829
7829
  break;
7830
7830
  } catch (err) {
@@ -9401,7 +9401,7 @@ var require_multistream = __commonJS({
9401
9401
  var require_pino = __commonJS({
9402
9402
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
9403
9403
  "use strict";
9404
- var os15 = require("os");
9404
+ var os16 = require("os");
9405
9405
  var stdSerializers = require_pino_std_serializers();
9406
9406
  var caller = require_caller();
9407
9407
  var redaction = require_redaction();
@@ -9448,7 +9448,7 @@ var require_pino = __commonJS({
9448
9448
  } = symbols;
9449
9449
  var { epochTime, nullTime } = time;
9450
9450
  var { pid } = process;
9451
- var hostname = os15.hostname();
9451
+ var hostname = os16.hostname();
9452
9452
  var defaultErrorSerializer = stdSerializers.err;
9453
9453
  var defaultOptions = {
9454
9454
  level: "info",
@@ -10172,11 +10172,11 @@ var init_lib = __esm({
10172
10172
  }
10173
10173
  }
10174
10174
  },
10175
- addToPath: function addToPath(path39, added, removed, oldPosInc, options) {
10176
- var last = path39.lastComponent;
10175
+ addToPath: function addToPath(path42, added, removed, oldPosInc, options) {
10176
+ var last = path42.lastComponent;
10177
10177
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
10178
10178
  return {
10179
- oldPos: path39.oldPos + oldPosInc,
10179
+ oldPos: path42.oldPos + oldPosInc,
10180
10180
  lastComponent: {
10181
10181
  count: last.count + 1,
10182
10182
  added,
@@ -10186,7 +10186,7 @@ var init_lib = __esm({
10186
10186
  };
10187
10187
  } else {
10188
10188
  return {
10189
- oldPos: path39.oldPos + oldPosInc,
10189
+ oldPos: path42.oldPos + oldPosInc,
10190
10190
  lastComponent: {
10191
10191
  count: 1,
10192
10192
  added,
@@ -10617,10 +10617,10 @@ function attachmentToHistoryMessage(o, ts) {
10617
10617
  const memories = raw.map((m2) => {
10618
10618
  if (!m2 || typeof m2 !== "object") return null;
10619
10619
  const rec = m2;
10620
- const path39 = typeof rec.path === "string" ? rec.path : null;
10620
+ const path42 = typeof rec.path === "string" ? rec.path : null;
10621
10621
  const content = typeof rec.content === "string" ? rec.content : null;
10622
- if (!path39 || content == null) return null;
10623
- const entry = { path: path39, content };
10622
+ if (!path42 || content == null) return null;
10623
+ const entry = { path: path42, content };
10624
10624
  if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
10625
10625
  return entry;
10626
10626
  }).filter((m2) => m2 !== null);
@@ -11083,8 +11083,8 @@ var init_claude_history = __esm({
11083
11083
  // src/tools/sandbox.ts
11084
11084
  function shouldSandbox(cwd, personaRoot) {
11085
11085
  if (!personaRoot) return false;
11086
- const sep2 = personaRoot.endsWith(path12.sep) ? "" : path12.sep;
11087
- return cwd.startsWith(personaRoot + sep2) && cwd !== personaRoot;
11086
+ const sep3 = personaRoot.endsWith(path12.sep) ? "" : path12.sep;
11087
+ return cwd.startsWith(personaRoot + sep3) && cwd !== personaRoot;
11088
11088
  }
11089
11089
  function inferSandboxSettingsPath(cwd, personaRoot) {
11090
11090
  if (!shouldSandbox(cwd, personaRoot)) return null;
@@ -11446,10 +11446,10 @@ function parseAttachment(obj) {
11446
11446
  const memories = raw.map((m2) => {
11447
11447
  if (!m2 || typeof m2 !== "object") return null;
11448
11448
  const rec = m2;
11449
- const path39 = typeof rec.path === "string" ? rec.path : null;
11449
+ const path42 = typeof rec.path === "string" ? rec.path : null;
11450
11450
  const content = typeof rec.content === "string" ? rec.content : null;
11451
- if (!path39 || content == null) return null;
11452
- const out = { path: path39, content };
11451
+ if (!path42 || content == null) return null;
11452
+ const out = { path: path42, content };
11453
11453
  if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
11454
11454
  return out;
11455
11455
  }).filter((m2) => m2 !== null);
@@ -20369,11 +20369,11 @@ function startRunCaseRecorder(opts) {
20369
20369
  let closing = false;
20370
20370
  let closedSettled = false;
20371
20371
  let closedResolve;
20372
- const closed = new Promise((resolve2) => {
20372
+ const closed = new Promise((resolve6) => {
20373
20373
  closedResolve = () => {
20374
20374
  if (closedSettled) return;
20375
20375
  closedSettled = true;
20376
- resolve2();
20376
+ resolve6();
20377
20377
  };
20378
20378
  });
20379
20379
  const ensureStream = () => {
@@ -20465,8 +20465,8 @@ async function runController(opts) {
20465
20465
  let exitCode = null;
20466
20466
  let procExited = false;
20467
20467
  let resolveProcExit;
20468
- const procExitPromise = new Promise((resolve2) => {
20469
- resolveProcExit = resolve2;
20468
+ const procExitPromise = new Promise((resolve6) => {
20469
+ resolveProcExit = resolve6;
20470
20470
  });
20471
20471
  const writeEvent = (event) => {
20472
20472
  try {
@@ -21892,8 +21892,8 @@ function startRecorder(opts) {
21892
21892
  const filePath = import_node_path5.default.join(dir, `${tsForFilename(now())}.jsonl`);
21893
21893
  let stream = null;
21894
21894
  let closedResolve;
21895
- const closed = new Promise((resolve2) => {
21896
- closedResolve = resolve2;
21895
+ const closed = new Promise((resolve6) => {
21896
+ closedResolve = resolve6;
21897
21897
  });
21898
21898
  let exited = false;
21899
21899
  const ensureStream = () => {
@@ -22047,13 +22047,13 @@ var SessionRunner = class {
22047
22047
  // 已经停止则立即 resolve;超时(默认 3000ms)抛错由上层透传成 RPC error
22048
22048
  async waitUntilStopped(timeoutMs = DEFAULT_WAIT_STOP_TIMEOUT_MS) {
22049
22049
  if (!this.state.procAlive) return;
22050
- return new Promise((resolve2, reject) => {
22050
+ return new Promise((resolve6, reject) => {
22051
22051
  let settled = false;
22052
22052
  const onStop = () => {
22053
22053
  if (settled) return;
22054
22054
  settled = true;
22055
22055
  clearTimeout(timer);
22056
- resolve2();
22056
+ resolve6();
22057
22057
  };
22058
22058
  const timer = setTimeout(() => {
22059
22059
  if (settled) return;
@@ -22144,7 +22144,7 @@ var SessionRunner = class {
22144
22144
  };
22145
22145
  const payload = JSON.stringify(frame) + "\n";
22146
22146
  const timeoutMs = opts.timeoutMs ?? DEFAULT_CONTROL_REQUEST_TIMEOUT_MS;
22147
- return new Promise((resolve2, reject) => {
22147
+ return new Promise((resolve6, reject) => {
22148
22148
  const timer = setTimeout(() => {
22149
22149
  const pending = this.pendingControlRequests.get(requestId);
22150
22150
  if (!pending) return;
@@ -22152,7 +22152,7 @@ var SessionRunner = class {
22152
22152
  reject(new Error(`control_request timeout: ${subtype}`));
22153
22153
  }, timeoutMs);
22154
22154
  timer.unref?.();
22155
- this.pendingControlRequests.set(requestId, { resolve: resolve2, reject, timer });
22155
+ this.pendingControlRequests.set(requestId, { resolve: resolve6, reject, timer });
22156
22156
  try {
22157
22157
  proc.stdin?.write(payload);
22158
22158
  this.recorder?.tapStdinWrite(payload);
@@ -25043,10 +25043,10 @@ function createPopupDetector(opts) {
25043
25043
  return visible;
25044
25044
  },
25045
25045
  writeBytes(data) {
25046
- return new Promise((resolve2) => {
25046
+ return new Promise((resolve6) => {
25047
25047
  term.write(data, () => {
25048
25048
  tick();
25049
- resolve2();
25049
+ resolve6();
25050
25050
  });
25051
25051
  });
25052
25052
  },
@@ -25717,7 +25717,7 @@ var LocalWsServer = class {
25717
25717
  pingIntervalMs;
25718
25718
  async start() {
25719
25719
  const host = this.opts.host ?? "127.0.0.1";
25720
- await new Promise((resolve2, reject) => {
25720
+ await new Promise((resolve6, reject) => {
25721
25721
  const httpServer = import_node_http.default.createServer((req, res) => this.handleHttpRequest(req, res));
25722
25722
  const wss = new import_websocket_server.default({ noServer: true, clientTracking: true });
25723
25723
  httpServer.on("upgrade", (req, socket, head) => {
@@ -25727,7 +25727,7 @@ var LocalWsServer = class {
25727
25727
  });
25728
25728
  httpServer.on("listening", () => {
25729
25729
  this.logger?.info("ws listening", { host, port: this.opts.port });
25730
- resolve2();
25730
+ resolve6();
25731
25731
  });
25732
25732
  httpServer.on("error", (err) => {
25733
25733
  this.logger?.error("ws server error", { err: err.message });
@@ -25748,11 +25748,11 @@ var LocalWsServer = class {
25748
25748
  if (c.pingTimer) clearInterval(c.pingTimer);
25749
25749
  }
25750
25750
  this.clients.clear();
25751
- await new Promise((resolve2) => {
25752
- this.wss?.close(() => resolve2());
25751
+ await new Promise((resolve6) => {
25752
+ this.wss?.close(() => resolve6());
25753
25753
  });
25754
- await new Promise((resolve2) => {
25755
- this.httpServer?.close(() => resolve2());
25754
+ await new Promise((resolve6) => {
25755
+ this.httpServer?.close(() => resolve6());
25756
25756
  });
25757
25757
  this.wss = null;
25758
25758
  this.httpServer = null;
@@ -26759,38 +26759,17 @@ var ReceivedCapabilityStore = class {
26759
26759
  }
26760
26760
  };
26761
26761
 
26762
- // src/state/legacy-migration.ts
26763
- var fs19 = __toESM(require("fs"), 1);
26764
- var path21 = __toESM(require("path"), 1);
26765
- var TARGETS = [
26766
- { src: "capabilities.json", bak: "capabilities.legacy.bak" },
26767
- { src: "remote-personas", bak: "remote-personas.legacy.bak" },
26768
- { src: "peers.json", bak: "peers.legacy.bak" }
26769
- ];
26770
- function migrateLegacyFiles(dataDir) {
26771
- for (const t of TARGETS) {
26772
- const srcPath = path21.join(dataDir, t.src);
26773
- const bakPath = path21.join(dataDir, t.bak);
26774
- if (!fs19.existsSync(srcPath)) continue;
26775
- if (fs19.existsSync(bakPath)) continue;
26776
- try {
26777
- fs19.renameSync(srcPath, bakPath);
26778
- } catch {
26779
- }
26780
- }
26781
- }
26782
-
26783
26762
  // src/received-capability/connect-remote.ts
26784
26763
  var crypto6 = __toESM(require("crypto"), 1);
26785
26764
  var HANDSHAKE_TIMEOUT_MS = 5e3;
26786
26765
  var RPC_TIMEOUT_MS = 5e3;
26787
26766
  async function connectRemote(args) {
26788
26767
  const ws = new wrapper_default(args.url);
26789
- await new Promise((resolve2, reject) => {
26768
+ await new Promise((resolve6, reject) => {
26790
26769
  const onError = (e) => reject(e);
26791
26770
  ws.once("open", () => {
26792
26771
  ws.off("error", onError);
26793
- resolve2();
26772
+ resolve6();
26794
26773
  });
26795
26774
  ws.once("error", onError);
26796
26775
  });
@@ -26802,7 +26781,7 @@ async function connectRemote(args) {
26802
26781
  selfDisplayName: args.selfDisplayName
26803
26782
  })
26804
26783
  );
26805
- await new Promise((resolve2, reject) => {
26784
+ await new Promise((resolve6, reject) => {
26806
26785
  const onMessage = (raw) => {
26807
26786
  let f;
26808
26787
  try {
@@ -26812,7 +26791,7 @@ async function connectRemote(args) {
26812
26791
  }
26813
26792
  if (f.type === "auth:ok" || f.type === "ready") {
26814
26793
  ws.off("message", onMessage);
26815
- resolve2();
26794
+ resolve6();
26816
26795
  return;
26817
26796
  }
26818
26797
  if (f.type === "auth:error" || f.code === 4401) {
@@ -26828,7 +26807,7 @@ async function connectRemote(args) {
26828
26807
  });
26829
26808
  function call(method, payload) {
26830
26809
  const requestId = crypto6.randomUUID();
26831
- return new Promise((resolve2, reject) => {
26810
+ return new Promise((resolve6, reject) => {
26832
26811
  const onMessage = (raw) => {
26833
26812
  let f;
26834
26813
  try {
@@ -26841,7 +26820,7 @@ async function connectRemote(args) {
26841
26820
  if (f.error || f.type?.endsWith(":error")) {
26842
26821
  reject(new Error(f.message ?? f.error ?? "rpc error"));
26843
26822
  } else {
26844
- resolve2(f);
26823
+ resolve6(f);
26845
26824
  }
26846
26825
  };
26847
26826
  ws.on("message", onMessage);
@@ -26872,61 +26851,61 @@ async function connectRemote(args) {
26872
26851
  }
26873
26852
 
26874
26853
  // src/migrations/2026-05-20-flatten-sessions.ts
26875
- var fs20 = __toESM(require("fs"), 1);
26876
- var path22 = __toESM(require("path"), 1);
26854
+ var fs19 = __toESM(require("fs"), 1);
26855
+ var path21 = __toESM(require("path"), 1);
26877
26856
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
26878
26857
  function migrateFlattenSessions(opts) {
26879
26858
  const dataDir = opts.dataDir;
26880
26859
  const now = opts.now ?? Date.now;
26881
- const sessionsDir = path22.join(dataDir, "sessions");
26882
- const flagPath = path22.join(sessionsDir, MIGRATION_FLAG_NAME);
26883
- if (existsSync4(flagPath)) {
26860
+ const sessionsDir = path21.join(dataDir, "sessions");
26861
+ const flagPath = path21.join(sessionsDir, MIGRATION_FLAG_NAME);
26862
+ if (existsSync3(flagPath)) {
26884
26863
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
26885
26864
  }
26886
26865
  let movedBare = 0;
26887
26866
  let movedVmOwner = 0;
26888
26867
  let archivedListener = 0;
26889
- const defaultDir = path22.join(sessionsDir, "default");
26890
- if (existsSync4(defaultDir)) {
26868
+ const defaultDir = path21.join(sessionsDir, "default");
26869
+ if (existsSync3(defaultDir)) {
26891
26870
  for (const entry of readdirSafe(defaultDir)) {
26892
26871
  if (!entry.endsWith(".json")) continue;
26893
- const src = path22.join(defaultDir, entry);
26894
- const dst = path22.join(sessionsDir, entry);
26895
- fs20.renameSync(src, dst);
26872
+ const src = path21.join(defaultDir, entry);
26873
+ const dst = path21.join(sessionsDir, entry);
26874
+ fs19.renameSync(src, dst);
26896
26875
  movedBare += 1;
26897
26876
  }
26898
26877
  rmdirIfEmpty(defaultDir);
26899
26878
  }
26900
26879
  for (const pid of readdirSafe(sessionsDir)) {
26901
- const personaDir = path22.join(sessionsDir, pid);
26880
+ const personaDir = path21.join(sessionsDir, pid);
26902
26881
  if (!isDir(personaDir)) continue;
26903
26882
  if (pid === "default") continue;
26904
- const ownerSrc = path22.join(personaDir, "owner");
26905
- if (existsSync4(ownerSrc) && isDir(ownerSrc)) {
26906
- const ownerDst = path22.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
26907
- fs20.mkdirSync(ownerDst, { recursive: true });
26883
+ const ownerSrc = path21.join(personaDir, "owner");
26884
+ if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
26885
+ const ownerDst = path21.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
26886
+ fs19.mkdirSync(ownerDst, { recursive: true });
26908
26887
  for (const file of readdirSafe(ownerSrc)) {
26909
26888
  if (!file.endsWith(".json")) continue;
26910
- fs20.renameSync(path22.join(ownerSrc, file), path22.join(ownerDst, file));
26889
+ fs19.renameSync(path21.join(ownerSrc, file), path21.join(ownerDst, file));
26911
26890
  movedVmOwner += 1;
26912
26891
  }
26913
26892
  rmdirIfEmpty(ownerSrc);
26914
26893
  }
26915
- const listenerSrc = path22.join(personaDir, "listener");
26916
- if (existsSync4(listenerSrc) && isDir(listenerSrc)) {
26917
- const archiveDst = path22.join(dataDir, ".legacy", `listener-${pid}`);
26918
- fs20.mkdirSync(archiveDst, { recursive: true });
26894
+ const listenerSrc = path21.join(personaDir, "listener");
26895
+ if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
26896
+ const archiveDst = path21.join(dataDir, ".legacy", `listener-${pid}`);
26897
+ fs19.mkdirSync(archiveDst, { recursive: true });
26919
26898
  for (const file of readdirSafe(listenerSrc)) {
26920
26899
  if (!file.endsWith(".json")) continue;
26921
- fs20.renameSync(path22.join(listenerSrc, file), path22.join(archiveDst, file));
26900
+ fs19.renameSync(path21.join(listenerSrc, file), path21.join(archiveDst, file));
26922
26901
  archivedListener += 1;
26923
26902
  }
26924
26903
  rmdirIfEmpty(listenerSrc);
26925
26904
  }
26926
26905
  rmdirIfEmpty(personaDir);
26927
26906
  }
26928
- fs20.mkdirSync(sessionsDir, { recursive: true });
26929
- fs20.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
26907
+ fs19.mkdirSync(sessionsDir, { recursive: true });
26908
+ fs19.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
26930
26909
  return {
26931
26910
  skipped: false,
26932
26911
  flagWritten: true,
@@ -26935,9 +26914,9 @@ function migrateFlattenSessions(opts) {
26935
26914
  archivedListener
26936
26915
  };
26937
26916
  }
26938
- function existsSync4(p2) {
26917
+ function existsSync3(p2) {
26939
26918
  try {
26940
- fs20.statSync(p2);
26919
+ fs19.statSync(p2);
26941
26920
  return true;
26942
26921
  } catch {
26943
26922
  return false;
@@ -26945,21 +26924,21 @@ function existsSync4(p2) {
26945
26924
  }
26946
26925
  function isDir(p2) {
26947
26926
  try {
26948
- return fs20.statSync(p2).isDirectory();
26927
+ return fs19.statSync(p2).isDirectory();
26949
26928
  } catch {
26950
26929
  return false;
26951
26930
  }
26952
26931
  }
26953
26932
  function readdirSafe(p2) {
26954
26933
  try {
26955
- return fs20.readdirSync(p2);
26934
+ return fs19.readdirSync(p2);
26956
26935
  } catch {
26957
26936
  return [];
26958
26937
  }
26959
26938
  }
26960
26939
  function rmdirIfEmpty(p2) {
26961
26940
  try {
26962
- fs20.rmdirSync(p2);
26941
+ fs19.rmdirSync(p2);
26963
26942
  } catch {
26964
26943
  }
26965
26944
  }
@@ -27713,10 +27692,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
27713
27692
  const work = import_node_path19.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
27714
27693
  import_node_fs17.default.mkdirSync(work, { recursive: true });
27715
27694
  try {
27716
- await new Promise((resolve2, reject) => {
27695
+ await new Promise((resolve6, reject) => {
27717
27696
  const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
27718
27697
  proc.on("error", reject);
27719
- proc.on("exit", (code) => code === 0 ? resolve2() : reject(new Error(`tar exited ${code}`)));
27698
+ proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
27720
27699
  });
27721
27700
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
27722
27701
  const src = import_node_path19.default.join(work, dirName, "frpc");
@@ -27817,7 +27796,7 @@ async function killStaleFrpc(deps) {
27817
27796
  }
27818
27797
  async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
27819
27798
  if (process.platform === "win32") return [];
27820
- return new Promise((resolve2) => {
27799
+ return new Promise((resolve6) => {
27821
27800
  const ps = (0, import_node_child_process4.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
27822
27801
  let buf = "";
27823
27802
  ps.stdout.on("data", (c) => {
@@ -27834,11 +27813,11 @@ async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
27834
27813
  const pid = parseInt(m2[1], 10);
27835
27814
  if (Number.isFinite(pid) && pid > 0) pids.push(pid);
27836
27815
  }
27837
- resolve2(pids);
27816
+ resolve6(pids);
27838
27817
  });
27839
27818
  ps.on("error", (e) => {
27840
27819
  logger?.warn("tunnel: ps scan failed", { err: e.message });
27841
- resolve2([]);
27820
+ resolve6([]);
27842
27821
  });
27843
27822
  });
27844
27823
  }
@@ -27916,17 +27895,17 @@ var TunnelManager = class {
27916
27895
  return;
27917
27896
  }
27918
27897
  proc.kill("SIGTERM");
27919
- await new Promise((resolve2) => {
27898
+ await new Promise((resolve6) => {
27920
27899
  const t = setTimeout(() => {
27921
27900
  try {
27922
27901
  proc.kill("SIGKILL");
27923
27902
  } catch {
27924
27903
  }
27925
- resolve2();
27904
+ resolve6();
27926
27905
  }, 5e3);
27927
27906
  proc.once("exit", () => {
27928
27907
  clearTimeout(t);
27929
- resolve2();
27908
+ resolve6();
27930
27909
  });
27931
27910
  });
27932
27911
  clearFrpcPid(this.deps.dataDir);
@@ -28030,14 +28009,14 @@ function formatFrpcTail(raw, maxLines = 12) {
28030
28009
  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");
28031
28010
  }
28032
28011
  async function waitForFrpcReady(proc, timeoutMs) {
28033
- return new Promise((resolve2) => {
28012
+ return new Promise((resolve6) => {
28034
28013
  let settled = false;
28035
28014
  let buf = "";
28036
28015
  const finish = (r) => {
28037
28016
  if (settled) return;
28038
28017
  settled = true;
28039
28018
  cleanup();
28040
- resolve2(r);
28019
+ resolve6(r);
28041
28020
  };
28042
28021
  const onData = (chunk) => {
28043
28022
  buf += String(chunk);
@@ -28560,6 +28539,7 @@ function buildPermissionHandlers(deps) {
28560
28539
  }
28561
28540
 
28562
28541
  // src/handlers/history.ts
28542
+ var path34 = __toESM(require("path"), 1);
28563
28543
  init_protocol();
28564
28544
 
28565
28545
  // src/session/recent-dirs.ts
@@ -28576,16 +28556,76 @@ function listRecentDirs(store, limit = 50) {
28576
28556
  return Array.from(latestByCwd.entries()).map(([cwd, updatedAt]) => ({ cwd, updatedAt })).sort((a, b2) => a.updatedAt > b2.updatedAt ? -1 : a.updatedAt < b2.updatedAt ? 1 : 0).slice(0, limit);
28577
28557
  }
28578
28558
 
28559
+ // src/permission/persona-paths.ts
28560
+ var path33 = __toESM(require("path"), 1);
28561
+ function getAllowedPersonaIds(grants, action) {
28562
+ const ids = /* @__PURE__ */ new Set();
28563
+ for (const g2 of grants) {
28564
+ if (g2.resource.type !== "persona") continue;
28565
+ const acted = g2.actions.includes(action) || g2.actions.includes("admin");
28566
+ if (!acted) continue;
28567
+ if (g2.resource.id === "*") return "*";
28568
+ ids.add(g2.resource.id);
28569
+ }
28570
+ return ids;
28571
+ }
28572
+ function isGuestPathAllowed(grants, absPath, personaRoot, action = "read") {
28573
+ const root = path33.resolve(personaRoot);
28574
+ const target = path33.resolve(absPath);
28575
+ const sep3 = root.endsWith(path33.sep) ? "" : path33.sep;
28576
+ if (!target.startsWith(root + sep3)) return false;
28577
+ const rel = path33.relative(root, target);
28578
+ if (!rel || rel.startsWith("..")) return false;
28579
+ const personaId = rel.split(path33.sep)[0];
28580
+ if (!personaId) return false;
28581
+ const allowed = getAllowedPersonaIds(grants, action);
28582
+ if (allowed === "*") return true;
28583
+ return allowed.has(personaId);
28584
+ }
28585
+ function personaIdFromPath(absPath, personaRoot) {
28586
+ const root = path33.resolve(personaRoot);
28587
+ const target = path33.resolve(absPath);
28588
+ const sep3 = root.endsWith(path33.sep) ? "" : path33.sep;
28589
+ if (!target.startsWith(root + sep3)) return null;
28590
+ const rel = path33.relative(root, target);
28591
+ if (!rel || rel.startsWith("..")) return null;
28592
+ const id = rel.split(path33.sep)[0];
28593
+ return id || null;
28594
+ }
28595
+
28579
28596
  // src/handlers/history.ts
28580
28597
  init_protocol();
28598
+ function assertGuestPath(ctx, absPath, personaRoot, method) {
28599
+ if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
28600
+ if (!isGuestPathAllowed(ctx.grants, absPath, personaRoot, "read")) {
28601
+ throw new ClawdError(
28602
+ ERROR_CODES.UNAUTHORIZED,
28603
+ `guest ${ctx.principal.id} cannot ${method} path ${absPath}`
28604
+ );
28605
+ }
28606
+ }
28581
28607
  function buildHistoryHandlers(deps) {
28582
- const { manager, history, store } = deps;
28583
- const projects = async () => {
28608
+ const { manager, history, store, personaRoot } = deps;
28609
+ const projects = async (_frame, _client, ctx) => {
28584
28610
  const list2 = await history.listProjects();
28611
+ if (ctx?.principal.kind === "guest" && personaRoot) {
28612
+ const filtered = list2.filter((p2) => {
28613
+ const pid = personaIdFromPath(p2.projectPath, personaRoot);
28614
+ if (!pid) return false;
28615
+ return isGuestPathAllowed(
28616
+ ctx.grants,
28617
+ path34.join(personaRoot, pid),
28618
+ personaRoot,
28619
+ "read"
28620
+ );
28621
+ });
28622
+ return { response: { type: "history:projects", projects: filtered } };
28623
+ }
28585
28624
  return { response: { type: "history:projects", projects: list2 } };
28586
28625
  };
28587
- const list = async (frame) => {
28626
+ const list = async (frame, _client, ctx) => {
28588
28627
  const args = HistoryListArgs.parse(frame);
28628
+ assertGuestPath(ctx, path34.resolve(args.projectPath), personaRoot, "history:list");
28589
28629
  const sessions = await history.listSessions(args);
28590
28630
  return { response: { type: "history:list", sessions } };
28591
28631
  };
@@ -28615,18 +28655,26 @@ function buildHistoryHandlers(deps) {
28615
28655
  });
28616
28656
  return { response: { type: "history:read", ...res } };
28617
28657
  };
28618
- const subagents = async (frame) => {
28658
+ const subagents = async (frame, _client, ctx) => {
28619
28659
  const args = HistorySubagentsArgs.parse(frame);
28660
+ assertGuestPath(ctx, path34.resolve(args.cwd), personaRoot, "history:subagents");
28620
28661
  const subs = await history.listSubagents(args);
28621
28662
  return { response: { type: "history:subagents", subagents: subs } };
28622
28663
  };
28623
- const subagentRead = async (frame) => {
28664
+ const subagentRead = async (frame, _client, ctx) => {
28624
28665
  const args = HistorySubagentReadArgs.parse(frame);
28666
+ assertGuestPath(ctx, path34.resolve(args.cwd), personaRoot, "history:subagent-read");
28625
28667
  const res = await history.readSubagent(args);
28626
28668
  return { response: { type: "history:subagent-read", ...res } };
28627
28669
  };
28628
- const recentDirs = async () => {
28670
+ const recentDirs = async (_frame, _client, ctx) => {
28629
28671
  const dirs = listRecentDirs(store);
28672
+ if (ctx?.principal.kind === "guest" && personaRoot) {
28673
+ const filtered = dirs.filter(
28674
+ (d) => isGuestPathAllowed(ctx.grants, path34.resolve(d.cwd), personaRoot, "read")
28675
+ );
28676
+ return { response: { type: "history:recentDirs", dirs: filtered } };
28677
+ }
28630
28678
  return { response: { type: "history:recentDirs", dirs } };
28631
28679
  };
28632
28680
  return {
@@ -28640,26 +28688,47 @@ function buildHistoryHandlers(deps) {
28640
28688
  }
28641
28689
 
28642
28690
  // src/handlers/workspace.ts
28691
+ var path35 = __toESM(require("path"), 1);
28692
+ var os13 = __toESM(require("os"), 1);
28643
28693
  init_protocol();
28694
+ init_protocol();
28695
+ function assertGuestPath2(ctx, absPath, personaRoot, method) {
28696
+ if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
28697
+ if (!isGuestPathAllowed(ctx.grants, absPath, personaRoot, "read")) {
28698
+ throw new ClawdError(
28699
+ ERROR_CODES.UNAUTHORIZED,
28700
+ `guest ${ctx.principal.id} cannot ${method} path ${absPath}`
28701
+ );
28702
+ }
28703
+ }
28644
28704
  function buildWorkspaceHandlers(deps) {
28645
- const { workspace, skills, agents } = deps;
28646
- const list = async (frame) => {
28705
+ const { workspace, skills, agents, personaRoot } = deps;
28706
+ const list = async (frame, _client, ctx) => {
28647
28707
  const args = WorkspaceListArgs.parse(frame);
28648
- const res = workspace.list(args);
28708
+ const isGuest = ctx?.principal.kind === "guest";
28709
+ const fallbackCwd = isGuest && personaRoot ? personaRoot : os13.homedir();
28710
+ const resolvedCwd = path35.resolve(args.cwd ?? fallbackCwd);
28711
+ const target = args.path ? path35.resolve(resolvedCwd, args.path) : resolvedCwd;
28712
+ assertGuestPath2(ctx, target, personaRoot, "workspace:list");
28713
+ const res = workspace.list({ ...args, cwd: resolvedCwd });
28649
28714
  return { response: { type: "workspace:list", ...res } };
28650
28715
  };
28651
- const read = async (frame) => {
28716
+ const read = async (frame, _client, ctx) => {
28652
28717
  const args = WorkspaceReadArgs.parse(frame);
28718
+ const target = path35.isAbsolute(args.path) ? path35.resolve(args.path) : path35.resolve(args.cwd, args.path);
28719
+ assertGuestPath2(ctx, target, personaRoot, "workspace:read");
28653
28720
  const res = workspace.read(args);
28654
28721
  return { response: { type: "workspace:read", ...res } };
28655
28722
  };
28656
- const skillsList = async (frame) => {
28723
+ const skillsList = async (frame, _client, ctx) => {
28657
28724
  const args = SkillsListArgs.parse(frame);
28725
+ assertGuestPath2(ctx, path35.resolve(args.cwd), personaRoot, "skills:list");
28658
28726
  const list2 = skills.list(args);
28659
28727
  return { response: { type: "skills:list", skills: list2 } };
28660
28728
  };
28661
- const agentsList = async (frame) => {
28729
+ const agentsList = async (frame, _client, ctx) => {
28662
28730
  const args = AgentsListArgs.parse(frame);
28731
+ assertGuestPath2(ctx, path35.resolve(args.cwd), personaRoot, "agents:list");
28663
28732
  const list2 = agents.list(args);
28664
28733
  return { response: { type: "agents:list", agents: list2 } };
28665
28734
  };
@@ -28672,6 +28741,8 @@ function buildWorkspaceHandlers(deps) {
28672
28741
  }
28673
28742
 
28674
28743
  // src/handlers/git.ts
28744
+ var path37 = __toESM(require("path"), 1);
28745
+ init_protocol();
28675
28746
  init_protocol();
28676
28747
 
28677
28748
  // src/workspace/git.ts
@@ -28754,19 +28825,32 @@ async function listGitBranches(cwd) {
28754
28825
  }
28755
28826
 
28756
28827
  // src/handlers/git.ts
28757
- function buildGitHandlers() {
28758
- const root = async (frame) => {
28828
+ function assertGuestCwd(ctx, cwd, personaRoot, method) {
28829
+ if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
28830
+ if (!isGuestPathAllowed(ctx.grants, path37.resolve(cwd), personaRoot, "read")) {
28831
+ throw new ClawdError(
28832
+ ERROR_CODES.UNAUTHORIZED,
28833
+ `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
28834
+ );
28835
+ }
28836
+ }
28837
+ function buildGitHandlers(deps) {
28838
+ const { personaRoot } = deps;
28839
+ const root = async (frame, _client, ctx) => {
28759
28840
  const args = GitRootArgs.parse(frame);
28841
+ assertGuestCwd(ctx, args.cwd, personaRoot, "git:root");
28760
28842
  const res = await getGitRoot(args.cwd);
28761
28843
  return { response: { type: "git:root", ...res } };
28762
28844
  };
28763
- const branch = async (frame) => {
28845
+ const branch = async (frame, _client, ctx) => {
28764
28846
  const args = GitBranchArgs.parse(frame);
28847
+ assertGuestCwd(ctx, args.cwd, personaRoot, "git:branch");
28765
28848
  const res = await readGitBranch(args.cwd);
28766
28849
  return { response: { type: "git:branch", ...res } };
28767
28850
  };
28768
- const branches = async (frame) => {
28851
+ const branches = async (frame, _client, ctx) => {
28769
28852
  const args = GitBranchesArgs.parse(frame);
28853
+ assertGuestCwd(ctx, args.cwd, personaRoot, "git:branches");
28770
28854
  const res = await listGitBranches(args.cwd);
28771
28855
  return { response: { type: "git:branches", ...res } };
28772
28856
  };
@@ -29203,12 +29287,19 @@ function buildPersonaHandlers(deps) {
29203
29287
  response: { type: "persona:list", personas }
29204
29288
  };
29205
29289
  };
29206
- const get = async (frame) => {
29290
+ const get = async (frame, _client, ctx) => {
29207
29291
  const args = PersonaIdArgsSchema.parse(frame);
29208
29292
  const persona = personaRegistry.get(args.personaId) ?? null;
29209
29293
  if (!persona) {
29210
29294
  return { response: { type: "persona:info", persona: null } };
29211
29295
  }
29296
+ const isGuest = ctx?.principal.kind === "guest";
29297
+ if (isGuest) {
29298
+ const allowed = persona.public && assertGrant(ctx.grants, { type: "persona", id: persona.personaId }, "read");
29299
+ if (!allowed) {
29300
+ return { response: { type: "persona:info", persona: null } };
29301
+ }
29302
+ }
29212
29303
  const personality = personaManager.readPersonality(args.personaId) ?? "";
29213
29304
  const skills = personaManager.listSkills(args.personaId);
29214
29305
  const plugins = personaManager.listEnabledPlugins(args.personaId);
@@ -29252,8 +29343,17 @@ var import_node_path26 = __toESM(require("path"), 1);
29252
29343
  init_protocol();
29253
29344
  init_protocol();
29254
29345
  var DEFAULT_TTL_SECONDS = 24 * 3600;
29346
+ function assertGuestAttachmentPath(ctx, absPath, personaRoot, method) {
29347
+ if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
29348
+ if (!isGuestPathAllowed(ctx.grants, absPath, personaRoot, "read")) {
29349
+ throw new ClawdError(
29350
+ ERROR_CODES.UNAUTHORIZED,
29351
+ `guest ${ctx.principal.id} cannot ${method} path ${absPath}`
29352
+ );
29353
+ }
29354
+ }
29255
29355
  function buildAttachmentHandlers(deps) {
29256
- const signUrl = async (frame) => {
29356
+ const signUrl = async (frame, _client, ctx) => {
29257
29357
  const parsed = AttachmentSignUrlArgs.safeParse(frame);
29258
29358
  if (!parsed.success) {
29259
29359
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, parsed.error.message);
@@ -29295,6 +29395,7 @@ function buildAttachmentHandlers(deps) {
29295
29395
  }
29296
29396
  const cwdAbs = import_node_path26.default.resolve(sessionFile.cwd);
29297
29397
  const candidateAbs = import_node_path26.default.isAbsolute(args.relPath) ? import_node_path26.default.resolve(args.relPath) : import_node_path26.default.resolve(cwdAbs, args.relPath);
29398
+ assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl");
29298
29399
  const entries = deps.groupFileStore.list(scope, args.sessionId);
29299
29400
  const entry = entries.find((e) => {
29300
29401
  const storedAbs = import_node_path26.default.isAbsolute(e.relPath) ? import_node_path26.default.resolve(e.relPath) : import_node_path26.default.resolve(cwdAbs, e.relPath);
@@ -29317,7 +29418,13 @@ function buildAttachmentHandlers(deps) {
29317
29418
  }
29318
29419
  };
29319
29420
  };
29320
- const groupAdd = async (frame) => {
29421
+ function guardGuestBySessionCwd(ctx, sessionId, method) {
29422
+ if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
29423
+ const f = deps.sessionStore.read(sessionId);
29424
+ if (!f) return;
29425
+ assertGuestAttachmentPath(ctx, import_node_path26.default.resolve(f.cwd), deps.personaRoot, method);
29426
+ }
29427
+ const groupAdd = async (frame, _client, ctx) => {
29321
29428
  if (!deps.groupFileStore || !deps.getSessionScope) {
29322
29429
  throw new ClawdError(ERROR_CODES.METHOD_NOT_IMPLEMENTED, "groupFileStore not wired");
29323
29430
  }
@@ -29326,6 +29433,7 @@ function buildAttachmentHandlers(deps) {
29326
29433
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, parsed.error.message);
29327
29434
  }
29328
29435
  const args = parsed.data;
29436
+ guardGuestBySessionCwd(ctx, args.sessionId, "attachment.groupAdd");
29329
29437
  const scope = deps.getSessionScope(args.sessionId);
29330
29438
  if (!scope) {
29331
29439
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
@@ -29340,7 +29448,7 @@ function buildAttachmentHandlers(deps) {
29340
29448
  });
29341
29449
  return { response: { type: "attachment.groupAdd", entry } };
29342
29450
  };
29343
- const groupRemove = async (frame) => {
29451
+ const groupRemove = async (frame, _client, ctx) => {
29344
29452
  if (!deps.groupFileStore || !deps.getSessionScope) {
29345
29453
  throw new ClawdError(ERROR_CODES.METHOD_NOT_IMPLEMENTED, "groupFileStore not wired");
29346
29454
  }
@@ -29348,6 +29456,7 @@ function buildAttachmentHandlers(deps) {
29348
29456
  if (!parsed.success) {
29349
29457
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, parsed.error.message);
29350
29458
  }
29459
+ guardGuestBySessionCwd(ctx, parsed.data.sessionId, "attachment.groupRemove");
29351
29460
  const scope = deps.getSessionScope(parsed.data.sessionId);
29352
29461
  if (!scope) {
29353
29462
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "session not found");
@@ -29361,7 +29470,7 @@ function buildAttachmentHandlers(deps) {
29361
29470
  }
29362
29471
  return { response: { type: "attachment.groupRemove", removed: true } };
29363
29472
  };
29364
- const groupList = async (frame) => {
29473
+ const groupList = async (frame, _client, ctx) => {
29365
29474
  if (!deps.groupFileStore || !deps.getSessionScope) {
29366
29475
  throw new ClawdError(ERROR_CODES.METHOD_NOT_IMPLEMENTED, "groupFileStore not wired");
29367
29476
  }
@@ -29369,6 +29478,7 @@ function buildAttachmentHandlers(deps) {
29369
29478
  if (!parsed.success) {
29370
29479
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, parsed.error.message);
29371
29480
  }
29481
+ guardGuestBySessionCwd(ctx, parsed.data.sessionId, "attachment.groupList");
29372
29482
  const scope = deps.getSessionScope(parsed.data.sessionId);
29373
29483
  if (!scope) return { response: { type: "attachment.groupList", entries: [] } };
29374
29484
  const entries = deps.groupFileStore.list(scope, parsed.data.sessionId);
@@ -29389,7 +29499,7 @@ function buildMethodHandlers(deps) {
29389
29499
  ...buildPermissionHandlers(deps),
29390
29500
  ...buildHistoryHandlers(deps),
29391
29501
  ...buildWorkspaceHandlers(deps),
29392
- ...buildGitHandlers(),
29502
+ ...buildGitHandlers(deps),
29393
29503
  ...buildCapabilitiesHandlers(deps),
29394
29504
  ...buildMetaHandlers(deps),
29395
29505
  ...buildPersonaHandlers({
@@ -29480,39 +29590,49 @@ var METHOD_GRANT_MAP = {
29480
29590
  "permission:respond": CAPABILITY_SCOPED,
29481
29591
  "session:answerQuestion": CAPABILITY_SCOPED,
29482
29592
  "session:cancelQuestion": CAPABILITY_SCOPED,
29483
- "history:projects": ADMIN_ANY,
29484
- "history:list": ADMIN_ANY,
29593
+ // 2026-05-25 老板拍板:guest 用别人 daemon 的 chat 必须能读 history / workspace /
29594
+ // attachment / skills / agents / git 元信息,下沉到 capability-scoped;handler 内
29595
+ // 用 isGuestPathAllowed (persona-paths.ts) 限制路径必须在 personaRoot/<allowed-pid>/** 下,
29596
+ // 防止跨 persona 越权读 owner 私有文件。
29597
+ "history:projects": CAPABILITY_SCOPED,
29598
+ "history:list": CAPABILITY_SCOPED,
29485
29599
  // history:read 取一条 session 的 CC JSONL 历史。guest 进 persona VM 后必须能读自己
29486
29600
  // 创建的 session 历史(chat view 加载历史消息走这条),所以下沉到 capability-scoped;
29487
29601
  // handler 内按 ctx.capabilityId === file.creatorPrincipalId 拦越权。
29488
29602
  "history:read": CAPABILITY_SCOPED,
29489
- "history:subagents": ADMIN_ANY,
29490
- "history:subagent-read": ADMIN_ANY,
29491
- "history:recentDirs": ADMIN_ANY,
29492
- "workspace:list": ADMIN_ANY,
29493
- "workspace:read": ADMIN_ANY,
29494
- "skills:list": ADMIN_ANY,
29495
- "agents:list": ADMIN_ANY,
29496
- "git:root": ADMIN_ANY,
29497
- "git:branch": ADMIN_ANY,
29498
- "git:branches": ADMIN_ANY,
29603
+ "history:subagents": CAPABILITY_SCOPED,
29604
+ "history:subagent-read": CAPABILITY_SCOPED,
29605
+ "history:recentDirs": CAPABILITY_SCOPED,
29606
+ "workspace:list": CAPABILITY_SCOPED,
29607
+ "workspace:read": CAPABILITY_SCOPED,
29608
+ "skills:list": CAPABILITY_SCOPED,
29609
+ "agents:list": CAPABILITY_SCOPED,
29610
+ "git:root": CAPABILITY_SCOPED,
29611
+ "git:branch": CAPABILITY_SCOPED,
29612
+ "git:branches": CAPABILITY_SCOPED,
29499
29613
  "capabilities:get": ADMIN_ANY,
29500
29614
  "persona:create": ADMIN_ANY,
29501
- // persona:list 下沉到 CAPABILITY_SCOPED:guest 调用合法(用于 People 面板展开
29502
- // 对方分享的 personas),handler 端按 ctx + persona.public + assertGrant 过滤。
29615
+ // persona:list / persona:get 下沉到 CAPABILITY_SCOPED:guest 调用合法
29616
+ // (list 用于 People 面板展开对方分享的 personas;get 用于 guest 视角下
29617
+ // PersonaDrawer 展示 persona 详情 readOnly),handler 端按 ctx + persona.public
29618
+ // + assertGrant 过滤,两者口径一致。
29619
+ // persona:update / persona:delete 保持 ADMIN_ANY:UI 端 guest viewerRole 下
29620
+ // 已干掉编辑入口,dispatcher 这层是双保险——非法 RPC 401 兜底。
29503
29621
  "persona:list": CAPABILITY_SCOPED,
29504
- "persona:get": ADMIN_ANY,
29622
+ "persona:get": CAPABILITY_SCOPED,
29505
29623
  "persona:update": ADMIN_ANY,
29506
29624
  "persona:delete": ADMIN_ANY,
29507
29625
  "session:pty:input": ADMIN_ANY,
29508
29626
  "session:pty:resize": ADMIN_ANY,
29509
29627
  "session:pty:snapshot": ADMIN_ANY,
29510
- // file-sharing attachment.* RPC:dispatcher admin-only 兜底(wire-level 拦),
29511
- // 实际只有 owner 能调(personal token 链路 2026-05-21 删除,HTTP Bearer 只识别 owner)
29512
- "attachment.signUrl": ADMIN_ANY,
29513
- "attachment.groupAdd": ADMIN_ANY,
29514
- "attachment.groupRemove": ADMIN_ANY,
29515
- "attachment.groupList": ADMIN_ANY
29628
+ // file-sharing attachment.* RPC:dispatcher 放行;handler 内按 sessionId 反查
29629
+ // session.ownerPersonaId + ctx.grants assertGrant,限制 guest 只能签 / 操作
29630
+ // 自己被授权 persona 下的 session 文件。HTTP Bearer 仍然只识别 owner,所以 guest
29631
+ // 拿到 signed URL 后还要 HTTP 端校验通过才能取到文件——这里 RPC 层 ACL 是第一道。
29632
+ "attachment.signUrl": CAPABILITY_SCOPED,
29633
+ "attachment.groupAdd": CAPABILITY_SCOPED,
29634
+ "attachment.groupRemove": CAPABILITY_SCOPED,
29635
+ "attachment.groupList": CAPABILITY_SCOPED
29516
29636
  };
29517
29637
  function computeGrantForFrame(method, frame) {
29518
29638
  const rule = METHOD_GRANT_MAP[method];
@@ -29552,7 +29672,6 @@ async function startDaemon(config) {
29552
29672
  const ownerPrincipalId = authFile.ownerPrincipalId;
29553
29673
  const ownerDisplayName = loadOwnerDisplayName(config.dataDir);
29554
29674
  const authMode = resolvedAuthToken == null ? "none" : "first-message";
29555
- migrateLegacyFiles(config.dataDir);
29556
29675
  const inboxStore = new InboxStore(config.dataDir);
29557
29676
  const inboxManager = new InboxManager(inboxStore, (_peerOwnerId, frame) => {
29558
29677
  wsServer?.broadcastToOwners(frame);
@@ -29786,8 +29905,12 @@ async function startDaemon(config) {
29786
29905
  getSignSecret: () => authFile?.signSecret ?? "",
29787
29906
  // group RPC + sign 都用:根据 sessionId 反查 scope。owner-mode persona session 走
29788
29907
  // 'persona/<pid>/owner',default 走 'default'。
29789
- getSessionScope: (sid) => manager.findOwnedSessionScope(sid)
29908
+ getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
29909
+ // guest path guard:candidate 必须在 personaRoot 子树下
29910
+ personaRoot: import_node_path27.default.join(config.dataDir, "personas")
29790
29911
  },
29912
+ // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
29913
+ personaRoot: import_node_path27.default.join(config.dataDir, "personas"),
29791
29914
  // Task 1.9: capability:issue/list/revoke handler 依赖
29792
29915
  capabilityManager,
29793
29916
  // v2 Phase 5: capability:issue 返回的 shareUrl 用此 base URL 拼接。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.79-beta.149.201b46d",
3
+ "version": "0.2.80-beta.150.2767f59",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",