@clawos-dev/clawd 0.2.71-beta.124.b09b0a0 → 0.2.71-beta.125.4951782

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 +321 -118
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -121,6 +121,11 @@ var init_methods = __esm({
121
121
  "capability:issue",
122
122
  "capability:list",
123
123
  "capability:revoke",
124
+ // ---- inbox:* (capability platform Phase 3 跨用户通知) ----
125
+ // owner 接 guest 的 cross-principal 消息事件. 当前 Phase 3 仅 owner 调 (admin-only),
126
+ // Phase 4 DM 真接通后 guest 也能调 inbox:postMessage 等 (本批次不加 postMessage).
127
+ "inbox:list",
128
+ "inbox:markRead",
124
129
  "info",
125
130
  "ping"
126
131
  ];
@@ -612,8 +617,8 @@ var init_parseUtil = __esm({
612
617
  init_errors2();
613
618
  init_en();
614
619
  makeIssue = (params) => {
615
- const { data, path: path35, errorMaps, issueData } = params;
616
- const fullPath = [...path35, ...issueData.path || []];
620
+ const { data, path: path36, errorMaps, issueData } = params;
621
+ const fullPath = [...path36, ...issueData.path || []];
617
622
  const fullIssue = {
618
623
  ...issueData,
619
624
  path: fullPath
@@ -924,11 +929,11 @@ var init_types = __esm({
924
929
  init_parseUtil();
925
930
  init_util();
926
931
  ParseInputLazyPath = class {
927
- constructor(parent, value, path35, key) {
932
+ constructor(parent, value, path36, key) {
928
933
  this._cachedPath = [];
929
934
  this.parent = parent;
930
935
  this.data = value;
931
- this._path = path35;
936
+ this._path = path36;
932
937
  this._key = key;
933
938
  }
934
939
  get path() {
@@ -5112,6 +5117,40 @@ var init_capability = __esm({
5112
5117
  }
5113
5118
  });
5114
5119
 
5120
+ // ../protocol/src/inbox.ts
5121
+ var INBOX_EVENT_KIND_VALUES, InboxEventKindSchema, INBOX_PREVIEW_MAX_LENGTH, InboxEventSchema, InboxListArgsSchema, InboxMarkReadArgsSchema;
5122
+ var init_inbox = __esm({
5123
+ "../protocol/src/inbox.ts"() {
5124
+ "use strict";
5125
+ init_zod();
5126
+ init_principal();
5127
+ init_capability();
5128
+ INBOX_EVENT_KIND_VALUES = ["persona-mention", "direct-message"];
5129
+ InboxEventKindSchema = external_exports.enum(INBOX_EVENT_KIND_VALUES);
5130
+ INBOX_PREVIEW_MAX_LENGTH = 140;
5131
+ InboxEventSchema = external_exports.object({
5132
+ id: external_exports.string().min(1),
5133
+ kind: InboxEventKindSchema,
5134
+ fromPrincipal: PrincipalSchema,
5135
+ toPrincipal: PrincipalSchema,
5136
+ // persona-mention 才有, direct-message 不带
5137
+ resource: ResourceSchema.optional(),
5138
+ preview: external_exports.string().max(INBOX_PREVIEW_MAX_LENGTH),
5139
+ createdAt: external_exports.number().int().nonnegative(),
5140
+ readAt: external_exports.number().int().positive().optional(),
5141
+ // direct-message 才有, sha256 hex 64; 派生规则: sha256(min(A,B) + '/' + max(A,B))
5142
+ threadId: external_exports.string().regex(/^[a-f0-9]{64}$/).optional()
5143
+ }).strict();
5144
+ InboxListArgsSchema = external_exports.object({
5145
+ // false / 缺省 = 只返回未读; true = 含已读 (历史回溯用)
5146
+ includeRead: external_exports.boolean().optional()
5147
+ }).strict();
5148
+ InboxMarkReadArgsSchema = external_exports.object({
5149
+ eventId: external_exports.string().min(1)
5150
+ }).strict();
5151
+ }
5152
+ });
5153
+
5115
5154
  // ../protocol/src/runtime.ts
5116
5155
  var init_runtime = __esm({
5117
5156
  "../protocol/src/runtime.ts"() {
@@ -5126,6 +5165,7 @@ var init_runtime = __esm({
5126
5165
  init_attachment_schemas();
5127
5166
  init_principal();
5128
5167
  init_capability();
5168
+ init_inbox();
5129
5169
  }
5130
5170
  });
5131
5171
 
@@ -5400,8 +5440,8 @@ var require_req = __commonJS({
5400
5440
  if (req.originalUrl) {
5401
5441
  _req.url = req.originalUrl;
5402
5442
  } else {
5403
- const path35 = req.path;
5404
- _req.url = typeof path35 === "string" ? path35 : req.url ? req.url.path || req.url : void 0;
5443
+ const path36 = req.path;
5444
+ _req.url = typeof path36 === "string" ? path36 : req.url ? req.url.path || req.url : void 0;
5405
5445
  }
5406
5446
  if (req.query) {
5407
5447
  _req.query = req.query;
@@ -5566,14 +5606,14 @@ var require_redact = __commonJS({
5566
5606
  }
5567
5607
  return obj;
5568
5608
  }
5569
- function parsePath(path35) {
5609
+ function parsePath(path36) {
5570
5610
  const parts = [];
5571
5611
  let current = "";
5572
5612
  let inBrackets = false;
5573
5613
  let inQuotes = false;
5574
5614
  let quoteChar = "";
5575
- for (let i = 0; i < path35.length; i++) {
5576
- const char = path35[i];
5615
+ for (let i = 0; i < path36.length; i++) {
5616
+ const char = path36[i];
5577
5617
  if (!inBrackets && char === ".") {
5578
5618
  if (current) {
5579
5619
  parts.push(current);
@@ -5704,10 +5744,10 @@ var require_redact = __commonJS({
5704
5744
  return current;
5705
5745
  }
5706
5746
  function redactPaths(obj, paths, censor, remove = false) {
5707
- for (const path35 of paths) {
5708
- const parts = parsePath(path35);
5747
+ for (const path36 of paths) {
5748
+ const parts = parsePath(path36);
5709
5749
  if (parts.includes("*")) {
5710
- redactWildcardPath(obj, parts, censor, path35, remove);
5750
+ redactWildcardPath(obj, parts, censor, path36, remove);
5711
5751
  } else {
5712
5752
  if (remove) {
5713
5753
  removeKey(obj, parts);
@@ -5792,8 +5832,8 @@ var require_redact = __commonJS({
5792
5832
  }
5793
5833
  } else {
5794
5834
  if (afterWildcard.includes("*")) {
5795
- const wrappedCensor = typeof censor === "function" ? (value, path35) => {
5796
- const fullPath = [...pathArray.slice(0, pathLength), ...path35];
5835
+ const wrappedCensor = typeof censor === "function" ? (value, path36) => {
5836
+ const fullPath = [...pathArray.slice(0, pathLength), ...path36];
5797
5837
  return censor(value, fullPath);
5798
5838
  } : censor;
5799
5839
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -5828,8 +5868,8 @@ var require_redact = __commonJS({
5828
5868
  return null;
5829
5869
  }
5830
5870
  const pathStructure = /* @__PURE__ */ new Map();
5831
- for (const path35 of pathsToClone) {
5832
- const parts = parsePath(path35);
5871
+ for (const path36 of pathsToClone) {
5872
+ const parts = parsePath(path36);
5833
5873
  let current = pathStructure;
5834
5874
  for (let i = 0; i < parts.length; i++) {
5835
5875
  const part = parts[i];
@@ -5881,24 +5921,24 @@ var require_redact = __commonJS({
5881
5921
  }
5882
5922
  return cloneSelectively(obj, pathStructure);
5883
5923
  }
5884
- function validatePath(path35) {
5885
- if (typeof path35 !== "string") {
5924
+ function validatePath(path36) {
5925
+ if (typeof path36 !== "string") {
5886
5926
  throw new Error("Paths must be (non-empty) strings");
5887
5927
  }
5888
- if (path35 === "") {
5928
+ if (path36 === "") {
5889
5929
  throw new Error("Invalid redaction path ()");
5890
5930
  }
5891
- if (path35.includes("..")) {
5892
- throw new Error(`Invalid redaction path (${path35})`);
5931
+ if (path36.includes("..")) {
5932
+ throw new Error(`Invalid redaction path (${path36})`);
5893
5933
  }
5894
- if (path35.includes(",")) {
5895
- throw new Error(`Invalid redaction path (${path35})`);
5934
+ if (path36.includes(",")) {
5935
+ throw new Error(`Invalid redaction path (${path36})`);
5896
5936
  }
5897
5937
  let bracketCount = 0;
5898
5938
  let inQuotes = false;
5899
5939
  let quoteChar = "";
5900
- for (let i = 0; i < path35.length; i++) {
5901
- const char = path35[i];
5940
+ for (let i = 0; i < path36.length; i++) {
5941
+ const char = path36[i];
5902
5942
  if ((char === '"' || char === "'") && bracketCount > 0) {
5903
5943
  if (!inQuotes) {
5904
5944
  inQuotes = true;
@@ -5912,20 +5952,20 @@ var require_redact = __commonJS({
5912
5952
  } else if (char === "]" && !inQuotes) {
5913
5953
  bracketCount--;
5914
5954
  if (bracketCount < 0) {
5915
- throw new Error(`Invalid redaction path (${path35})`);
5955
+ throw new Error(`Invalid redaction path (${path36})`);
5916
5956
  }
5917
5957
  }
5918
5958
  }
5919
5959
  if (bracketCount !== 0) {
5920
- throw new Error(`Invalid redaction path (${path35})`);
5960
+ throw new Error(`Invalid redaction path (${path36})`);
5921
5961
  }
5922
5962
  }
5923
5963
  function validatePaths(paths) {
5924
5964
  if (!Array.isArray(paths)) {
5925
5965
  throw new TypeError("paths must be an array");
5926
5966
  }
5927
- for (const path35 of paths) {
5928
- validatePath(path35);
5967
+ for (const path36 of paths) {
5968
+ validatePath(path36);
5929
5969
  }
5930
5970
  }
5931
5971
  function slowRedact(options = {}) {
@@ -6093,8 +6133,8 @@ var require_redaction = __commonJS({
6093
6133
  if (shape[k2] === null) {
6094
6134
  o[k2] = (value) => topCensor(value, [k2]);
6095
6135
  } else {
6096
- const wrappedCensor = typeof censor === "function" ? (value, path35) => {
6097
- return censor(value, [k2, ...path35]);
6136
+ const wrappedCensor = typeof censor === "function" ? (value, path36) => {
6137
+ return censor(value, [k2, ...path36]);
6098
6138
  } : censor;
6099
6139
  o[k2] = Redact({
6100
6140
  paths: shape[k2],
@@ -6312,10 +6352,10 @@ var require_atomic_sleep = __commonJS({
6312
6352
  var require_sonic_boom = __commonJS({
6313
6353
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
6314
6354
  "use strict";
6315
- var fs31 = require("fs");
6355
+ var fs32 = require("fs");
6316
6356
  var EventEmitter2 = require("events");
6317
6357
  var inherits = require("util").inherits;
6318
- var path35 = require("path");
6358
+ var path36 = require("path");
6319
6359
  var sleep = require_atomic_sleep();
6320
6360
  var assert = require("assert");
6321
6361
  var BUSY_WRITE_TIMEOUT = 100;
@@ -6369,20 +6409,20 @@ var require_sonic_boom = __commonJS({
6369
6409
  const mode = sonic.mode;
6370
6410
  if (sonic.sync) {
6371
6411
  try {
6372
- if (sonic.mkdir) fs31.mkdirSync(path35.dirname(file), { recursive: true });
6373
- const fd = fs31.openSync(file, flags, mode);
6412
+ if (sonic.mkdir) fs32.mkdirSync(path36.dirname(file), { recursive: true });
6413
+ const fd = fs32.openSync(file, flags, mode);
6374
6414
  fileOpened(null, fd);
6375
6415
  } catch (err) {
6376
6416
  fileOpened(err);
6377
6417
  throw err;
6378
6418
  }
6379
6419
  } else if (sonic.mkdir) {
6380
- fs31.mkdir(path35.dirname(file), { recursive: true }, (err) => {
6420
+ fs32.mkdir(path36.dirname(file), { recursive: true }, (err) => {
6381
6421
  if (err) return fileOpened(err);
6382
- fs31.open(file, flags, mode, fileOpened);
6422
+ fs32.open(file, flags, mode, fileOpened);
6383
6423
  });
6384
6424
  } else {
6385
- fs31.open(file, flags, mode, fileOpened);
6425
+ fs32.open(file, flags, mode, fileOpened);
6386
6426
  }
6387
6427
  }
6388
6428
  function SonicBoom(opts) {
@@ -6423,8 +6463,8 @@ var require_sonic_boom = __commonJS({
6423
6463
  this.flush = flushBuffer;
6424
6464
  this.flushSync = flushBufferSync;
6425
6465
  this._actualWrite = actualWriteBuffer;
6426
- fsWriteSync = () => fs31.writeSync(this.fd, this._writingBuf);
6427
- fsWrite = () => fs31.write(this.fd, this._writingBuf, this.release);
6466
+ fsWriteSync = () => fs32.writeSync(this.fd, this._writingBuf);
6467
+ fsWrite = () => fs32.write(this.fd, this._writingBuf, this.release);
6428
6468
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
6429
6469
  this._writingBuf = "";
6430
6470
  this.write = write;
@@ -6433,15 +6473,15 @@ var require_sonic_boom = __commonJS({
6433
6473
  this._actualWrite = actualWrite;
6434
6474
  fsWriteSync = () => {
6435
6475
  if (Buffer.isBuffer(this._writingBuf)) {
6436
- return fs31.writeSync(this.fd, this._writingBuf);
6476
+ return fs32.writeSync(this.fd, this._writingBuf);
6437
6477
  }
6438
- return fs31.writeSync(this.fd, this._writingBuf, "utf8");
6478
+ return fs32.writeSync(this.fd, this._writingBuf, "utf8");
6439
6479
  };
6440
6480
  fsWrite = () => {
6441
6481
  if (Buffer.isBuffer(this._writingBuf)) {
6442
- return fs31.write(this.fd, this._writingBuf, this.release);
6482
+ return fs32.write(this.fd, this._writingBuf, this.release);
6443
6483
  }
6444
- return fs31.write(this.fd, this._writingBuf, "utf8", this.release);
6484
+ return fs32.write(this.fd, this._writingBuf, "utf8", this.release);
6445
6485
  };
6446
6486
  } else {
6447
6487
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -6498,7 +6538,7 @@ var require_sonic_boom = __commonJS({
6498
6538
  }
6499
6539
  }
6500
6540
  if (this._fsync) {
6501
- fs31.fsyncSync(this.fd);
6541
+ fs32.fsyncSync(this.fd);
6502
6542
  }
6503
6543
  const len = this._len;
6504
6544
  if (this._reopening) {
@@ -6612,7 +6652,7 @@ var require_sonic_boom = __commonJS({
6612
6652
  const onDrain = () => {
6613
6653
  if (!this._fsync) {
6614
6654
  try {
6615
- fs31.fsync(this.fd, (err) => {
6655
+ fs32.fsync(this.fd, (err) => {
6616
6656
  this._flushPending = false;
6617
6657
  cb(err);
6618
6658
  });
@@ -6714,7 +6754,7 @@ var require_sonic_boom = __commonJS({
6714
6754
  const fd = this.fd;
6715
6755
  this.once("ready", () => {
6716
6756
  if (fd !== this.fd) {
6717
- fs31.close(fd, (err) => {
6757
+ fs32.close(fd, (err) => {
6718
6758
  if (err) {
6719
6759
  return this.emit("error", err);
6720
6760
  }
@@ -6763,7 +6803,7 @@ var require_sonic_boom = __commonJS({
6763
6803
  buf = this._bufs[0];
6764
6804
  }
6765
6805
  try {
6766
- const n = Buffer.isBuffer(buf) ? fs31.writeSync(this.fd, buf) : fs31.writeSync(this.fd, buf, "utf8");
6806
+ const n = Buffer.isBuffer(buf) ? fs32.writeSync(this.fd, buf) : fs32.writeSync(this.fd, buf, "utf8");
6767
6807
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
6768
6808
  buf = releasedBufObj.writingBuf;
6769
6809
  this._len = releasedBufObj.len;
@@ -6779,7 +6819,7 @@ var require_sonic_boom = __commonJS({
6779
6819
  }
6780
6820
  }
6781
6821
  try {
6782
- fs31.fsyncSync(this.fd);
6822
+ fs32.fsyncSync(this.fd);
6783
6823
  } catch {
6784
6824
  }
6785
6825
  }
@@ -6800,7 +6840,7 @@ var require_sonic_boom = __commonJS({
6800
6840
  buf = mergeBuf(this._bufs[0], this._lens[0]);
6801
6841
  }
6802
6842
  try {
6803
- const n = fs31.writeSync(this.fd, buf);
6843
+ const n = fs32.writeSync(this.fd, buf);
6804
6844
  buf = buf.subarray(n);
6805
6845
  this._len = Math.max(this._len - n, 0);
6806
6846
  if (buf.length <= 0) {
@@ -6828,13 +6868,13 @@ var require_sonic_boom = __commonJS({
6828
6868
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
6829
6869
  if (this.sync) {
6830
6870
  try {
6831
- const written = Buffer.isBuffer(this._writingBuf) ? fs31.writeSync(this.fd, this._writingBuf) : fs31.writeSync(this.fd, this._writingBuf, "utf8");
6871
+ const written = Buffer.isBuffer(this._writingBuf) ? fs32.writeSync(this.fd, this._writingBuf) : fs32.writeSync(this.fd, this._writingBuf, "utf8");
6832
6872
  release(null, written);
6833
6873
  } catch (err) {
6834
6874
  release(err);
6835
6875
  }
6836
6876
  } else {
6837
- fs31.write(this.fd, this._writingBuf, release);
6877
+ fs32.write(this.fd, this._writingBuf, release);
6838
6878
  }
6839
6879
  }
6840
6880
  function actualWriteBuffer() {
@@ -6843,7 +6883,7 @@ var require_sonic_boom = __commonJS({
6843
6883
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
6844
6884
  if (this.sync) {
6845
6885
  try {
6846
- const written = fs31.writeSync(this.fd, this._writingBuf);
6886
+ const written = fs32.writeSync(this.fd, this._writingBuf);
6847
6887
  release(null, written);
6848
6888
  } catch (err) {
6849
6889
  release(err);
@@ -6852,7 +6892,7 @@ var require_sonic_boom = __commonJS({
6852
6892
  if (kCopyBuffer) {
6853
6893
  this._writingBuf = Buffer.from(this._writingBuf);
6854
6894
  }
6855
- fs31.write(this.fd, this._writingBuf, release);
6895
+ fs32.write(this.fd, this._writingBuf, release);
6856
6896
  }
6857
6897
  }
6858
6898
  function actualClose(sonic) {
@@ -6868,12 +6908,12 @@ var require_sonic_boom = __commonJS({
6868
6908
  sonic._lens = [];
6869
6909
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
6870
6910
  try {
6871
- fs31.fsync(sonic.fd, closeWrapped);
6911
+ fs32.fsync(sonic.fd, closeWrapped);
6872
6912
  } catch {
6873
6913
  }
6874
6914
  function closeWrapped() {
6875
6915
  if (sonic.fd !== 1 && sonic.fd !== 2) {
6876
- fs31.close(sonic.fd, done);
6916
+ fs32.close(sonic.fd, done);
6877
6917
  } else {
6878
6918
  done();
6879
6919
  }
@@ -7130,7 +7170,7 @@ var require_thread_stream = __commonJS({
7130
7170
  var { version: version2 } = require_package();
7131
7171
  var { EventEmitter: EventEmitter2 } = require("events");
7132
7172
  var { Worker } = require("worker_threads");
7133
- var { join: join8 } = require("path");
7173
+ var { join: join9 } = require("path");
7134
7174
  var { pathToFileURL } = require("url");
7135
7175
  var { wait } = require_wait();
7136
7176
  var {
@@ -7166,7 +7206,7 @@ var require_thread_stream = __commonJS({
7166
7206
  function createWorker(stream, opts) {
7167
7207
  const { filename, workerData } = opts;
7168
7208
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
7169
- const toExecute = bundlerOverrides["thread-stream-worker"] || join8(__dirname, "lib", "worker.js");
7209
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join9(__dirname, "lib", "worker.js");
7170
7210
  const worker = new Worker(toExecute, {
7171
7211
  ...opts.workerOpts,
7172
7212
  trackUnmanagedFds: false,
@@ -7552,7 +7592,7 @@ var require_transport = __commonJS({
7552
7592
  "use strict";
7553
7593
  var { createRequire } = require("module");
7554
7594
  var getCallers = require_caller();
7555
- var { join: join8, isAbsolute, sep: sep2 } = require("path");
7595
+ var { join: join9, isAbsolute, sep: sep2 } = require("path");
7556
7596
  var sleep = require_atomic_sleep();
7557
7597
  var onExit = require_on_exit_leak_free();
7558
7598
  var ThreadStream = require_thread_stream();
@@ -7615,7 +7655,7 @@ var require_transport = __commonJS({
7615
7655
  throw new Error("only one of target or targets can be specified");
7616
7656
  }
7617
7657
  if (targets) {
7618
- target = bundlerOverrides["pino-worker"] || join8(__dirname, "worker.js");
7658
+ target = bundlerOverrides["pino-worker"] || join9(__dirname, "worker.js");
7619
7659
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
7620
7660
  return {
7621
7661
  ...dest,
@@ -7633,7 +7673,7 @@ var require_transport = __commonJS({
7633
7673
  });
7634
7674
  });
7635
7675
  } else if (pipeline2) {
7636
- target = bundlerOverrides["pino-worker"] || join8(__dirname, "worker.js");
7676
+ target = bundlerOverrides["pino-worker"] || join9(__dirname, "worker.js");
7637
7677
  options.pipelines = [pipeline2.map((dest) => {
7638
7678
  return {
7639
7679
  ...dest,
@@ -7655,7 +7695,7 @@ var require_transport = __commonJS({
7655
7695
  return origin;
7656
7696
  }
7657
7697
  if (origin === "pino/file") {
7658
- return join8(__dirname, "..", "file.js");
7698
+ return join9(__dirname, "..", "file.js");
7659
7699
  }
7660
7700
  let fixTarget2;
7661
7701
  for (const filePath of callers) {
@@ -8645,7 +8685,7 @@ var require_safe_stable_stringify = __commonJS({
8645
8685
  return circularValue;
8646
8686
  }
8647
8687
  let res = "";
8648
- let join8 = ",";
8688
+ let join9 = ",";
8649
8689
  const originalIndentation = indentation;
8650
8690
  if (Array.isArray(value)) {
8651
8691
  if (value.length === 0) {
@@ -8659,7 +8699,7 @@ var require_safe_stable_stringify = __commonJS({
8659
8699
  indentation += spacer;
8660
8700
  res += `
8661
8701
  ${indentation}`;
8662
- join8 = `,
8702
+ join9 = `,
8663
8703
  ${indentation}`;
8664
8704
  }
8665
8705
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -8667,13 +8707,13 @@ ${indentation}`;
8667
8707
  for (; i < maximumValuesToStringify - 1; i++) {
8668
8708
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
8669
8709
  res += tmp2 !== void 0 ? tmp2 : "null";
8670
- res += join8;
8710
+ res += join9;
8671
8711
  }
8672
8712
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
8673
8713
  res += tmp !== void 0 ? tmp : "null";
8674
8714
  if (value.length - 1 > maximumBreadth) {
8675
8715
  const removedKeys = value.length - maximumBreadth - 1;
8676
- res += `${join8}"... ${getItemCount(removedKeys)} not stringified"`;
8716
+ res += `${join9}"... ${getItemCount(removedKeys)} not stringified"`;
8677
8717
  }
8678
8718
  if (spacer !== "") {
8679
8719
  res += `
@@ -8694,7 +8734,7 @@ ${originalIndentation}`;
8694
8734
  let separator = "";
8695
8735
  if (spacer !== "") {
8696
8736
  indentation += spacer;
8697
- join8 = `,
8737
+ join9 = `,
8698
8738
  ${indentation}`;
8699
8739
  whitespace = " ";
8700
8740
  }
@@ -8708,13 +8748,13 @@ ${indentation}`;
8708
8748
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
8709
8749
  if (tmp !== void 0) {
8710
8750
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
8711
- separator = join8;
8751
+ separator = join9;
8712
8752
  }
8713
8753
  }
8714
8754
  if (keyLength > maximumBreadth) {
8715
8755
  const removedKeys = keyLength - maximumBreadth;
8716
8756
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
8717
- separator = join8;
8757
+ separator = join9;
8718
8758
  }
8719
8759
  if (spacer !== "" && separator.length > 1) {
8720
8760
  res = `
@@ -8755,7 +8795,7 @@ ${originalIndentation}`;
8755
8795
  }
8756
8796
  const originalIndentation = indentation;
8757
8797
  let res = "";
8758
- let join8 = ",";
8798
+ let join9 = ",";
8759
8799
  if (Array.isArray(value)) {
8760
8800
  if (value.length === 0) {
8761
8801
  return "[]";
@@ -8768,7 +8808,7 @@ ${originalIndentation}`;
8768
8808
  indentation += spacer;
8769
8809
  res += `
8770
8810
  ${indentation}`;
8771
- join8 = `,
8811
+ join9 = `,
8772
8812
  ${indentation}`;
8773
8813
  }
8774
8814
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -8776,13 +8816,13 @@ ${indentation}`;
8776
8816
  for (; i < maximumValuesToStringify - 1; i++) {
8777
8817
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
8778
8818
  res += tmp2 !== void 0 ? tmp2 : "null";
8779
- res += join8;
8819
+ res += join9;
8780
8820
  }
8781
8821
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
8782
8822
  res += tmp !== void 0 ? tmp : "null";
8783
8823
  if (value.length - 1 > maximumBreadth) {
8784
8824
  const removedKeys = value.length - maximumBreadth - 1;
8785
- res += `${join8}"... ${getItemCount(removedKeys)} not stringified"`;
8825
+ res += `${join9}"... ${getItemCount(removedKeys)} not stringified"`;
8786
8826
  }
8787
8827
  if (spacer !== "") {
8788
8828
  res += `
@@ -8795,7 +8835,7 @@ ${originalIndentation}`;
8795
8835
  let whitespace = "";
8796
8836
  if (spacer !== "") {
8797
8837
  indentation += spacer;
8798
- join8 = `,
8838
+ join9 = `,
8799
8839
  ${indentation}`;
8800
8840
  whitespace = " ";
8801
8841
  }
@@ -8804,7 +8844,7 @@ ${indentation}`;
8804
8844
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
8805
8845
  if (tmp !== void 0) {
8806
8846
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
8807
- separator = join8;
8847
+ separator = join9;
8808
8848
  }
8809
8849
  }
8810
8850
  if (spacer !== "" && separator.length > 1) {
@@ -8862,20 +8902,20 @@ ${originalIndentation}`;
8862
8902
  indentation += spacer;
8863
8903
  let res2 = `
8864
8904
  ${indentation}`;
8865
- const join9 = `,
8905
+ const join10 = `,
8866
8906
  ${indentation}`;
8867
8907
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
8868
8908
  let i = 0;
8869
8909
  for (; i < maximumValuesToStringify - 1; i++) {
8870
8910
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
8871
8911
  res2 += tmp2 !== void 0 ? tmp2 : "null";
8872
- res2 += join9;
8912
+ res2 += join10;
8873
8913
  }
8874
8914
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
8875
8915
  res2 += tmp !== void 0 ? tmp : "null";
8876
8916
  if (value.length - 1 > maximumBreadth) {
8877
8917
  const removedKeys = value.length - maximumBreadth - 1;
8878
- res2 += `${join9}"... ${getItemCount(removedKeys)} not stringified"`;
8918
+ res2 += `${join10}"... ${getItemCount(removedKeys)} not stringified"`;
8879
8919
  }
8880
8920
  res2 += `
8881
8921
  ${originalIndentation}`;
@@ -8891,16 +8931,16 @@ ${originalIndentation}`;
8891
8931
  return '"[Object]"';
8892
8932
  }
8893
8933
  indentation += spacer;
8894
- const join8 = `,
8934
+ const join9 = `,
8895
8935
  ${indentation}`;
8896
8936
  let res = "";
8897
8937
  let separator = "";
8898
8938
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
8899
8939
  if (isTypedArrayWithEntries(value)) {
8900
- res += stringifyTypedArray(value, join8, maximumBreadth);
8940
+ res += stringifyTypedArray(value, join9, maximumBreadth);
8901
8941
  keys = keys.slice(value.length);
8902
8942
  maximumPropertiesToStringify -= value.length;
8903
- separator = join8;
8943
+ separator = join9;
8904
8944
  }
8905
8945
  if (deterministic) {
8906
8946
  keys = sort(keys, comparator);
@@ -8911,13 +8951,13 @@ ${indentation}`;
8911
8951
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
8912
8952
  if (tmp !== void 0) {
8913
8953
  res += `${separator}${strEscape(key2)}: ${tmp}`;
8914
- separator = join8;
8954
+ separator = join9;
8915
8955
  }
8916
8956
  }
8917
8957
  if (keyLength > maximumBreadth) {
8918
8958
  const removedKeys = keyLength - maximumBreadth;
8919
8959
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
8920
- separator = join8;
8960
+ separator = join9;
8921
8961
  }
8922
8962
  if (separator !== "") {
8923
8963
  res = `
@@ -10008,11 +10048,11 @@ var init_lib = __esm({
10008
10048
  }
10009
10049
  }
10010
10050
  },
10011
- addToPath: function addToPath(path35, added, removed, oldPosInc, options) {
10012
- var last = path35.lastComponent;
10051
+ addToPath: function addToPath(path36, added, removed, oldPosInc, options) {
10052
+ var last = path36.lastComponent;
10013
10053
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
10014
10054
  return {
10015
- oldPos: path35.oldPos + oldPosInc,
10055
+ oldPos: path36.oldPos + oldPosInc,
10016
10056
  lastComponent: {
10017
10057
  count: last.count + 1,
10018
10058
  added,
@@ -10022,7 +10062,7 @@ var init_lib = __esm({
10022
10062
  };
10023
10063
  } else {
10024
10064
  return {
10025
- oldPos: path35.oldPos + oldPosInc,
10065
+ oldPos: path36.oldPos + oldPosInc,
10026
10066
  lastComponent: {
10027
10067
  count: 1,
10028
10068
  added,
@@ -10453,10 +10493,10 @@ function attachmentToHistoryMessage(o, ts) {
10453
10493
  const memories = raw.map((m2) => {
10454
10494
  if (!m2 || typeof m2 !== "object") return null;
10455
10495
  const rec = m2;
10456
- const path35 = typeof rec.path === "string" ? rec.path : null;
10496
+ const path36 = typeof rec.path === "string" ? rec.path : null;
10457
10497
  const content = typeof rec.content === "string" ? rec.content : null;
10458
- if (!path35 || content == null) return null;
10459
- const entry = { path: path35, content };
10498
+ if (!path36 || content == null) return null;
10499
+ const entry = { path: path36, content };
10460
10500
  if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
10461
10501
  return entry;
10462
10502
  }).filter((m2) => m2 !== null);
@@ -11282,10 +11322,10 @@ function parseAttachment(obj) {
11282
11322
  const memories = raw.map((m2) => {
11283
11323
  if (!m2 || typeof m2 !== "object") return null;
11284
11324
  const rec = m2;
11285
- const path35 = typeof rec.path === "string" ? rec.path : null;
11325
+ const path36 = typeof rec.path === "string" ? rec.path : null;
11286
11326
  const content = typeof rec.content === "string" ? rec.content : null;
11287
- if (!path35 || content == null) return null;
11288
- const out = { path: path35, content };
11327
+ if (!path36 || content == null) return null;
11328
+ const out = { path: path36, content };
11289
11329
  if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
11290
11330
  return out;
11291
11331
  }).filter((m2) => m2 !== null);
@@ -18784,7 +18824,7 @@ var require_websocket = __commonJS({
18784
18824
  var http2 = require("http");
18785
18825
  var net = require("net");
18786
18826
  var tls = require("tls");
18787
- var { randomBytes: randomBytes2, createHash: createHash3 } = require("crypto");
18827
+ var { randomBytes: randomBytes3, createHash: createHash3 } = require("crypto");
18788
18828
  var { Duplex, Readable: Readable3 } = require("stream");
18789
18829
  var { URL: URL2 } = require("url");
18790
18830
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -19314,7 +19354,7 @@ var require_websocket = __commonJS({
19314
19354
  }
19315
19355
  }
19316
19356
  const defaultPort = isSecure ? 443 : 80;
19317
- const key = randomBytes2(16).toString("base64");
19357
+ const key = randomBytes3(16).toString("base64");
19318
19358
  const request = isSecure ? https.request : http2.request;
19319
19359
  const protocolSet = /* @__PURE__ */ new Set();
19320
19360
  let perMessageDeflate;
@@ -26112,62 +26152,190 @@ function cleanupGuestSessionsForCapability(cap, factory) {
26112
26152
  return { removed };
26113
26153
  }
26114
26154
 
26115
- // src/migrations/2026-05-20-flatten-sessions.ts
26155
+ // src/inbox/inbox-store.ts
26116
26156
  var fs17 = __toESM(require("fs"), 1);
26117
26157
  var path19 = __toESM(require("path"), 1);
26158
+ var INBOX_FILE_NAME = "inbox.jsonl";
26159
+ var InboxStore = class {
26160
+ constructor(dataDir) {
26161
+ this.dataDir = dataDir;
26162
+ fs17.mkdirSync(dataDir, { recursive: true });
26163
+ }
26164
+ dataDir;
26165
+ list() {
26166
+ const file = this.filePath();
26167
+ let raw;
26168
+ try {
26169
+ raw = fs17.readFileSync(file, "utf8");
26170
+ } catch (err) {
26171
+ if (err?.code === "ENOENT") return [];
26172
+ return [];
26173
+ }
26174
+ return parseAllLines(raw);
26175
+ }
26176
+ append(ev) {
26177
+ const file = this.filePath();
26178
+ const line = JSON.stringify(ev) + "\n";
26179
+ fs17.appendFileSync(file, line, { mode: 384 });
26180
+ try {
26181
+ fs17.chmodSync(file, 384);
26182
+ } catch {
26183
+ }
26184
+ }
26185
+ /**
26186
+ * 标记某条 event 为已读. 已有 readAt 时不覆盖 (idempotent: 第二次调用维持第一次时间).
26187
+ * 未知 id 静默 no-op (不抛, 不写文件).
26188
+ */
26189
+ markRead(id, at) {
26190
+ const events = this.list();
26191
+ let changed = false;
26192
+ const next = events.map((e) => {
26193
+ if (e.id !== id) return e;
26194
+ if (e.readAt !== void 0) return e;
26195
+ changed = true;
26196
+ return { ...e, readAt: at };
26197
+ });
26198
+ if (!changed) return;
26199
+ this.rewrite(next);
26200
+ }
26201
+ rewrite(events) {
26202
+ const file = this.filePath();
26203
+ const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
26204
+ const content = events.map((e) => JSON.stringify(e)).join("\n") + (events.length > 0 ? "\n" : "");
26205
+ fs17.writeFileSync(tmp, content, { mode: 384 });
26206
+ fs17.renameSync(tmp, file);
26207
+ try {
26208
+ fs17.chmodSync(file, 384);
26209
+ } catch {
26210
+ }
26211
+ }
26212
+ filePath() {
26213
+ return path19.join(this.dataDir, INBOX_FILE_NAME);
26214
+ }
26215
+ };
26216
+ function parseAllLines(raw) {
26217
+ const out = [];
26218
+ for (const line of raw.split("\n")) {
26219
+ const trimmed = line.trim();
26220
+ if (!trimmed) continue;
26221
+ let parsed;
26222
+ try {
26223
+ parsed = JSON.parse(trimmed);
26224
+ } catch {
26225
+ continue;
26226
+ }
26227
+ const r = InboxEventSchema.safeParse(parsed);
26228
+ if (r.success) out.push(r.data);
26229
+ }
26230
+ return out;
26231
+ }
26232
+
26233
+ // src/inbox/inbox-manager.ts
26234
+ var crypto6 = __toESM(require("crypto"), 1);
26235
+ var InboxManager = class {
26236
+ constructor(store, broadcast, opts = {}) {
26237
+ this.store = store;
26238
+ this.broadcast = broadcast;
26239
+ this.now = opts.now ?? Date.now;
26240
+ this.genId = opts.genId ?? defaultGenId;
26241
+ }
26242
+ store;
26243
+ broadcast;
26244
+ now;
26245
+ genId;
26246
+ /**
26247
+ * persona VM 内某 sender 给 CC 发消息 → 跨 principal 时记 inbox event.
26248
+ * 返回 null = owner 自己 (no-op); 否则返回写入的 event (含派生 id / createdAt).
26249
+ */
26250
+ recordPersonaMention(args) {
26251
+ if (args.sender.kind === "owner") return null;
26252
+ const resource = { type: "persona", id: args.personaId };
26253
+ const ev = {
26254
+ id: this.genId(),
26255
+ kind: "persona-mention",
26256
+ fromPrincipal: args.sender,
26257
+ toPrincipal: OWNER_PRINCIPAL,
26258
+ resource,
26259
+ preview: truncatePreview(args.preview),
26260
+ createdAt: this.now()
26261
+ };
26262
+ this.store.append(ev);
26263
+ this.broadcast({ type: "inbox:event", event: ev });
26264
+ return ev;
26265
+ }
26266
+ list(opts = {}) {
26267
+ const all = this.store.list();
26268
+ if (opts.includeRead) return all;
26269
+ return all.filter((e) => e.readAt === void 0);
26270
+ }
26271
+ markRead(eventId) {
26272
+ this.store.markRead(eventId, this.now());
26273
+ }
26274
+ };
26275
+ function truncatePreview(s) {
26276
+ if (s.length <= INBOX_PREVIEW_MAX_LENGTH) return s;
26277
+ return s.slice(0, INBOX_PREVIEW_MAX_LENGTH);
26278
+ }
26279
+ function defaultGenId() {
26280
+ return "inb_" + crypto6.randomBytes(6).toString("base64url");
26281
+ }
26282
+
26283
+ // src/migrations/2026-05-20-flatten-sessions.ts
26284
+ var fs18 = __toESM(require("fs"), 1);
26285
+ var path20 = __toESM(require("path"), 1);
26118
26286
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
26119
26287
  function migrateFlattenSessions(opts) {
26120
26288
  const dataDir = opts.dataDir;
26121
26289
  const now = opts.now ?? Date.now;
26122
- const sessionsDir = path19.join(dataDir, "sessions");
26123
- const flagPath = path19.join(sessionsDir, MIGRATION_FLAG_NAME);
26290
+ const sessionsDir = path20.join(dataDir, "sessions");
26291
+ const flagPath = path20.join(sessionsDir, MIGRATION_FLAG_NAME);
26124
26292
  if (existsSync3(flagPath)) {
26125
26293
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
26126
26294
  }
26127
26295
  let movedBare = 0;
26128
26296
  let movedVmOwner = 0;
26129
26297
  let archivedListener = 0;
26130
- const defaultDir = path19.join(sessionsDir, "default");
26298
+ const defaultDir = path20.join(sessionsDir, "default");
26131
26299
  if (existsSync3(defaultDir)) {
26132
26300
  for (const entry of readdirSafe(defaultDir)) {
26133
26301
  if (!entry.endsWith(".json")) continue;
26134
- const src = path19.join(defaultDir, entry);
26135
- const dst = path19.join(sessionsDir, entry);
26136
- fs17.renameSync(src, dst);
26302
+ const src = path20.join(defaultDir, entry);
26303
+ const dst = path20.join(sessionsDir, entry);
26304
+ fs18.renameSync(src, dst);
26137
26305
  movedBare += 1;
26138
26306
  }
26139
26307
  rmdirIfEmpty(defaultDir);
26140
26308
  }
26141
26309
  for (const pid of readdirSafe(sessionsDir)) {
26142
- const personaDir = path19.join(sessionsDir, pid);
26310
+ const personaDir = path20.join(sessionsDir, pid);
26143
26311
  if (!isDir(personaDir)) continue;
26144
26312
  if (pid === "default") continue;
26145
- const ownerSrc = path19.join(personaDir, "owner");
26313
+ const ownerSrc = path20.join(personaDir, "owner");
26146
26314
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
26147
- const ownerDst = path19.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
26148
- fs17.mkdirSync(ownerDst, { recursive: true });
26315
+ const ownerDst = path20.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
26316
+ fs18.mkdirSync(ownerDst, { recursive: true });
26149
26317
  for (const file of readdirSafe(ownerSrc)) {
26150
26318
  if (!file.endsWith(".json")) continue;
26151
- fs17.renameSync(path19.join(ownerSrc, file), path19.join(ownerDst, file));
26319
+ fs18.renameSync(path20.join(ownerSrc, file), path20.join(ownerDst, file));
26152
26320
  movedVmOwner += 1;
26153
26321
  }
26154
26322
  rmdirIfEmpty(ownerSrc);
26155
26323
  }
26156
- const listenerSrc = path19.join(personaDir, "listener");
26324
+ const listenerSrc = path20.join(personaDir, "listener");
26157
26325
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
26158
- const archiveDst = path19.join(dataDir, ".legacy", `listener-${pid}`);
26159
- fs17.mkdirSync(archiveDst, { recursive: true });
26326
+ const archiveDst = path20.join(dataDir, ".legacy", `listener-${pid}`);
26327
+ fs18.mkdirSync(archiveDst, { recursive: true });
26160
26328
  for (const file of readdirSafe(listenerSrc)) {
26161
26329
  if (!file.endsWith(".json")) continue;
26162
- fs17.renameSync(path19.join(listenerSrc, file), path19.join(archiveDst, file));
26330
+ fs18.renameSync(path20.join(listenerSrc, file), path20.join(archiveDst, file));
26163
26331
  archivedListener += 1;
26164
26332
  }
26165
26333
  rmdirIfEmpty(listenerSrc);
26166
26334
  }
26167
26335
  rmdirIfEmpty(personaDir);
26168
26336
  }
26169
- fs17.mkdirSync(sessionsDir, { recursive: true });
26170
- fs17.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
26337
+ fs18.mkdirSync(sessionsDir, { recursive: true });
26338
+ fs18.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
26171
26339
  return {
26172
26340
  skipped: false,
26173
26341
  flagWritten: true,
@@ -26178,7 +26346,7 @@ function migrateFlattenSessions(opts) {
26178
26346
  }
26179
26347
  function existsSync3(p2) {
26180
26348
  try {
26181
- fs17.statSync(p2);
26349
+ fs18.statSync(p2);
26182
26350
  return true;
26183
26351
  } catch {
26184
26352
  return false;
@@ -26186,21 +26354,21 @@ function existsSync3(p2) {
26186
26354
  }
26187
26355
  function isDir(p2) {
26188
26356
  try {
26189
- return fs17.statSync(p2).isDirectory();
26357
+ return fs18.statSync(p2).isDirectory();
26190
26358
  } catch {
26191
26359
  return false;
26192
26360
  }
26193
26361
  }
26194
26362
  function readdirSafe(p2) {
26195
26363
  try {
26196
- return fs17.readdirSync(p2);
26364
+ return fs18.readdirSync(p2);
26197
26365
  } catch {
26198
26366
  return [];
26199
26367
  }
26200
26368
  }
26201
26369
  function rmdirIfEmpty(p2) {
26202
26370
  try {
26203
- fs17.rmdirSync(p2);
26371
+ fs18.rmdirSync(p2);
26204
26372
  } catch {
26205
26373
  }
26206
26374
  }
@@ -28051,6 +28219,31 @@ function buildCapabilityHandlers(deps) {
28051
28219
  };
28052
28220
  }
28053
28221
 
28222
+ // src/handlers/inbox.ts
28223
+ function buildInboxHandlers(deps) {
28224
+ const { manager } = deps;
28225
+ const list = async (frame) => {
28226
+ const { type: _t, requestId: _r, ...rest } = frame;
28227
+ const args = InboxListArgsSchema.parse(rest);
28228
+ const events = manager.list({ includeRead: args.includeRead ?? false });
28229
+ return {
28230
+ response: { type: "inbox:list", events }
28231
+ };
28232
+ };
28233
+ const markRead = async (frame) => {
28234
+ const { type: _t, requestId: _r, ...rest } = frame;
28235
+ const args = InboxMarkReadArgsSchema.parse(rest);
28236
+ manager.markRead(args.eventId);
28237
+ return {
28238
+ response: { type: "inbox:markRead:ok", eventId: args.eventId }
28239
+ };
28240
+ };
28241
+ return {
28242
+ "inbox:list": list,
28243
+ "inbox:markRead": markRead
28244
+ };
28245
+ }
28246
+
28054
28247
  // src/handlers/meta.ts
28055
28248
  var import_node_os13 = __toESM(require("os"), 1);
28056
28249
  init_protocol();
@@ -28303,6 +28496,7 @@ function buildMethodHandlers(deps) {
28303
28496
  personaRegistry: deps.personaRegistry
28304
28497
  }),
28305
28498
  ...buildCapabilityHandlers({ manager: deps.capabilityManager }),
28499
+ ...buildInboxHandlers({ manager: deps.inboxManager }),
28306
28500
  ...deps.attachment ? buildAttachmentHandlers(deps.attachment) : {}
28307
28501
  };
28308
28502
  }
@@ -28321,6 +28515,9 @@ var METHOD_GRANT_MAP = {
28321
28515
  "capability:issue": ADMIN_ANY,
28322
28516
  "capability:list": ADMIN_ANY,
28323
28517
  "capability:revoke": ADMIN_ANY,
28518
+ // ---- inbox 跨用户通知 (Phase 3 admin-only, owner 调; Phase 4 加 postMessage) ----
28519
+ "inbox:list": ADMIN_ANY,
28520
+ "inbox:markRead": ADMIN_ANY,
28324
28521
  // ---- 业务方法:Phase 1 全 admin-only(owner 自动通过;guest 无法调用) ----
28325
28522
  "session:create": ADMIN_ANY,
28326
28523
  "session:list": ADMIN_ANY,
@@ -28451,6 +28648,10 @@ async function startDaemon(config) {
28451
28648
  }
28452
28649
  }
28453
28650
  });
28651
+ const inboxStore = new InboxStore(config.dataDir);
28652
+ const inboxManager = new InboxManager(inboxStore, (frame) => {
28653
+ wsServer?.broadcastToOwners(frame);
28654
+ });
28454
28655
  let wsServer = null;
28455
28656
  const authGate = authMode === "first-message" ? new AuthGate({
28456
28657
  shouldEnforce: buildShouldEnforce({ tunnel: config.tunnel }),
@@ -28640,7 +28841,9 @@ async function startDaemon(config) {
28640
28841
  }
28641
28842
  },
28642
28843
  // Task 1.9: capability:issue/list/revoke handler 依赖
28643
- capabilityManager
28844
+ capabilityManager,
28845
+ // Phase 3 Task 3.4: inbox:list/markRead handler 依赖
28846
+ inboxManager
28644
28847
  });
28645
28848
  const authResolver = new AuthContextResolver({
28646
28849
  ownerToken: resolvedAuthToken,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.71-beta.124.b09b0a0",
3
+ "version": "0.2.71-beta.125.4951782",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",