@clawos-dev/clawd 0.2.79 → 0.2.80-beta.151.166c577
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +358 -201
- 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:
|
|
650
|
-
const fullPath = [...
|
|
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,
|
|
961
|
+
constructor(parent, value, path42, key) {
|
|
962
962
|
this._cachedPath = [];
|
|
963
963
|
this.parent = parent;
|
|
964
964
|
this.data = value;
|
|
965
|
-
this._path =
|
|
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
|
|
5568
|
-
_req.url = typeof
|
|
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(
|
|
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 <
|
|
5740
|
-
const char =
|
|
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
|
|
5872
|
-
const parts = parsePath(
|
|
5871
|
+
for (const path42 of paths) {
|
|
5872
|
+
const parts = parsePath(path42);
|
|
5873
5873
|
if (parts.includes("*")) {
|
|
5874
|
-
redactWildcardPath(obj, parts, censor,
|
|
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,
|
|
5960
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
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
|
|
5996
|
-
const parts = parsePath(
|
|
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(
|
|
6049
|
-
if (typeof
|
|
6048
|
+
function validatePath(path42) {
|
|
6049
|
+
if (typeof path42 !== "string") {
|
|
6050
6050
|
throw new Error("Paths must be (non-empty) strings");
|
|
6051
6051
|
}
|
|
6052
|
-
if (
|
|
6052
|
+
if (path42 === "") {
|
|
6053
6053
|
throw new Error("Invalid redaction path ()");
|
|
6054
6054
|
}
|
|
6055
|
-
if (
|
|
6056
|
-
throw new Error(`Invalid redaction path (${
|
|
6055
|
+
if (path42.includes("..")) {
|
|
6056
|
+
throw new Error(`Invalid redaction path (${path42})`);
|
|
6057
6057
|
}
|
|
6058
|
-
if (
|
|
6059
|
-
throw new Error(`Invalid redaction path (${
|
|
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 <
|
|
6065
|
-
const char =
|
|
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 (${
|
|
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 (${
|
|
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
|
|
6092
|
-
validatePath(
|
|
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,
|
|
6261
|
-
return censor(value, [k2, ...
|
|
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
|
|
6479
|
+
var fs33 = require("fs");
|
|
6480
6480
|
var EventEmitter2 = require("events");
|
|
6481
6481
|
var inherits = require("util").inherits;
|
|
6482
|
-
var
|
|
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)
|
|
6537
|
-
const fd =
|
|
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
|
-
|
|
6544
|
+
fs33.mkdir(path42.dirname(file), { recursive: true }, (err) => {
|
|
6545
6545
|
if (err) return fileOpened(err);
|
|
6546
|
-
|
|
6546
|
+
fs33.open(file, flags, mode, fileOpened);
|
|
6547
6547
|
});
|
|
6548
6548
|
} else {
|
|
6549
|
-
|
|
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 = () =>
|
|
6591
|
-
fsWrite = () =>
|
|
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
|
|
6600
|
+
return fs33.writeSync(this.fd, this._writingBuf);
|
|
6601
6601
|
}
|
|
6602
|
-
return
|
|
6602
|
+
return fs33.writeSync(this.fd, this._writingBuf, "utf8");
|
|
6603
6603
|
};
|
|
6604
6604
|
fsWrite = () => {
|
|
6605
6605
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
6606
|
-
return
|
|
6606
|
+
return fs33.write(this.fd, this._writingBuf, this.release);
|
|
6607
6607
|
}
|
|
6608
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) ?
|
|
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
|
-
|
|
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 =
|
|
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) ?
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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 (
|
|
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() +
|
|
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
|
|
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 =
|
|
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(
|
|
10176
|
-
var last =
|
|
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:
|
|
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:
|
|
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
|
|
10620
|
+
const path42 = typeof rec.path === "string" ? rec.path : null;
|
|
10621
10621
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
10622
|
-
if (!
|
|
10623
|
-
const entry = { path:
|
|
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
|
|
11087
|
-
return cwd.startsWith(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
|
|
11449
|
+
const path42 = typeof rec.path === "string" ? rec.path : null;
|
|
11450
11450
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
11451
|
-
if (!
|
|
11452
|
-
const out = { path:
|
|
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((
|
|
20372
|
+
const closed = new Promise((resolve6) => {
|
|
20373
20373
|
closedResolve = () => {
|
|
20374
20374
|
if (closedSettled) return;
|
|
20375
20375
|
closedSettled = true;
|
|
20376
|
-
|
|
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((
|
|
20469
|
-
resolveProcExit =
|
|
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((
|
|
21896
|
-
closedResolve =
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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:
|
|
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((
|
|
25046
|
+
return new Promise((resolve6) => {
|
|
25047
25047
|
term.write(data, () => {
|
|
25048
25048
|
tick();
|
|
25049
|
-
|
|
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((
|
|
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
|
-
|
|
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((
|
|
25752
|
-
this.wss?.close(() =>
|
|
25751
|
+
await new Promise((resolve6) => {
|
|
25752
|
+
this.wss?.close(() => resolve6());
|
|
25753
25753
|
});
|
|
25754
|
-
await new Promise((
|
|
25755
|
-
this.httpServer?.close(() =>
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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
|
|
26876
|
-
var
|
|
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 =
|
|
26882
|
-
const flagPath =
|
|
26883
|
-
if (
|
|
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 =
|
|
26890
|
-
if (
|
|
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 =
|
|
26894
|
-
const dst =
|
|
26895
|
-
|
|
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 =
|
|
26880
|
+
const personaDir = path21.join(sessionsDir, pid);
|
|
26902
26881
|
if (!isDir(personaDir)) continue;
|
|
26903
26882
|
if (pid === "default") continue;
|
|
26904
|
-
const ownerSrc =
|
|
26905
|
-
if (
|
|
26906
|
-
const ownerDst =
|
|
26907
|
-
|
|
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
|
-
|
|
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 =
|
|
26916
|
-
if (
|
|
26917
|
-
const archiveDst =
|
|
26918
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26929
|
-
|
|
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
|
|
26917
|
+
function existsSync3(p2) {
|
|
26939
26918
|
try {
|
|
26940
|
-
|
|
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
|
|
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
|
|
26934
|
+
return fs19.readdirSync(p2);
|
|
26956
26935
|
} catch {
|
|
26957
26936
|
return [];
|
|
26958
26937
|
}
|
|
26959
26938
|
}
|
|
26960
26939
|
function rmdirIfEmpty(p2) {
|
|
26961
26940
|
try {
|
|
26962
|
-
|
|
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((
|
|
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 ?
|
|
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((
|
|
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
|
-
|
|
27816
|
+
resolve6(pids);
|
|
27838
27817
|
});
|
|
27839
27818
|
ps.on("error", (e) => {
|
|
27840
27819
|
logger?.warn("tunnel: ps scan failed", { err: e.message });
|
|
27841
|
-
|
|
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((
|
|
27898
|
+
await new Promise((resolve6) => {
|
|
27920
27899
|
const t = setTimeout(() => {
|
|
27921
27900
|
try {
|
|
27922
27901
|
proc.kill("SIGKILL");
|
|
27923
27902
|
} catch {
|
|
27924
27903
|
}
|
|
27925
|
-
|
|
27904
|
+
resolve6();
|
|
27926
27905
|
}, 5e3);
|
|
27927
27906
|
proc.once("exit", () => {
|
|
27928
27907
|
clearTimeout(t);
|
|
27929
|
-
|
|
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((
|
|
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
|
-
|
|
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,27 +28688,82 @@ 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 buildEnabledPluginNames(personaManager, personaId) {
|
|
28696
|
+
const out = /* @__PURE__ */ new Set();
|
|
28697
|
+
for (const p2 of personaManager.listEnabledPlugins(personaId)) {
|
|
28698
|
+
const name = p2.id.includes("@") ? p2.id.slice(0, p2.id.indexOf("@")) : p2.id;
|
|
28699
|
+
if (name) out.add(name);
|
|
28700
|
+
}
|
|
28701
|
+
return out;
|
|
28702
|
+
}
|
|
28703
|
+
function filterGuestSkills(list, enabledPluginNames) {
|
|
28704
|
+
return list.filter((e) => {
|
|
28705
|
+
if (e.source === "builtin" || e.source === "project") return true;
|
|
28706
|
+
if (e.source === "plugin") return !!e.plugin && enabledPluginNames.has(e.plugin);
|
|
28707
|
+
return false;
|
|
28708
|
+
});
|
|
28709
|
+
}
|
|
28710
|
+
function filterGuestAgents(list, enabledPluginNames) {
|
|
28711
|
+
return list.filter((e) => {
|
|
28712
|
+
if (e.source === "builtin" || e.source === "project") return true;
|
|
28713
|
+
if (e.source === "plugin") return !!e.plugin && enabledPluginNames.has(e.plugin);
|
|
28714
|
+
return false;
|
|
28715
|
+
});
|
|
28716
|
+
}
|
|
28717
|
+
function assertGuestPath2(ctx, absPath, personaRoot, method) {
|
|
28718
|
+
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
28719
|
+
if (!isGuestPathAllowed(ctx.grants, absPath, personaRoot, "read")) {
|
|
28720
|
+
throw new ClawdError(
|
|
28721
|
+
ERROR_CODES.UNAUTHORIZED,
|
|
28722
|
+
`guest ${ctx.principal.id} cannot ${method} path ${absPath}`
|
|
28723
|
+
);
|
|
28724
|
+
}
|
|
28725
|
+
}
|
|
28644
28726
|
function buildWorkspaceHandlers(deps) {
|
|
28645
|
-
const { workspace, skills, agents } = deps;
|
|
28646
|
-
const list = async (frame) => {
|
|
28727
|
+
const { workspace, skills, agents, personaRoot, personaManager } = deps;
|
|
28728
|
+
const list = async (frame, _client, ctx) => {
|
|
28647
28729
|
const args = WorkspaceListArgs.parse(frame);
|
|
28648
|
-
const
|
|
28730
|
+
const isGuest = ctx?.principal.kind === "guest";
|
|
28731
|
+
const fallbackCwd = isGuest && personaRoot ? personaRoot : os13.homedir();
|
|
28732
|
+
const resolvedCwd = path35.resolve(args.cwd ?? fallbackCwd);
|
|
28733
|
+
const target = args.path ? path35.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
28734
|
+
assertGuestPath2(ctx, target, personaRoot, "workspace:list");
|
|
28735
|
+
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
28649
28736
|
return { response: { type: "workspace:list", ...res } };
|
|
28650
28737
|
};
|
|
28651
|
-
const read = async (frame) => {
|
|
28738
|
+
const read = async (frame, _client, ctx) => {
|
|
28652
28739
|
const args = WorkspaceReadArgs.parse(frame);
|
|
28740
|
+
const target = path35.isAbsolute(args.path) ? path35.resolve(args.path) : path35.resolve(args.cwd, args.path);
|
|
28741
|
+
assertGuestPath2(ctx, target, personaRoot, "workspace:read");
|
|
28653
28742
|
const res = workspace.read(args);
|
|
28654
28743
|
return { response: { type: "workspace:read", ...res } };
|
|
28655
28744
|
};
|
|
28656
|
-
const skillsList = async (frame) => {
|
|
28745
|
+
const skillsList = async (frame, _client, ctx) => {
|
|
28657
28746
|
const args = SkillsListArgs.parse(frame);
|
|
28747
|
+
const cwdAbs = path35.resolve(args.cwd);
|
|
28748
|
+
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list");
|
|
28658
28749
|
const list2 = skills.list(args);
|
|
28750
|
+
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
28751
|
+
const personaId = personaIdFromPath(cwdAbs, personaRoot);
|
|
28752
|
+
const enabled = personaId ? buildEnabledPluginNames(personaManager, personaId) : /* @__PURE__ */ new Set();
|
|
28753
|
+
return { response: { type: "skills:list", skills: filterGuestSkills(list2, enabled) } };
|
|
28754
|
+
}
|
|
28659
28755
|
return { response: { type: "skills:list", skills: list2 } };
|
|
28660
28756
|
};
|
|
28661
|
-
const agentsList = async (frame) => {
|
|
28757
|
+
const agentsList = async (frame, _client, ctx) => {
|
|
28662
28758
|
const args = AgentsListArgs.parse(frame);
|
|
28759
|
+
const cwdAbs = path35.resolve(args.cwd);
|
|
28760
|
+
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list");
|
|
28663
28761
|
const list2 = agents.list(args);
|
|
28762
|
+
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
28763
|
+
const personaId = personaIdFromPath(cwdAbs, personaRoot);
|
|
28764
|
+
const enabled = personaId ? buildEnabledPluginNames(personaManager, personaId) : /* @__PURE__ */ new Set();
|
|
28765
|
+
return { response: { type: "agents:list", agents: filterGuestAgents(list2, enabled) } };
|
|
28766
|
+
}
|
|
28664
28767
|
return { response: { type: "agents:list", agents: list2 } };
|
|
28665
28768
|
};
|
|
28666
28769
|
return {
|
|
@@ -28672,6 +28775,8 @@ function buildWorkspaceHandlers(deps) {
|
|
|
28672
28775
|
}
|
|
28673
28776
|
|
|
28674
28777
|
// src/handlers/git.ts
|
|
28778
|
+
var path37 = __toESM(require("path"), 1);
|
|
28779
|
+
init_protocol();
|
|
28675
28780
|
init_protocol();
|
|
28676
28781
|
|
|
28677
28782
|
// src/workspace/git.ts
|
|
@@ -28754,19 +28859,32 @@ async function listGitBranches(cwd) {
|
|
|
28754
28859
|
}
|
|
28755
28860
|
|
|
28756
28861
|
// src/handlers/git.ts
|
|
28757
|
-
function
|
|
28758
|
-
|
|
28862
|
+
function assertGuestCwd(ctx, cwd, personaRoot, method) {
|
|
28863
|
+
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
28864
|
+
if (!isGuestPathAllowed(ctx.grants, path37.resolve(cwd), personaRoot, "read")) {
|
|
28865
|
+
throw new ClawdError(
|
|
28866
|
+
ERROR_CODES.UNAUTHORIZED,
|
|
28867
|
+
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
28868
|
+
);
|
|
28869
|
+
}
|
|
28870
|
+
}
|
|
28871
|
+
function buildGitHandlers(deps) {
|
|
28872
|
+
const { personaRoot } = deps;
|
|
28873
|
+
const root = async (frame, _client, ctx) => {
|
|
28759
28874
|
const args = GitRootArgs.parse(frame);
|
|
28875
|
+
assertGuestCwd(ctx, args.cwd, personaRoot, "git:root");
|
|
28760
28876
|
const res = await getGitRoot(args.cwd);
|
|
28761
28877
|
return { response: { type: "git:root", ...res } };
|
|
28762
28878
|
};
|
|
28763
|
-
const branch = async (frame) => {
|
|
28879
|
+
const branch = async (frame, _client, ctx) => {
|
|
28764
28880
|
const args = GitBranchArgs.parse(frame);
|
|
28881
|
+
assertGuestCwd(ctx, args.cwd, personaRoot, "git:branch");
|
|
28765
28882
|
const res = await readGitBranch(args.cwd);
|
|
28766
28883
|
return { response: { type: "git:branch", ...res } };
|
|
28767
28884
|
};
|
|
28768
|
-
const branches = async (frame) => {
|
|
28885
|
+
const branches = async (frame, _client, ctx) => {
|
|
28769
28886
|
const args = GitBranchesArgs.parse(frame);
|
|
28887
|
+
assertGuestCwd(ctx, args.cwd, personaRoot, "git:branches");
|
|
28770
28888
|
const res = await listGitBranches(args.cwd);
|
|
28771
28889
|
return { response: { type: "git:branches", ...res } };
|
|
28772
28890
|
};
|
|
@@ -29203,12 +29321,19 @@ function buildPersonaHandlers(deps) {
|
|
|
29203
29321
|
response: { type: "persona:list", personas }
|
|
29204
29322
|
};
|
|
29205
29323
|
};
|
|
29206
|
-
const get = async (frame) => {
|
|
29324
|
+
const get = async (frame, _client, ctx) => {
|
|
29207
29325
|
const args = PersonaIdArgsSchema.parse(frame);
|
|
29208
29326
|
const persona = personaRegistry.get(args.personaId) ?? null;
|
|
29209
29327
|
if (!persona) {
|
|
29210
29328
|
return { response: { type: "persona:info", persona: null } };
|
|
29211
29329
|
}
|
|
29330
|
+
const isGuest = ctx?.principal.kind === "guest";
|
|
29331
|
+
if (isGuest) {
|
|
29332
|
+
const allowed = persona.public && assertGrant(ctx.grants, { type: "persona", id: persona.personaId }, "read");
|
|
29333
|
+
if (!allowed) {
|
|
29334
|
+
return { response: { type: "persona:info", persona: null } };
|
|
29335
|
+
}
|
|
29336
|
+
}
|
|
29212
29337
|
const personality = personaManager.readPersonality(args.personaId) ?? "";
|
|
29213
29338
|
const skills = personaManager.listSkills(args.personaId);
|
|
29214
29339
|
const plugins = personaManager.listEnabledPlugins(args.personaId);
|
|
@@ -29252,8 +29377,17 @@ var import_node_path26 = __toESM(require("path"), 1);
|
|
|
29252
29377
|
init_protocol();
|
|
29253
29378
|
init_protocol();
|
|
29254
29379
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
29380
|
+
function assertGuestAttachmentPath(ctx, absPath, personaRoot, method) {
|
|
29381
|
+
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
29382
|
+
if (!isGuestPathAllowed(ctx.grants, absPath, personaRoot, "read")) {
|
|
29383
|
+
throw new ClawdError(
|
|
29384
|
+
ERROR_CODES.UNAUTHORIZED,
|
|
29385
|
+
`guest ${ctx.principal.id} cannot ${method} path ${absPath}`
|
|
29386
|
+
);
|
|
29387
|
+
}
|
|
29388
|
+
}
|
|
29255
29389
|
function buildAttachmentHandlers(deps) {
|
|
29256
|
-
const signUrl = async (frame) => {
|
|
29390
|
+
const signUrl = async (frame, _client, ctx) => {
|
|
29257
29391
|
const parsed = AttachmentSignUrlArgs.safeParse(frame);
|
|
29258
29392
|
if (!parsed.success) {
|
|
29259
29393
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, parsed.error.message);
|
|
@@ -29295,6 +29429,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
29295
29429
|
}
|
|
29296
29430
|
const cwdAbs = import_node_path26.default.resolve(sessionFile.cwd);
|
|
29297
29431
|
const candidateAbs = import_node_path26.default.isAbsolute(args.relPath) ? import_node_path26.default.resolve(args.relPath) : import_node_path26.default.resolve(cwdAbs, args.relPath);
|
|
29432
|
+
assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl");
|
|
29298
29433
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
29299
29434
|
const entry = entries.find((e) => {
|
|
29300
29435
|
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 +29452,13 @@ function buildAttachmentHandlers(deps) {
|
|
|
29317
29452
|
}
|
|
29318
29453
|
};
|
|
29319
29454
|
};
|
|
29320
|
-
|
|
29455
|
+
function guardGuestBySessionCwd(ctx, sessionId, method) {
|
|
29456
|
+
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
29457
|
+
const f = deps.sessionStore.read(sessionId);
|
|
29458
|
+
if (!f) return;
|
|
29459
|
+
assertGuestAttachmentPath(ctx, import_node_path26.default.resolve(f.cwd), deps.personaRoot, method);
|
|
29460
|
+
}
|
|
29461
|
+
const groupAdd = async (frame, _client, ctx) => {
|
|
29321
29462
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
29322
29463
|
throw new ClawdError(ERROR_CODES.METHOD_NOT_IMPLEMENTED, "groupFileStore not wired");
|
|
29323
29464
|
}
|
|
@@ -29326,6 +29467,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
29326
29467
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, parsed.error.message);
|
|
29327
29468
|
}
|
|
29328
29469
|
const args = parsed.data;
|
|
29470
|
+
guardGuestBySessionCwd(ctx, args.sessionId, "attachment.groupAdd");
|
|
29329
29471
|
const scope = deps.getSessionScope(args.sessionId);
|
|
29330
29472
|
if (!scope) {
|
|
29331
29473
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
@@ -29340,7 +29482,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
29340
29482
|
});
|
|
29341
29483
|
return { response: { type: "attachment.groupAdd", entry } };
|
|
29342
29484
|
};
|
|
29343
|
-
const groupRemove = async (frame) => {
|
|
29485
|
+
const groupRemove = async (frame, _client, ctx) => {
|
|
29344
29486
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
29345
29487
|
throw new ClawdError(ERROR_CODES.METHOD_NOT_IMPLEMENTED, "groupFileStore not wired");
|
|
29346
29488
|
}
|
|
@@ -29348,6 +29490,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
29348
29490
|
if (!parsed.success) {
|
|
29349
29491
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, parsed.error.message);
|
|
29350
29492
|
}
|
|
29493
|
+
guardGuestBySessionCwd(ctx, parsed.data.sessionId, "attachment.groupRemove");
|
|
29351
29494
|
const scope = deps.getSessionScope(parsed.data.sessionId);
|
|
29352
29495
|
if (!scope) {
|
|
29353
29496
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "session not found");
|
|
@@ -29361,7 +29504,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
29361
29504
|
}
|
|
29362
29505
|
return { response: { type: "attachment.groupRemove", removed: true } };
|
|
29363
29506
|
};
|
|
29364
|
-
const groupList = async (frame) => {
|
|
29507
|
+
const groupList = async (frame, _client, ctx) => {
|
|
29365
29508
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
29366
29509
|
throw new ClawdError(ERROR_CODES.METHOD_NOT_IMPLEMENTED, "groupFileStore not wired");
|
|
29367
29510
|
}
|
|
@@ -29369,6 +29512,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
29369
29512
|
if (!parsed.success) {
|
|
29370
29513
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, parsed.error.message);
|
|
29371
29514
|
}
|
|
29515
|
+
guardGuestBySessionCwd(ctx, parsed.data.sessionId, "attachment.groupList");
|
|
29372
29516
|
const scope = deps.getSessionScope(parsed.data.sessionId);
|
|
29373
29517
|
if (!scope) return { response: { type: "attachment.groupList", entries: [] } };
|
|
29374
29518
|
const entries = deps.groupFileStore.list(scope, parsed.data.sessionId);
|
|
@@ -29389,7 +29533,7 @@ function buildMethodHandlers(deps) {
|
|
|
29389
29533
|
...buildPermissionHandlers(deps),
|
|
29390
29534
|
...buildHistoryHandlers(deps),
|
|
29391
29535
|
...buildWorkspaceHandlers(deps),
|
|
29392
|
-
...buildGitHandlers(),
|
|
29536
|
+
...buildGitHandlers(deps),
|
|
29393
29537
|
...buildCapabilitiesHandlers(deps),
|
|
29394
29538
|
...buildMetaHandlers(deps),
|
|
29395
29539
|
...buildPersonaHandlers({
|
|
@@ -29480,39 +29624,49 @@ var METHOD_GRANT_MAP = {
|
|
|
29480
29624
|
"permission:respond": CAPABILITY_SCOPED,
|
|
29481
29625
|
"session:answerQuestion": CAPABILITY_SCOPED,
|
|
29482
29626
|
"session:cancelQuestion": CAPABILITY_SCOPED,
|
|
29483
|
-
|
|
29484
|
-
|
|
29627
|
+
// 2026-05-25 老板拍板:guest 用别人 daemon 的 chat 必须能读 history / workspace /
|
|
29628
|
+
// attachment / skills / agents / git 元信息,下沉到 capability-scoped;handler 内
|
|
29629
|
+
// 用 isGuestPathAllowed (persona-paths.ts) 限制路径必须在 personaRoot/<allowed-pid>/** 下,
|
|
29630
|
+
// 防止跨 persona 越权读 owner 私有文件。
|
|
29631
|
+
"history:projects": CAPABILITY_SCOPED,
|
|
29632
|
+
"history:list": CAPABILITY_SCOPED,
|
|
29485
29633
|
// history:read 取一条 session 的 CC JSONL 历史。guest 进 persona VM 后必须能读自己
|
|
29486
29634
|
// 创建的 session 历史(chat view 加载历史消息走这条),所以下沉到 capability-scoped;
|
|
29487
29635
|
// handler 内按 ctx.capabilityId === file.creatorPrincipalId 拦越权。
|
|
29488
29636
|
"history:read": CAPABILITY_SCOPED,
|
|
29489
|
-
"history:subagents":
|
|
29490
|
-
"history:subagent-read":
|
|
29491
|
-
"history:recentDirs":
|
|
29492
|
-
"workspace:list":
|
|
29493
|
-
"workspace:read":
|
|
29494
|
-
"skills:list":
|
|
29495
|
-
"agents:list":
|
|
29496
|
-
"git:root":
|
|
29497
|
-
"git:branch":
|
|
29498
|
-
"git:branches":
|
|
29637
|
+
"history:subagents": CAPABILITY_SCOPED,
|
|
29638
|
+
"history:subagent-read": CAPABILITY_SCOPED,
|
|
29639
|
+
"history:recentDirs": CAPABILITY_SCOPED,
|
|
29640
|
+
"workspace:list": CAPABILITY_SCOPED,
|
|
29641
|
+
"workspace:read": CAPABILITY_SCOPED,
|
|
29642
|
+
"skills:list": CAPABILITY_SCOPED,
|
|
29643
|
+
"agents:list": CAPABILITY_SCOPED,
|
|
29644
|
+
"git:root": CAPABILITY_SCOPED,
|
|
29645
|
+
"git:branch": CAPABILITY_SCOPED,
|
|
29646
|
+
"git:branches": CAPABILITY_SCOPED,
|
|
29499
29647
|
"capabilities:get": ADMIN_ANY,
|
|
29500
29648
|
"persona:create": ADMIN_ANY,
|
|
29501
|
-
// persona:list 下沉到 CAPABILITY_SCOPED:guest
|
|
29502
|
-
//
|
|
29649
|
+
// persona:list / persona:get 下沉到 CAPABILITY_SCOPED:guest 调用合法
|
|
29650
|
+
// (list 用于 People 面板展开对方分享的 personas;get 用于 guest 视角下
|
|
29651
|
+
// PersonaDrawer 展示 persona 详情 readOnly),handler 端按 ctx + persona.public
|
|
29652
|
+
// + assertGrant 过滤,两者口径一致。
|
|
29653
|
+
// persona:update / persona:delete 保持 ADMIN_ANY:UI 端 guest viewerRole 下
|
|
29654
|
+
// 已干掉编辑入口,dispatcher 这层是双保险——非法 RPC 401 兜底。
|
|
29503
29655
|
"persona:list": CAPABILITY_SCOPED,
|
|
29504
|
-
"persona:get":
|
|
29656
|
+
"persona:get": CAPABILITY_SCOPED,
|
|
29505
29657
|
"persona:update": ADMIN_ANY,
|
|
29506
29658
|
"persona:delete": ADMIN_ANY,
|
|
29507
29659
|
"session:pty:input": ADMIN_ANY,
|
|
29508
29660
|
"session:pty:resize": ADMIN_ANY,
|
|
29509
29661
|
"session:pty:snapshot": ADMIN_ANY,
|
|
29510
|
-
// file-sharing attachment.* RPC:dispatcher
|
|
29511
|
-
//
|
|
29512
|
-
|
|
29513
|
-
|
|
29514
|
-
"attachment.
|
|
29515
|
-
"attachment.
|
|
29662
|
+
// file-sharing attachment.* RPC:dispatcher 放行;handler 内按 sessionId 反查
|
|
29663
|
+
// session.ownerPersonaId + ctx.grants 跑 assertGrant,限制 guest 只能签 / 操作
|
|
29664
|
+
// 自己被授权 persona 下的 session 文件。HTTP Bearer 仍然只识别 owner,所以 guest
|
|
29665
|
+
// 拿到 signed URL 后还要 HTTP 端校验通过才能取到文件——这里 RPC 层 ACL 是第一道。
|
|
29666
|
+
"attachment.signUrl": CAPABILITY_SCOPED,
|
|
29667
|
+
"attachment.groupAdd": CAPABILITY_SCOPED,
|
|
29668
|
+
"attachment.groupRemove": CAPABILITY_SCOPED,
|
|
29669
|
+
"attachment.groupList": CAPABILITY_SCOPED
|
|
29516
29670
|
};
|
|
29517
29671
|
function computeGrantForFrame(method, frame) {
|
|
29518
29672
|
const rule = METHOD_GRANT_MAP[method];
|
|
@@ -29552,7 +29706,6 @@ async function startDaemon(config) {
|
|
|
29552
29706
|
const ownerPrincipalId = authFile.ownerPrincipalId;
|
|
29553
29707
|
const ownerDisplayName = loadOwnerDisplayName(config.dataDir);
|
|
29554
29708
|
const authMode = resolvedAuthToken == null ? "none" : "first-message";
|
|
29555
|
-
migrateLegacyFiles(config.dataDir);
|
|
29556
29709
|
const inboxStore = new InboxStore(config.dataDir);
|
|
29557
29710
|
const inboxManager = new InboxManager(inboxStore, (_peerOwnerId, frame) => {
|
|
29558
29711
|
wsServer?.broadcastToOwners(frame);
|
|
@@ -29786,8 +29939,12 @@ async function startDaemon(config) {
|
|
|
29786
29939
|
getSignSecret: () => authFile?.signSecret ?? "",
|
|
29787
29940
|
// group RPC + sign 都用:根据 sessionId 反查 scope。owner-mode persona session 走
|
|
29788
29941
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
29789
|
-
getSessionScope: (sid) => manager.findOwnedSessionScope(sid)
|
|
29942
|
+
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
29943
|
+
// guest path guard:candidate 必须在 personaRoot 子树下
|
|
29944
|
+
personaRoot: import_node_path27.default.join(config.dataDir, "personas")
|
|
29790
29945
|
},
|
|
29946
|
+
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
29947
|
+
personaRoot: import_node_path27.default.join(config.dataDir, "personas"),
|
|
29791
29948
|
// Task 1.9: capability:issue/list/revoke handler 依赖
|
|
29792
29949
|
capabilityManager,
|
|
29793
29950
|
// v2 Phase 5: capability:issue 返回的 shareUrl 用此 base URL 拼接。
|
package/package.json
CHANGED