@clawos-dev/clawd 0.2.182 → 0.2.183-beta.365.f527c19
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 +940 -607
- package/package.json +1 -1
- package/dist/persona-defaults/persona-builder/CLAUDE.md +0 -160
package/dist/cli.cjs
CHANGED
|
@@ -157,6 +157,12 @@ var init_methods = __esm({
|
|
|
157
157
|
// 写入路径:device:connect 落 store + 自动反向(决策 #11);list / remove 作联系人列表读删。
|
|
158
158
|
"contact:list",
|
|
159
159
|
"contact:remove",
|
|
160
|
+
// ---- visitor:* (web 访客 · persona web 分享,spec 2026-06-24-persona-web-share-design) ----
|
|
161
|
+
// owner-only:列出登录访问过本机 public persona 的 web 访客(零安装、飞书登录、daemon 自签
|
|
162
|
+
// visitor token)。存储 ~/.clawd/visitors.json(VisitorStore),登录(exchange)即 upsert;
|
|
163
|
+
// 访客身份用 TTC unique_id,会话按 creatorPrincipalId='visitor-<id>' 进现有会话用户分组。
|
|
164
|
+
// 访客换 token 走 HTTP-only 公开路由 POST /share/exchange(非 WS method)。
|
|
165
|
+
"visitor:list",
|
|
160
166
|
// ---- whoami (v2 capability platform) ----
|
|
161
167
|
// 任何 authed connection 都能调;返回 owner 显示名 + 当前 capability wire 形态 +
|
|
162
168
|
// grants 对应的 persona 元数据 (id + displayName)。UI 端 AddRemotePersonaDialog
|
|
@@ -727,8 +733,8 @@ var init_parseUtil = __esm({
|
|
|
727
733
|
init_errors2();
|
|
728
734
|
init_en();
|
|
729
735
|
makeIssue = (params) => {
|
|
730
|
-
const { data, path:
|
|
731
|
-
const fullPath = [...
|
|
736
|
+
const { data, path: path66, errorMaps, issueData } = params;
|
|
737
|
+
const fullPath = [...path66, ...issueData.path || []];
|
|
732
738
|
const fullIssue = {
|
|
733
739
|
...issueData,
|
|
734
740
|
path: fullPath
|
|
@@ -1039,11 +1045,11 @@ var init_types = __esm({
|
|
|
1039
1045
|
init_parseUtil();
|
|
1040
1046
|
init_util();
|
|
1041
1047
|
ParseInputLazyPath = class {
|
|
1042
|
-
constructor(parent, value,
|
|
1048
|
+
constructor(parent, value, path66, key) {
|
|
1043
1049
|
this._cachedPath = [];
|
|
1044
1050
|
this.parent = parent;
|
|
1045
1051
|
this.data = value;
|
|
1046
|
-
this._path =
|
|
1052
|
+
this._path = path66;
|
|
1047
1053
|
this._key = key;
|
|
1048
1054
|
}
|
|
1049
1055
|
get path() {
|
|
@@ -6037,6 +6043,32 @@ var init_log = __esm({
|
|
|
6037
6043
|
}
|
|
6038
6044
|
});
|
|
6039
6045
|
|
|
6046
|
+
// ../protocol/src/visitor-schemas.ts
|
|
6047
|
+
var VisitorTokenPayloadSchema, VisitorRecordSchema, VisitorListResultSchema;
|
|
6048
|
+
var init_visitor_schemas = __esm({
|
|
6049
|
+
"../protocol/src/visitor-schemas.ts"() {
|
|
6050
|
+
"use strict";
|
|
6051
|
+
init_zod();
|
|
6052
|
+
VisitorTokenPayloadSchema = external_exports.object({
|
|
6053
|
+
v: external_exports.literal(1),
|
|
6054
|
+
visitorId: external_exports.string().min(1),
|
|
6055
|
+
displayName: external_exports.string(),
|
|
6056
|
+
provider: external_exports.string(),
|
|
6057
|
+
iat: external_exports.number(),
|
|
6058
|
+
exp: external_exports.number()
|
|
6059
|
+
});
|
|
6060
|
+
VisitorRecordSchema = external_exports.object({
|
|
6061
|
+
visitorId: external_exports.string(),
|
|
6062
|
+
displayName: external_exports.string(),
|
|
6063
|
+
avatarUrl: external_exports.string().optional(),
|
|
6064
|
+
provider: external_exports.string(),
|
|
6065
|
+
firstSeen: external_exports.number(),
|
|
6066
|
+
lastSeen: external_exports.number()
|
|
6067
|
+
});
|
|
6068
|
+
VisitorListResultSchema = external_exports.object({ visitors: external_exports.array(VisitorRecordSchema) });
|
|
6069
|
+
}
|
|
6070
|
+
});
|
|
6071
|
+
|
|
6040
6072
|
// ../protocol/src/runtime.ts
|
|
6041
6073
|
var init_runtime = __esm({
|
|
6042
6074
|
"../protocol/src/runtime.ts"() {
|
|
@@ -6057,6 +6089,7 @@ var init_runtime = __esm({
|
|
|
6057
6089
|
init_feishu_auth();
|
|
6058
6090
|
init_dispatch();
|
|
6059
6091
|
init_log();
|
|
6092
|
+
init_visitor_schemas();
|
|
6060
6093
|
}
|
|
6061
6094
|
});
|
|
6062
6095
|
|
|
@@ -6331,8 +6364,8 @@ var require_req = __commonJS({
|
|
|
6331
6364
|
if (req.originalUrl) {
|
|
6332
6365
|
_req.url = req.originalUrl;
|
|
6333
6366
|
} else {
|
|
6334
|
-
const
|
|
6335
|
-
_req.url = typeof
|
|
6367
|
+
const path66 = req.path;
|
|
6368
|
+
_req.url = typeof path66 === "string" ? path66 : req.url ? req.url.path || req.url : void 0;
|
|
6336
6369
|
}
|
|
6337
6370
|
if (req.query) {
|
|
6338
6371
|
_req.query = req.query;
|
|
@@ -6497,14 +6530,14 @@ var require_redact = __commonJS({
|
|
|
6497
6530
|
}
|
|
6498
6531
|
return obj;
|
|
6499
6532
|
}
|
|
6500
|
-
function parsePath(
|
|
6533
|
+
function parsePath(path66) {
|
|
6501
6534
|
const parts = [];
|
|
6502
6535
|
let current = "";
|
|
6503
6536
|
let inBrackets = false;
|
|
6504
6537
|
let inQuotes = false;
|
|
6505
6538
|
let quoteChar = "";
|
|
6506
|
-
for (let i = 0; i <
|
|
6507
|
-
const char =
|
|
6539
|
+
for (let i = 0; i < path66.length; i++) {
|
|
6540
|
+
const char = path66[i];
|
|
6508
6541
|
if (!inBrackets && char === ".") {
|
|
6509
6542
|
if (current) {
|
|
6510
6543
|
parts.push(current);
|
|
@@ -6635,10 +6668,10 @@ var require_redact = __commonJS({
|
|
|
6635
6668
|
return current;
|
|
6636
6669
|
}
|
|
6637
6670
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
6638
|
-
for (const
|
|
6639
|
-
const parts = parsePath(
|
|
6671
|
+
for (const path66 of paths) {
|
|
6672
|
+
const parts = parsePath(path66);
|
|
6640
6673
|
if (parts.includes("*")) {
|
|
6641
|
-
redactWildcardPath(obj, parts, censor,
|
|
6674
|
+
redactWildcardPath(obj, parts, censor, path66, remove);
|
|
6642
6675
|
} else {
|
|
6643
6676
|
if (remove) {
|
|
6644
6677
|
removeKey(obj, parts);
|
|
@@ -6723,8 +6756,8 @@ var require_redact = __commonJS({
|
|
|
6723
6756
|
}
|
|
6724
6757
|
} else {
|
|
6725
6758
|
if (afterWildcard.includes("*")) {
|
|
6726
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6727
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
6759
|
+
const wrappedCensor = typeof censor === "function" ? (value, path66) => {
|
|
6760
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path66];
|
|
6728
6761
|
return censor(value, fullPath);
|
|
6729
6762
|
} : censor;
|
|
6730
6763
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -6759,8 +6792,8 @@ var require_redact = __commonJS({
|
|
|
6759
6792
|
return null;
|
|
6760
6793
|
}
|
|
6761
6794
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
6762
|
-
for (const
|
|
6763
|
-
const parts = parsePath(
|
|
6795
|
+
for (const path66 of pathsToClone) {
|
|
6796
|
+
const parts = parsePath(path66);
|
|
6764
6797
|
let current = pathStructure;
|
|
6765
6798
|
for (let i = 0; i < parts.length; i++) {
|
|
6766
6799
|
const part = parts[i];
|
|
@@ -6812,24 +6845,24 @@ var require_redact = __commonJS({
|
|
|
6812
6845
|
}
|
|
6813
6846
|
return cloneSelectively(obj, pathStructure);
|
|
6814
6847
|
}
|
|
6815
|
-
function validatePath(
|
|
6816
|
-
if (typeof
|
|
6848
|
+
function validatePath(path66) {
|
|
6849
|
+
if (typeof path66 !== "string") {
|
|
6817
6850
|
throw new Error("Paths must be (non-empty) strings");
|
|
6818
6851
|
}
|
|
6819
|
-
if (
|
|
6852
|
+
if (path66 === "") {
|
|
6820
6853
|
throw new Error("Invalid redaction path ()");
|
|
6821
6854
|
}
|
|
6822
|
-
if (
|
|
6823
|
-
throw new Error(`Invalid redaction path (${
|
|
6855
|
+
if (path66.includes("..")) {
|
|
6856
|
+
throw new Error(`Invalid redaction path (${path66})`);
|
|
6824
6857
|
}
|
|
6825
|
-
if (
|
|
6826
|
-
throw new Error(`Invalid redaction path (${
|
|
6858
|
+
if (path66.includes(",")) {
|
|
6859
|
+
throw new Error(`Invalid redaction path (${path66})`);
|
|
6827
6860
|
}
|
|
6828
6861
|
let bracketCount = 0;
|
|
6829
6862
|
let inQuotes = false;
|
|
6830
6863
|
let quoteChar = "";
|
|
6831
|
-
for (let i = 0; i <
|
|
6832
|
-
const char =
|
|
6864
|
+
for (let i = 0; i < path66.length; i++) {
|
|
6865
|
+
const char = path66[i];
|
|
6833
6866
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
6834
6867
|
if (!inQuotes) {
|
|
6835
6868
|
inQuotes = true;
|
|
@@ -6843,20 +6876,20 @@ var require_redact = __commonJS({
|
|
|
6843
6876
|
} else if (char === "]" && !inQuotes) {
|
|
6844
6877
|
bracketCount--;
|
|
6845
6878
|
if (bracketCount < 0) {
|
|
6846
|
-
throw new Error(`Invalid redaction path (${
|
|
6879
|
+
throw new Error(`Invalid redaction path (${path66})`);
|
|
6847
6880
|
}
|
|
6848
6881
|
}
|
|
6849
6882
|
}
|
|
6850
6883
|
if (bracketCount !== 0) {
|
|
6851
|
-
throw new Error(`Invalid redaction path (${
|
|
6884
|
+
throw new Error(`Invalid redaction path (${path66})`);
|
|
6852
6885
|
}
|
|
6853
6886
|
}
|
|
6854
6887
|
function validatePaths(paths) {
|
|
6855
6888
|
if (!Array.isArray(paths)) {
|
|
6856
6889
|
throw new TypeError("paths must be an array");
|
|
6857
6890
|
}
|
|
6858
|
-
for (const
|
|
6859
|
-
validatePath(
|
|
6891
|
+
for (const path66 of paths) {
|
|
6892
|
+
validatePath(path66);
|
|
6860
6893
|
}
|
|
6861
6894
|
}
|
|
6862
6895
|
function slowRedact(options = {}) {
|
|
@@ -7024,8 +7057,8 @@ var require_redaction = __commonJS({
|
|
|
7024
7057
|
if (shape[k2] === null) {
|
|
7025
7058
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
7026
7059
|
} else {
|
|
7027
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
7028
|
-
return censor(value, [k2, ...
|
|
7060
|
+
const wrappedCensor = typeof censor === "function" ? (value, path66) => {
|
|
7061
|
+
return censor(value, [k2, ...path66]);
|
|
7029
7062
|
} : censor;
|
|
7030
7063
|
o[k2] = Redact({
|
|
7031
7064
|
paths: shape[k2],
|
|
@@ -7243,10 +7276,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
7243
7276
|
var require_sonic_boom = __commonJS({
|
|
7244
7277
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
7245
7278
|
"use strict";
|
|
7246
|
-
var
|
|
7279
|
+
var fs60 = require("fs");
|
|
7247
7280
|
var EventEmitter3 = require("events");
|
|
7248
7281
|
var inherits = require("util").inherits;
|
|
7249
|
-
var
|
|
7282
|
+
var path66 = require("path");
|
|
7250
7283
|
var sleep2 = require_atomic_sleep();
|
|
7251
7284
|
var assert = require("assert");
|
|
7252
7285
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -7300,20 +7333,20 @@ var require_sonic_boom = __commonJS({
|
|
|
7300
7333
|
const mode = sonic.mode;
|
|
7301
7334
|
if (sonic.sync) {
|
|
7302
7335
|
try {
|
|
7303
|
-
if (sonic.mkdir)
|
|
7304
|
-
const fd =
|
|
7336
|
+
if (sonic.mkdir) fs60.mkdirSync(path66.dirname(file), { recursive: true });
|
|
7337
|
+
const fd = fs60.openSync(file, flags, mode);
|
|
7305
7338
|
fileOpened(null, fd);
|
|
7306
7339
|
} catch (err) {
|
|
7307
7340
|
fileOpened(err);
|
|
7308
7341
|
throw err;
|
|
7309
7342
|
}
|
|
7310
7343
|
} else if (sonic.mkdir) {
|
|
7311
|
-
|
|
7344
|
+
fs60.mkdir(path66.dirname(file), { recursive: true }, (err) => {
|
|
7312
7345
|
if (err) return fileOpened(err);
|
|
7313
|
-
|
|
7346
|
+
fs60.open(file, flags, mode, fileOpened);
|
|
7314
7347
|
});
|
|
7315
7348
|
} else {
|
|
7316
|
-
|
|
7349
|
+
fs60.open(file, flags, mode, fileOpened);
|
|
7317
7350
|
}
|
|
7318
7351
|
}
|
|
7319
7352
|
function SonicBoom(opts) {
|
|
@@ -7354,8 +7387,8 @@ var require_sonic_boom = __commonJS({
|
|
|
7354
7387
|
this.flush = flushBuffer;
|
|
7355
7388
|
this.flushSync = flushBufferSync;
|
|
7356
7389
|
this._actualWrite = actualWriteBuffer;
|
|
7357
|
-
fsWriteSync = () =>
|
|
7358
|
-
fsWrite = () =>
|
|
7390
|
+
fsWriteSync = () => fs60.writeSync(this.fd, this._writingBuf);
|
|
7391
|
+
fsWrite = () => fs60.write(this.fd, this._writingBuf, this.release);
|
|
7359
7392
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
7360
7393
|
this._writingBuf = "";
|
|
7361
7394
|
this.write = write;
|
|
@@ -7364,15 +7397,15 @@ var require_sonic_boom = __commonJS({
|
|
|
7364
7397
|
this._actualWrite = actualWrite;
|
|
7365
7398
|
fsWriteSync = () => {
|
|
7366
7399
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7367
|
-
return
|
|
7400
|
+
return fs60.writeSync(this.fd, this._writingBuf);
|
|
7368
7401
|
}
|
|
7369
|
-
return
|
|
7402
|
+
return fs60.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7370
7403
|
};
|
|
7371
7404
|
fsWrite = () => {
|
|
7372
7405
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7373
|
-
return
|
|
7406
|
+
return fs60.write(this.fd, this._writingBuf, this.release);
|
|
7374
7407
|
}
|
|
7375
|
-
return
|
|
7408
|
+
return fs60.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
7376
7409
|
};
|
|
7377
7410
|
} else {
|
|
7378
7411
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -7429,7 +7462,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7429
7462
|
}
|
|
7430
7463
|
}
|
|
7431
7464
|
if (this._fsync) {
|
|
7432
|
-
|
|
7465
|
+
fs60.fsyncSync(this.fd);
|
|
7433
7466
|
}
|
|
7434
7467
|
const len = this._len;
|
|
7435
7468
|
if (this._reopening) {
|
|
@@ -7543,7 +7576,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7543
7576
|
const onDrain = () => {
|
|
7544
7577
|
if (!this._fsync) {
|
|
7545
7578
|
try {
|
|
7546
|
-
|
|
7579
|
+
fs60.fsync(this.fd, (err) => {
|
|
7547
7580
|
this._flushPending = false;
|
|
7548
7581
|
cb(err);
|
|
7549
7582
|
});
|
|
@@ -7645,7 +7678,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7645
7678
|
const fd = this.fd;
|
|
7646
7679
|
this.once("ready", () => {
|
|
7647
7680
|
if (fd !== this.fd) {
|
|
7648
|
-
|
|
7681
|
+
fs60.close(fd, (err) => {
|
|
7649
7682
|
if (err) {
|
|
7650
7683
|
return this.emit("error", err);
|
|
7651
7684
|
}
|
|
@@ -7694,7 +7727,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7694
7727
|
buf = this._bufs[0];
|
|
7695
7728
|
}
|
|
7696
7729
|
try {
|
|
7697
|
-
const n = Buffer.isBuffer(buf) ?
|
|
7730
|
+
const n = Buffer.isBuffer(buf) ? fs60.writeSync(this.fd, buf) : fs60.writeSync(this.fd, buf, "utf8");
|
|
7698
7731
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
7699
7732
|
buf = releasedBufObj.writingBuf;
|
|
7700
7733
|
this._len = releasedBufObj.len;
|
|
@@ -7710,7 +7743,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7710
7743
|
}
|
|
7711
7744
|
}
|
|
7712
7745
|
try {
|
|
7713
|
-
|
|
7746
|
+
fs60.fsyncSync(this.fd);
|
|
7714
7747
|
} catch {
|
|
7715
7748
|
}
|
|
7716
7749
|
}
|
|
@@ -7731,7 +7764,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7731
7764
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
7732
7765
|
}
|
|
7733
7766
|
try {
|
|
7734
|
-
const n =
|
|
7767
|
+
const n = fs60.writeSync(this.fd, buf);
|
|
7735
7768
|
buf = buf.subarray(n);
|
|
7736
7769
|
this._len = Math.max(this._len - n, 0);
|
|
7737
7770
|
if (buf.length <= 0) {
|
|
@@ -7759,13 +7792,13 @@ var require_sonic_boom = __commonJS({
|
|
|
7759
7792
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
7760
7793
|
if (this.sync) {
|
|
7761
7794
|
try {
|
|
7762
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
7795
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs60.writeSync(this.fd, this._writingBuf) : fs60.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7763
7796
|
release(null, written);
|
|
7764
7797
|
} catch (err) {
|
|
7765
7798
|
release(err);
|
|
7766
7799
|
}
|
|
7767
7800
|
} else {
|
|
7768
|
-
|
|
7801
|
+
fs60.write(this.fd, this._writingBuf, release);
|
|
7769
7802
|
}
|
|
7770
7803
|
}
|
|
7771
7804
|
function actualWriteBuffer() {
|
|
@@ -7774,7 +7807,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7774
7807
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
7775
7808
|
if (this.sync) {
|
|
7776
7809
|
try {
|
|
7777
|
-
const written =
|
|
7810
|
+
const written = fs60.writeSync(this.fd, this._writingBuf);
|
|
7778
7811
|
release(null, written);
|
|
7779
7812
|
} catch (err) {
|
|
7780
7813
|
release(err);
|
|
@@ -7783,7 +7816,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7783
7816
|
if (kCopyBuffer) {
|
|
7784
7817
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
7785
7818
|
}
|
|
7786
|
-
|
|
7819
|
+
fs60.write(this.fd, this._writingBuf, release);
|
|
7787
7820
|
}
|
|
7788
7821
|
}
|
|
7789
7822
|
function actualClose(sonic) {
|
|
@@ -7799,12 +7832,12 @@ var require_sonic_boom = __commonJS({
|
|
|
7799
7832
|
sonic._lens = [];
|
|
7800
7833
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
7801
7834
|
try {
|
|
7802
|
-
|
|
7835
|
+
fs60.fsync(sonic.fd, closeWrapped);
|
|
7803
7836
|
} catch {
|
|
7804
7837
|
}
|
|
7805
7838
|
function closeWrapped() {
|
|
7806
7839
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
7807
|
-
|
|
7840
|
+
fs60.close(sonic.fd, done);
|
|
7808
7841
|
} else {
|
|
7809
7842
|
done();
|
|
7810
7843
|
}
|
|
@@ -10939,11 +10972,11 @@ var init_lib = __esm({
|
|
|
10939
10972
|
}
|
|
10940
10973
|
}
|
|
10941
10974
|
},
|
|
10942
|
-
addToPath: function addToPath(
|
|
10943
|
-
var last =
|
|
10975
|
+
addToPath: function addToPath(path66, added, removed, oldPosInc, options) {
|
|
10976
|
+
var last = path66.lastComponent;
|
|
10944
10977
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
10945
10978
|
return {
|
|
10946
|
-
oldPos:
|
|
10979
|
+
oldPos: path66.oldPos + oldPosInc,
|
|
10947
10980
|
lastComponent: {
|
|
10948
10981
|
count: last.count + 1,
|
|
10949
10982
|
added,
|
|
@@ -10953,7 +10986,7 @@ var init_lib = __esm({
|
|
|
10953
10986
|
};
|
|
10954
10987
|
} else {
|
|
10955
10988
|
return {
|
|
10956
|
-
oldPos:
|
|
10989
|
+
oldPos: path66.oldPos + oldPosInc,
|
|
10957
10990
|
lastComponent: {
|
|
10958
10991
|
count: 1,
|
|
10959
10992
|
added,
|
|
@@ -11199,7 +11232,7 @@ function hashDirToCwd(hash) {
|
|
|
11199
11232
|
}
|
|
11200
11233
|
function safeStatMtime(p2) {
|
|
11201
11234
|
try {
|
|
11202
|
-
return
|
|
11235
|
+
return import_node_fs13.default.statSync(p2).mtimeMs;
|
|
11203
11236
|
} catch {
|
|
11204
11237
|
return 0;
|
|
11205
11238
|
}
|
|
@@ -11207,7 +11240,7 @@ function safeStatMtime(p2) {
|
|
|
11207
11240
|
function readJsonlLines(file) {
|
|
11208
11241
|
let raw;
|
|
11209
11242
|
try {
|
|
11210
|
-
raw =
|
|
11243
|
+
raw = import_node_fs13.default.readFileSync(file, "utf8");
|
|
11211
11244
|
} catch (err) {
|
|
11212
11245
|
if (err.code === "ENOENT") return [];
|
|
11213
11246
|
throw err;
|
|
@@ -11399,10 +11432,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
11399
11432
|
const memories = raw.map((m2) => {
|
|
11400
11433
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11401
11434
|
const rec3 = m2;
|
|
11402
|
-
const
|
|
11435
|
+
const path66 = typeof rec3.path === "string" ? rec3.path : null;
|
|
11403
11436
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
11404
|
-
if (!
|
|
11405
|
-
const entry = { path:
|
|
11437
|
+
if (!path66 || content == null) return null;
|
|
11438
|
+
const entry = { path: path66, content };
|
|
11406
11439
|
if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
|
|
11407
11440
|
return entry;
|
|
11408
11441
|
}).filter((m2) => m2 !== null);
|
|
@@ -11438,8 +11471,8 @@ function attachmentDeferredToolsText(a) {
|
|
|
11438
11471
|
function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
11439
11472
|
if (backupFileName === null) return null;
|
|
11440
11473
|
try {
|
|
11441
|
-
return
|
|
11442
|
-
|
|
11474
|
+
return import_node_fs13.default.readFileSync(
|
|
11475
|
+
import_node_path12.default.join(fileHistoryRoot, toolSessionId, backupFileName),
|
|
11443
11476
|
"utf8"
|
|
11444
11477
|
);
|
|
11445
11478
|
} catch {
|
|
@@ -11448,19 +11481,19 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
|
11448
11481
|
}
|
|
11449
11482
|
function readCurrentContent(filePath) {
|
|
11450
11483
|
try {
|
|
11451
|
-
return
|
|
11484
|
+
return import_node_fs13.default.readFileSync(filePath, "utf8");
|
|
11452
11485
|
} catch (err) {
|
|
11453
11486
|
if (err.code === "ENOENT") return null;
|
|
11454
11487
|
return null;
|
|
11455
11488
|
}
|
|
11456
11489
|
}
|
|
11457
|
-
var
|
|
11490
|
+
var import_node_fs13, import_node_os5, import_node_path12, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
|
|
11458
11491
|
var init_claude_history = __esm({
|
|
11459
11492
|
"src/tools/claude-history.ts"() {
|
|
11460
11493
|
"use strict";
|
|
11461
|
-
|
|
11494
|
+
import_node_fs13 = __toESM(require("fs"), 1);
|
|
11462
11495
|
import_node_os5 = __toESM(require("os"), 1);
|
|
11463
|
-
|
|
11496
|
+
import_node_path12 = __toESM(require("path"), 1);
|
|
11464
11497
|
init_lib();
|
|
11465
11498
|
init_tool_result_extra();
|
|
11466
11499
|
TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
|
|
@@ -11484,14 +11517,14 @@ var init_claude_history = __esm({
|
|
|
11484
11517
|
// 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
|
|
11485
11518
|
fileHistoryRoot;
|
|
11486
11519
|
constructor(opts = {}) {
|
|
11487
|
-
const base = opts.baseDir ??
|
|
11488
|
-
this.projectsRoot =
|
|
11489
|
-
this.fileHistoryRoot =
|
|
11520
|
+
const base = opts.baseDir ?? import_node_path12.default.join(import_node_os5.default.homedir(), ".claude");
|
|
11521
|
+
this.projectsRoot = import_node_path12.default.join(base, "projects");
|
|
11522
|
+
this.fileHistoryRoot = import_node_path12.default.join(base, "file-history");
|
|
11490
11523
|
}
|
|
11491
11524
|
async listProjects() {
|
|
11492
11525
|
let entries;
|
|
11493
11526
|
try {
|
|
11494
|
-
entries =
|
|
11527
|
+
entries = import_node_fs13.default.readdirSync(this.projectsRoot, { withFileTypes: true });
|
|
11495
11528
|
} catch (err) {
|
|
11496
11529
|
if (err.code === "ENOENT") return [];
|
|
11497
11530
|
throw err;
|
|
@@ -11499,9 +11532,9 @@ var init_claude_history = __esm({
|
|
|
11499
11532
|
const out = [];
|
|
11500
11533
|
for (const ent of entries) {
|
|
11501
11534
|
if (!ent.isDirectory()) continue;
|
|
11502
|
-
const dir =
|
|
11503
|
-
const files =
|
|
11504
|
-
const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(
|
|
11535
|
+
const dir = import_node_path12.default.join(this.projectsRoot, ent.name);
|
|
11536
|
+
const files = import_node_fs13.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
11537
|
+
const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path12.default.join(dir, f))), 0);
|
|
11505
11538
|
out.push({
|
|
11506
11539
|
projectPath: hashDirToCwd(ent.name),
|
|
11507
11540
|
hashDir: ent.name,
|
|
@@ -11513,17 +11546,17 @@ var init_claude_history = __esm({
|
|
|
11513
11546
|
return out;
|
|
11514
11547
|
}
|
|
11515
11548
|
async listSessions(args) {
|
|
11516
|
-
const dir =
|
|
11549
|
+
const dir = import_node_path12.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
|
|
11517
11550
|
let files;
|
|
11518
11551
|
try {
|
|
11519
|
-
files =
|
|
11552
|
+
files = import_node_fs13.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
11520
11553
|
} catch (err) {
|
|
11521
11554
|
if (err.code === "ENOENT") return [];
|
|
11522
11555
|
throw err;
|
|
11523
11556
|
}
|
|
11524
11557
|
const out = [];
|
|
11525
11558
|
for (const f of files) {
|
|
11526
|
-
const full =
|
|
11559
|
+
const full = import_node_path12.default.join(dir, f);
|
|
11527
11560
|
const toolSessionId = f.slice(0, -".jsonl".length);
|
|
11528
11561
|
const lines = readJsonlLines(full);
|
|
11529
11562
|
let summary = "";
|
|
@@ -11578,7 +11611,7 @@ var init_claude_history = __esm({
|
|
|
11578
11611
|
return out;
|
|
11579
11612
|
}
|
|
11580
11613
|
async read(args) {
|
|
11581
|
-
const file =
|
|
11614
|
+
const file = import_node_path12.default.join(
|
|
11582
11615
|
this.projectsRoot,
|
|
11583
11616
|
cwdToHashDir(args.cwd),
|
|
11584
11617
|
`${args.toolSessionId}.jsonl`
|
|
@@ -11615,7 +11648,7 @@ var init_claude_history = __esm({
|
|
|
11615
11648
|
// 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
|
|
11616
11649
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
11617
11650
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
11618
|
-
const dir =
|
|
11651
|
+
const dir = import_node_path12.default.join(
|
|
11619
11652
|
this.projectsRoot,
|
|
11620
11653
|
cwdToHashDir(cwd),
|
|
11621
11654
|
toolSessionId,
|
|
@@ -11623,7 +11656,7 @@ var init_claude_history = __esm({
|
|
|
11623
11656
|
);
|
|
11624
11657
|
let entries;
|
|
11625
11658
|
try {
|
|
11626
|
-
entries =
|
|
11659
|
+
entries = import_node_fs13.default.readdirSync(dir, { withFileTypes: true });
|
|
11627
11660
|
} catch (err) {
|
|
11628
11661
|
if (err.code === "ENOENT") return null;
|
|
11629
11662
|
return null;
|
|
@@ -11633,7 +11666,7 @@ var init_claude_history = __esm({
|
|
|
11633
11666
|
if (!e.isFile()) continue;
|
|
11634
11667
|
if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
|
|
11635
11668
|
const subagentId = e.name.slice("agent-".length, -".jsonl".length);
|
|
11636
|
-
const filePath =
|
|
11669
|
+
const filePath = import_node_path12.default.join(dir, e.name);
|
|
11637
11670
|
const lines = readJsonlLines(filePath);
|
|
11638
11671
|
let firstText = "";
|
|
11639
11672
|
let messageCount = 0;
|
|
@@ -11650,7 +11683,7 @@ var init_claude_history = __esm({
|
|
|
11650
11683
|
return out;
|
|
11651
11684
|
}
|
|
11652
11685
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
11653
|
-
const file =
|
|
11686
|
+
const file = import_node_path12.default.join(
|
|
11654
11687
|
this.projectsRoot,
|
|
11655
11688
|
cwdToHashDir(cwd),
|
|
11656
11689
|
`${toolSessionId}.jsonl`
|
|
@@ -11685,7 +11718,7 @@ var init_claude_history = __esm({
|
|
|
11685
11718
|
}
|
|
11686
11719
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
11687
11720
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
11688
|
-
const file =
|
|
11721
|
+
const file = import_node_path12.default.join(
|
|
11689
11722
|
this.projectsRoot,
|
|
11690
11723
|
cwdToHashDir(cwd),
|
|
11691
11724
|
toolSessionId,
|
|
@@ -11694,7 +11727,7 @@ var init_claude_history = __esm({
|
|
|
11694
11727
|
);
|
|
11695
11728
|
let exists = false;
|
|
11696
11729
|
try {
|
|
11697
|
-
exists =
|
|
11730
|
+
exists = import_node_fs13.default.statSync(file).isFile();
|
|
11698
11731
|
} catch {
|
|
11699
11732
|
return null;
|
|
11700
11733
|
}
|
|
@@ -11713,7 +11746,7 @@ var init_claude_history = __esm({
|
|
|
11713
11746
|
* "那一刻每个 tracked 文件对应的 backup 文件名"
|
|
11714
11747
|
*/
|
|
11715
11748
|
readFileHistorySnapshots(args) {
|
|
11716
|
-
const file =
|
|
11749
|
+
const file = import_node_path12.default.join(
|
|
11717
11750
|
this.projectsRoot,
|
|
11718
11751
|
cwdToHashDir(args.cwd),
|
|
11719
11752
|
`${args.toolSessionId}.jsonl`
|
|
@@ -11758,7 +11791,7 @@ var init_claude_history = __esm({
|
|
|
11758
11791
|
for (const [anchorId, target] of snapshots) {
|
|
11759
11792
|
let hasAny = false;
|
|
11760
11793
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
11761
|
-
const absPath =
|
|
11794
|
+
const absPath = import_node_path12.default.isAbsolute(rawPath) ? rawPath : import_node_path12.default.join(args.cwd, rawPath);
|
|
11762
11795
|
const backupContent = readBackupContent(
|
|
11763
11796
|
this.fileHistoryRoot,
|
|
11764
11797
|
args.toolSessionId,
|
|
@@ -11798,7 +11831,7 @@ var init_claude_history = __esm({
|
|
|
11798
11831
|
let totalInsertions = 0;
|
|
11799
11832
|
let totalDeletions = 0;
|
|
11800
11833
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
11801
|
-
const absPath =
|
|
11834
|
+
const absPath = import_node_path12.default.isAbsolute(rawPath) ? rawPath : import_node_path12.default.join(args.cwd, rawPath);
|
|
11802
11835
|
const backupContent = readBackupContent(
|
|
11803
11836
|
this.fileHistoryRoot,
|
|
11804
11837
|
args.toolSessionId,
|
|
@@ -11845,7 +11878,7 @@ var init_claude_history = __esm({
|
|
|
11845
11878
|
};
|
|
11846
11879
|
}
|
|
11847
11880
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
11848
|
-
const file =
|
|
11881
|
+
const file = import_node_path12.default.join(
|
|
11849
11882
|
this.projectsRoot,
|
|
11850
11883
|
cwdToHashDir(cwd),
|
|
11851
11884
|
`${toolSessionId}.jsonl`
|
|
@@ -11870,13 +11903,13 @@ var init_claude_history = __esm({
|
|
|
11870
11903
|
function probeViaWhich() {
|
|
11871
11904
|
try {
|
|
11872
11905
|
const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
11873
|
-
if (out &&
|
|
11906
|
+
if (out && import_node_fs14.default.existsSync(out)) return out;
|
|
11874
11907
|
} catch {
|
|
11875
11908
|
}
|
|
11876
11909
|
return null;
|
|
11877
11910
|
}
|
|
11878
11911
|
async function probeClaude(env = process.env) {
|
|
11879
|
-
if (env.CLAUDE_BIN &&
|
|
11912
|
+
if (env.CLAUDE_BIN && import_node_fs14.default.existsSync(env.CLAUDE_BIN)) {
|
|
11880
11913
|
return { available: true, path: env.CLAUDE_BIN };
|
|
11881
11914
|
}
|
|
11882
11915
|
const w2 = probeViaWhich();
|
|
@@ -12211,10 +12244,10 @@ function parseAttachment(obj) {
|
|
|
12211
12244
|
const memories = raw.map((m2) => {
|
|
12212
12245
|
if (!m2 || typeof m2 !== "object") return null;
|
|
12213
12246
|
const rec3 = m2;
|
|
12214
|
-
const
|
|
12247
|
+
const path66 = typeof rec3.path === "string" ? rec3.path : null;
|
|
12215
12248
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
12216
|
-
if (!
|
|
12217
|
-
const out = { path:
|
|
12249
|
+
if (!path66 || content == null) return null;
|
|
12250
|
+
const out = { path: path66, content };
|
|
12218
12251
|
if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
|
|
12219
12252
|
return out;
|
|
12220
12253
|
}).filter((m2) => m2 !== null);
|
|
@@ -12318,13 +12351,13 @@ function encodeClaudeStdin(text) {
|
|
|
12318
12351
|
};
|
|
12319
12352
|
return JSON.stringify(frame) + "\n";
|
|
12320
12353
|
}
|
|
12321
|
-
var import_node_child_process, import_node_child_process2,
|
|
12354
|
+
var import_node_child_process, import_node_child_process2, import_node_fs14, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
|
|
12322
12355
|
var init_claude = __esm({
|
|
12323
12356
|
"src/tools/claude.ts"() {
|
|
12324
12357
|
"use strict";
|
|
12325
12358
|
import_node_child_process = require("child_process");
|
|
12326
12359
|
import_node_child_process2 = require("child_process");
|
|
12327
|
-
|
|
12360
|
+
import_node_fs14 = __toESM(require("fs"), 1);
|
|
12328
12361
|
init_protocol();
|
|
12329
12362
|
init_claude_history();
|
|
12330
12363
|
init_tool_result_extra();
|
|
@@ -33178,8 +33211,8 @@ var require_utils = __commonJS({
|
|
|
33178
33211
|
var result = transform[inputType][outputType](input);
|
|
33179
33212
|
return result;
|
|
33180
33213
|
};
|
|
33181
|
-
exports2.resolve = function(
|
|
33182
|
-
var parts =
|
|
33214
|
+
exports2.resolve = function(path66) {
|
|
33215
|
+
var parts = path66.split("/");
|
|
33183
33216
|
var result = [];
|
|
33184
33217
|
for (var index = 0; index < parts.length; index++) {
|
|
33185
33218
|
var part = parts[index];
|
|
@@ -39032,18 +39065,18 @@ var require_object = __commonJS({
|
|
|
39032
39065
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
39033
39066
|
this.files[name] = object;
|
|
39034
39067
|
};
|
|
39035
|
-
var parentFolder = function(
|
|
39036
|
-
if (
|
|
39037
|
-
|
|
39068
|
+
var parentFolder = function(path66) {
|
|
39069
|
+
if (path66.slice(-1) === "/") {
|
|
39070
|
+
path66 = path66.substring(0, path66.length - 1);
|
|
39038
39071
|
}
|
|
39039
|
-
var lastSlash =
|
|
39040
|
-
return lastSlash > 0 ?
|
|
39072
|
+
var lastSlash = path66.lastIndexOf("/");
|
|
39073
|
+
return lastSlash > 0 ? path66.substring(0, lastSlash) : "";
|
|
39041
39074
|
};
|
|
39042
|
-
var forceTrailingSlash = function(
|
|
39043
|
-
if (
|
|
39044
|
-
|
|
39075
|
+
var forceTrailingSlash = function(path66) {
|
|
39076
|
+
if (path66.slice(-1) !== "/") {
|
|
39077
|
+
path66 += "/";
|
|
39045
39078
|
}
|
|
39046
|
-
return
|
|
39079
|
+
return path66;
|
|
39047
39080
|
};
|
|
39048
39081
|
var folderAdd = function(name, createFolders) {
|
|
39049
39082
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -40045,7 +40078,7 @@ var require_lib3 = __commonJS({
|
|
|
40045
40078
|
// src/run-case/recorder.ts
|
|
40046
40079
|
function startRunCaseRecorder(opts) {
|
|
40047
40080
|
const now = opts.now ?? Date.now;
|
|
40048
|
-
const dir =
|
|
40081
|
+
const dir = import_node_path54.default.dirname(opts.recordPath);
|
|
40049
40082
|
let stream = null;
|
|
40050
40083
|
let closing = false;
|
|
40051
40084
|
let closedSettled = false;
|
|
@@ -40059,8 +40092,8 @@ function startRunCaseRecorder(opts) {
|
|
|
40059
40092
|
});
|
|
40060
40093
|
const ensureStream = () => {
|
|
40061
40094
|
if (stream) return stream;
|
|
40062
|
-
|
|
40063
|
-
stream =
|
|
40095
|
+
import_node_fs42.default.mkdirSync(dir, { recursive: true });
|
|
40096
|
+
stream = import_node_fs42.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
40064
40097
|
stream.on("close", () => closedResolve());
|
|
40065
40098
|
return stream;
|
|
40066
40099
|
};
|
|
@@ -40085,12 +40118,12 @@ function startRunCaseRecorder(opts) {
|
|
|
40085
40118
|
};
|
|
40086
40119
|
return { tap, close, closed };
|
|
40087
40120
|
}
|
|
40088
|
-
var
|
|
40121
|
+
var import_node_fs42, import_node_path54;
|
|
40089
40122
|
var init_recorder = __esm({
|
|
40090
40123
|
"src/run-case/recorder.ts"() {
|
|
40091
40124
|
"use strict";
|
|
40092
|
-
|
|
40093
|
-
|
|
40125
|
+
import_node_fs42 = __toESM(require("fs"), 1);
|
|
40126
|
+
import_node_path54 = __toESM(require("path"), 1);
|
|
40094
40127
|
}
|
|
40095
40128
|
});
|
|
40096
40129
|
|
|
@@ -40133,7 +40166,7 @@ var init_wire = __esm({
|
|
|
40133
40166
|
// src/run-case/controller.ts
|
|
40134
40167
|
async function runController(opts) {
|
|
40135
40168
|
const now = opts.now ?? Date.now;
|
|
40136
|
-
const cwd = opts.cwd ?? (0,
|
|
40169
|
+
const cwd = opts.cwd ?? (0, import_node_fs43.mkdtempSync)(import_node_path55.default.join(import_node_os21.default.tmpdir(), "clawd-runcase-"));
|
|
40137
40170
|
const ownsCwd = opts.cwd === void 0;
|
|
40138
40171
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
40139
40172
|
const spawnCtx = { cwd };
|
|
@@ -40294,19 +40327,19 @@ async function runController(opts) {
|
|
|
40294
40327
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
40295
40328
|
if (ownsCwd) {
|
|
40296
40329
|
try {
|
|
40297
|
-
(0,
|
|
40330
|
+
(0, import_node_fs43.rmSync)(cwd, { recursive: true, force: true });
|
|
40298
40331
|
} catch {
|
|
40299
40332
|
}
|
|
40300
40333
|
}
|
|
40301
40334
|
return exitCode ?? 0;
|
|
40302
40335
|
}
|
|
40303
|
-
var
|
|
40336
|
+
var import_node_fs43, import_node_os21, import_node_path55;
|
|
40304
40337
|
var init_controller = __esm({
|
|
40305
40338
|
"src/run-case/controller.ts"() {
|
|
40306
40339
|
"use strict";
|
|
40307
|
-
|
|
40340
|
+
import_node_fs43 = require("fs");
|
|
40308
40341
|
import_node_os21 = __toESM(require("os"), 1);
|
|
40309
|
-
|
|
40342
|
+
import_node_path55 = __toESM(require("path"), 1);
|
|
40310
40343
|
init_claude();
|
|
40311
40344
|
init_stdout_splitter();
|
|
40312
40345
|
init_permission_stdio();
|
|
@@ -40568,8 +40601,8 @@ Env (advanced):
|
|
|
40568
40601
|
`;
|
|
40569
40602
|
|
|
40570
40603
|
// src/index.ts
|
|
40571
|
-
var
|
|
40572
|
-
var
|
|
40604
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
40605
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
40573
40606
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
40574
40607
|
|
|
40575
40608
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
@@ -40620,7 +40653,7 @@ function v4(options, buf, offset) {
|
|
|
40620
40653
|
var v4_default = v4;
|
|
40621
40654
|
|
|
40622
40655
|
// src/index.ts
|
|
40623
|
-
var
|
|
40656
|
+
var import_node_url4 = require("url");
|
|
40624
40657
|
|
|
40625
40658
|
// src/logger.ts
|
|
40626
40659
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
@@ -45229,14 +45262,6 @@ var DEFAULT_PERSONAS = [
|
|
|
45229
45262
|
public: false,
|
|
45230
45263
|
sandboxProfile: DEFAULT_BYPASS_PROFILE
|
|
45231
45264
|
},
|
|
45232
|
-
{
|
|
45233
|
-
personaId: "persona-builder",
|
|
45234
|
-
label: "\u4EBA\u683C\u8BBE\u8BA1\u5E08",
|
|
45235
|
-
model: "opus",
|
|
45236
|
-
iconKey: "reading",
|
|
45237
|
-
public: false,
|
|
45238
|
-
sandboxProfile: DEFAULT_BYPASS_PROFILE
|
|
45239
|
-
},
|
|
45240
45265
|
{
|
|
45241
45266
|
personaId: "persona-bug-fixer",
|
|
45242
45267
|
label: "Bug \u4FEE\u590D\u5E08",
|
|
@@ -45572,12 +45597,187 @@ function tryLoadViewerAssets(logger) {
|
|
|
45572
45597
|
return null;
|
|
45573
45598
|
}
|
|
45574
45599
|
|
|
45600
|
+
// src/share-ui/load.ts
|
|
45601
|
+
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
45602
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
45603
|
+
var import_node_url3 = require("url");
|
|
45604
|
+
|
|
45605
|
+
// src/share-ui/asset-loader.ts
|
|
45606
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
45607
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
45608
|
+
function createShareUiAssetLoader(opts) {
|
|
45609
|
+
let indexHtml;
|
|
45610
|
+
try {
|
|
45611
|
+
indexHtml = import_node_fs10.default.readFileSync(opts.indexHtmlPath, "utf8");
|
|
45612
|
+
} catch (err) {
|
|
45613
|
+
throw new Error(`share-ui index.html not found at ${opts.indexHtmlPath}: ${err.message}`);
|
|
45614
|
+
}
|
|
45615
|
+
const assetsDir = import_node_path9.default.resolve(opts.assetsDir);
|
|
45616
|
+
return {
|
|
45617
|
+
renderIndexHtml() {
|
|
45618
|
+
return indexHtml;
|
|
45619
|
+
},
|
|
45620
|
+
resolveAssetPath(rel) {
|
|
45621
|
+
const resolved = import_node_path9.default.resolve(assetsDir, rel);
|
|
45622
|
+
if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path9.default.sep)) return null;
|
|
45623
|
+
try {
|
|
45624
|
+
if (import_node_fs10.default.statSync(resolved).isFile()) return resolved;
|
|
45625
|
+
} catch {
|
|
45626
|
+
}
|
|
45627
|
+
return null;
|
|
45628
|
+
}
|
|
45629
|
+
};
|
|
45630
|
+
}
|
|
45631
|
+
|
|
45632
|
+
// src/share-ui/load.ts
|
|
45633
|
+
var import_meta3 = {};
|
|
45634
|
+
function tryLoadShareUi(logger) {
|
|
45635
|
+
const candidates = [];
|
|
45636
|
+
try {
|
|
45637
|
+
const here = import_node_path10.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url));
|
|
45638
|
+
candidates.push(here);
|
|
45639
|
+
candidates.push(import_node_path10.default.resolve(here, ".."));
|
|
45640
|
+
candidates.push(import_node_path10.default.resolve(here, "..", "..", "dist"));
|
|
45641
|
+
} catch {
|
|
45642
|
+
}
|
|
45643
|
+
if (process.argv[1]) {
|
|
45644
|
+
candidates.push(import_node_path10.default.dirname(process.argv[1]));
|
|
45645
|
+
}
|
|
45646
|
+
for (const root of candidates) {
|
|
45647
|
+
const shareUiDir = import_node_path10.default.join(root, "share-ui");
|
|
45648
|
+
const indexHtmlPath = import_node_path10.default.join(shareUiDir, "guest.html");
|
|
45649
|
+
const assetsDir = import_node_path10.default.join(shareUiDir, "assets");
|
|
45650
|
+
try {
|
|
45651
|
+
if (import_node_fs11.default.statSync(indexHtmlPath).isFile() && import_node_fs11.default.statSync(assetsDir).isDirectory()) {
|
|
45652
|
+
logger?.info("share-ui.assets-root.resolved", { root: shareUiDir });
|
|
45653
|
+
return createShareUiAssetLoader({ indexHtmlPath, assetsDir });
|
|
45654
|
+
}
|
|
45655
|
+
} catch {
|
|
45656
|
+
}
|
|
45657
|
+
}
|
|
45658
|
+
logger?.warn("share-ui.assets-not-found", {
|
|
45659
|
+
candidates,
|
|
45660
|
+
hint: "run `pnpm -F @clawos/ext-clawd-ui build && pnpm -F @clawos-dev/clawd build`"
|
|
45661
|
+
});
|
|
45662
|
+
return null;
|
|
45663
|
+
}
|
|
45664
|
+
|
|
45665
|
+
// src/visitor/visitor-token.ts
|
|
45666
|
+
var import_node_crypto4 = __toESM(require("crypto"), 1);
|
|
45667
|
+
|
|
45668
|
+
// ../protocol/src/index.ts
|
|
45669
|
+
init_runtime();
|
|
45670
|
+
|
|
45671
|
+
// src/visitor/visitor-token.ts
|
|
45672
|
+
function hmac(secret, body) {
|
|
45673
|
+
return import_node_crypto4.default.createHmac("sha256", secret).update(body).digest("base64url");
|
|
45674
|
+
}
|
|
45675
|
+
function signVisitorToken(secret, payload) {
|
|
45676
|
+
const body = Buffer.from(JSON.stringify(payload)).toString("base64url");
|
|
45677
|
+
return `${body}.${hmac(secret, body)}`;
|
|
45678
|
+
}
|
|
45679
|
+
function verifyVisitorToken(secret, token, now) {
|
|
45680
|
+
const dot = token.indexOf(".");
|
|
45681
|
+
if (dot <= 0) return { ok: false, reason: "BAD_FORMAT" };
|
|
45682
|
+
const body = token.slice(0, dot);
|
|
45683
|
+
const sig = token.slice(dot + 1);
|
|
45684
|
+
const expected = hmac(secret, body);
|
|
45685
|
+
if (sig.length !== expected.length) return { ok: false, reason: "BAD_SIGNATURE" };
|
|
45686
|
+
if (!import_node_crypto4.default.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
|
|
45687
|
+
return { ok: false, reason: "BAD_SIGNATURE" };
|
|
45688
|
+
}
|
|
45689
|
+
let payload;
|
|
45690
|
+
try {
|
|
45691
|
+
const parsed = VisitorTokenPayloadSchema.safeParse(
|
|
45692
|
+
JSON.parse(Buffer.from(body, "base64url").toString("utf8"))
|
|
45693
|
+
);
|
|
45694
|
+
if (!parsed.success) return { ok: false, reason: "BAD_FORMAT" };
|
|
45695
|
+
payload = parsed.data;
|
|
45696
|
+
} catch {
|
|
45697
|
+
return { ok: false, reason: "BAD_FORMAT" };
|
|
45698
|
+
}
|
|
45699
|
+
if (now >= payload.exp) return { ok: false, reason: "EXPIRED" };
|
|
45700
|
+
return { ok: true, payload };
|
|
45701
|
+
}
|
|
45702
|
+
|
|
45703
|
+
// src/visitor/visitor-login.ts
|
|
45704
|
+
function buildVisitorLogin(deps) {
|
|
45705
|
+
return async function exchangeVisitorToken(args) {
|
|
45706
|
+
let id;
|
|
45707
|
+
try {
|
|
45708
|
+
id = await deps.fetchUserInfo(args.ttcToken);
|
|
45709
|
+
} catch {
|
|
45710
|
+
return { ok: false, reason: "BAD_TTC_TOKEN" };
|
|
45711
|
+
}
|
|
45712
|
+
deps.visitorStore.upsert({
|
|
45713
|
+
visitorId: id.ownerId,
|
|
45714
|
+
displayName: id.displayName,
|
|
45715
|
+
provider: id.provider,
|
|
45716
|
+
...id.avatarUrl ? { avatarUrl: id.avatarUrl } : {},
|
|
45717
|
+
now: deps.now()
|
|
45718
|
+
});
|
|
45719
|
+
const iat = Math.floor(deps.now() / 1e3);
|
|
45720
|
+
const visitorToken = signVisitorToken(deps.getSecret(), {
|
|
45721
|
+
v: 1,
|
|
45722
|
+
visitorId: id.ownerId,
|
|
45723
|
+
displayName: id.displayName,
|
|
45724
|
+
provider: id.provider,
|
|
45725
|
+
iat,
|
|
45726
|
+
exp: iat + deps.ttlSeconds
|
|
45727
|
+
});
|
|
45728
|
+
return { ok: true, visitorToken };
|
|
45729
|
+
};
|
|
45730
|
+
}
|
|
45731
|
+
|
|
45732
|
+
// src/visitor/visitor-store.ts
|
|
45733
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
45734
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
45735
|
+
function createVisitorStore(opts) {
|
|
45736
|
+
const file = import_node_path11.default.join(opts.dir, "visitors.json");
|
|
45737
|
+
const read = () => {
|
|
45738
|
+
try {
|
|
45739
|
+
return JSON.parse(import_node_fs12.default.readFileSync(file, "utf8"));
|
|
45740
|
+
} catch {
|
|
45741
|
+
return [];
|
|
45742
|
+
}
|
|
45743
|
+
};
|
|
45744
|
+
const write = (rows) => {
|
|
45745
|
+
import_node_fs12.default.mkdirSync(opts.dir, { recursive: true });
|
|
45746
|
+
import_node_fs12.default.writeFileSync(file, JSON.stringify(rows, null, 2));
|
|
45747
|
+
};
|
|
45748
|
+
return {
|
|
45749
|
+
upsert(r) {
|
|
45750
|
+
const rows = read();
|
|
45751
|
+
const ex = rows.find((x) => x.visitorId === r.visitorId);
|
|
45752
|
+
if (ex) {
|
|
45753
|
+
ex.displayName = r.displayName;
|
|
45754
|
+
ex.provider = r.provider;
|
|
45755
|
+
ex.lastSeen = r.now;
|
|
45756
|
+
if (r.avatarUrl) ex.avatarUrl = r.avatarUrl;
|
|
45757
|
+
} else {
|
|
45758
|
+
rows.push({
|
|
45759
|
+
visitorId: r.visitorId,
|
|
45760
|
+
displayName: r.displayName,
|
|
45761
|
+
provider: r.provider,
|
|
45762
|
+
...r.avatarUrl ? { avatarUrl: r.avatarUrl } : {},
|
|
45763
|
+
firstSeen: r.now,
|
|
45764
|
+
lastSeen: r.now
|
|
45765
|
+
});
|
|
45766
|
+
}
|
|
45767
|
+
write(rows);
|
|
45768
|
+
},
|
|
45769
|
+
list() {
|
|
45770
|
+
return read();
|
|
45771
|
+
}
|
|
45772
|
+
};
|
|
45773
|
+
}
|
|
45774
|
+
|
|
45575
45775
|
// src/index.ts
|
|
45576
45776
|
init_claude();
|
|
45577
45777
|
|
|
45578
45778
|
// src/tools/codex.ts
|
|
45579
45779
|
var import_node_child_process4 = require("child_process");
|
|
45580
|
-
var
|
|
45780
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
45581
45781
|
|
|
45582
45782
|
// src/tools/codex-session.ts
|
|
45583
45783
|
var import_node_child_process3 = require("child_process");
|
|
@@ -45825,8 +46025,8 @@ function turnStartInput(text) {
|
|
|
45825
46025
|
const items = [];
|
|
45826
46026
|
let leftover = text;
|
|
45827
46027
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
45828
|
-
const [marker, name,
|
|
45829
|
-
items.push({ type: "skill", name, path:
|
|
46028
|
+
const [marker, name, path66] = m2;
|
|
46029
|
+
items.push({ type: "skill", name, path: path66 });
|
|
45830
46030
|
leftover = leftover.replace(marker, "");
|
|
45831
46031
|
}
|
|
45832
46032
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -46010,10 +46210,10 @@ function sanitizeCodexModel(model) {
|
|
|
46010
46210
|
return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
|
|
46011
46211
|
}
|
|
46012
46212
|
async function probeCodex(env = process.env) {
|
|
46013
|
-
if (env.CODEX_BIN &&
|
|
46213
|
+
if (env.CODEX_BIN && import_node_fs15.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
|
|
46014
46214
|
try {
|
|
46015
46215
|
const out = (0, import_node_child_process4.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
|
|
46016
|
-
if (out &&
|
|
46216
|
+
if (out && import_node_fs15.default.existsSync(out)) return { available: true, path: out };
|
|
46017
46217
|
} catch {
|
|
46018
46218
|
}
|
|
46019
46219
|
return { available: false };
|
|
@@ -46058,9 +46258,9 @@ var CodexAdapter = class {
|
|
|
46058
46258
|
};
|
|
46059
46259
|
|
|
46060
46260
|
// src/tools/claude-tui.ts
|
|
46061
|
-
var
|
|
46261
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
46062
46262
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
46063
|
-
var
|
|
46263
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
46064
46264
|
var import_headless = __toESM(require_xterm_headless(), 1);
|
|
46065
46265
|
|
|
46066
46266
|
// ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
|
|
@@ -47194,9 +47394,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
47194
47394
|
function jsonlExistsForCtx(ctx) {
|
|
47195
47395
|
if (!ctx.toolSessionId) return false;
|
|
47196
47396
|
const home = import_node_os6.default.homedir();
|
|
47197
|
-
const file =
|
|
47397
|
+
const file = import_node_path13.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
|
|
47198
47398
|
try {
|
|
47199
|
-
return
|
|
47399
|
+
return import_node_fs16.default.statSync(file).isFile();
|
|
47200
47400
|
} catch {
|
|
47201
47401
|
return false;
|
|
47202
47402
|
}
|
|
@@ -47265,10 +47465,10 @@ var PersonaDispatchManager = class {
|
|
|
47265
47465
|
};
|
|
47266
47466
|
|
|
47267
47467
|
// src/dispatch/mcp-config.ts
|
|
47268
|
-
var
|
|
47269
|
-
var
|
|
47468
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
47469
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
47270
47470
|
function dispatchMcpConfigPath(dataDir) {
|
|
47271
|
-
return
|
|
47471
|
+
return import_node_path14.default.join(dataDir, "dispatch.mcp.json");
|
|
47272
47472
|
}
|
|
47273
47473
|
function writeDispatchMcpConfig(args) {
|
|
47274
47474
|
const cfgPath = dispatchMcpConfigPath(args.dataDir);
|
|
@@ -47283,16 +47483,16 @@ function writeDispatchMcpConfig(args) {
|
|
|
47283
47483
|
}
|
|
47284
47484
|
}
|
|
47285
47485
|
};
|
|
47286
|
-
|
|
47287
|
-
|
|
47486
|
+
import_node_fs17.default.mkdirSync(args.dataDir, { recursive: true });
|
|
47487
|
+
import_node_fs17.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
47288
47488
|
return cfgPath;
|
|
47289
47489
|
}
|
|
47290
47490
|
|
|
47291
47491
|
// src/ticket/mcp-config.ts
|
|
47292
|
-
var
|
|
47293
|
-
var
|
|
47492
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
47493
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
47294
47494
|
function ticketMcpConfigPath(dataDir) {
|
|
47295
|
-
return
|
|
47495
|
+
return import_node_path15.default.join(dataDir, "ticket.mcp.json");
|
|
47296
47496
|
}
|
|
47297
47497
|
function writeTicketMcpConfig(args) {
|
|
47298
47498
|
const cfgPath = ticketMcpConfigPath(args.dataDir);
|
|
@@ -47313,16 +47513,16 @@ function writeTicketMcpConfig(args) {
|
|
|
47313
47513
|
}
|
|
47314
47514
|
}
|
|
47315
47515
|
};
|
|
47316
|
-
|
|
47317
|
-
|
|
47516
|
+
import_node_fs18.default.mkdirSync(args.dataDir, { recursive: true });
|
|
47517
|
+
import_node_fs18.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
47318
47518
|
return cfgPath;
|
|
47319
47519
|
}
|
|
47320
47520
|
|
|
47321
47521
|
// src/shift/mcp-config.ts
|
|
47322
|
-
var
|
|
47323
|
-
var
|
|
47522
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
47523
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
47324
47524
|
function shiftMcpConfigPath(dataDir) {
|
|
47325
|
-
return
|
|
47525
|
+
return import_node_path16.default.join(dataDir, "shift.mcp.json");
|
|
47326
47526
|
}
|
|
47327
47527
|
async function writeShiftMcpConfig(args) {
|
|
47328
47528
|
const cfgPath = shiftMcpConfigPath(args.dataDir);
|
|
@@ -47337,21 +47537,21 @@ async function writeShiftMcpConfig(args) {
|
|
|
47337
47537
|
}
|
|
47338
47538
|
}
|
|
47339
47539
|
};
|
|
47340
|
-
await
|
|
47341
|
-
await
|
|
47540
|
+
await import_node_fs19.default.promises.mkdir(args.dataDir, { recursive: true });
|
|
47541
|
+
await import_node_fs19.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
47342
47542
|
return cfgPath;
|
|
47343
47543
|
}
|
|
47344
47544
|
|
|
47345
47545
|
// src/shift/store.ts
|
|
47346
47546
|
var import_promises = __toESM(require("fs/promises"), 1);
|
|
47347
|
-
var
|
|
47348
|
-
var
|
|
47547
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
47548
|
+
var import_node_crypto5 = require("crypto");
|
|
47349
47549
|
|
|
47350
47550
|
// src/shift/constants.ts
|
|
47351
47551
|
var MAX_RUNS_PER_SHIFT = 30;
|
|
47352
47552
|
var DEFAULT_TIMEOUT_MS = 30 * 6e4;
|
|
47353
47553
|
var CONSECUTIVE_ERROR_THRESHOLD = 5;
|
|
47354
|
-
var TICK_INTERVAL_MS =
|
|
47554
|
+
var TICK_INTERVAL_MS = 1e3;
|
|
47355
47555
|
var STORE_FLUSH_DEBOUNCE_MS = 500;
|
|
47356
47556
|
var CLOCK_JUMP_THRESHOLD_MS = 5 * 6e4;
|
|
47357
47557
|
|
|
@@ -47413,7 +47613,7 @@ function createShiftStore(deps) {
|
|
|
47413
47613
|
flushTimer = null;
|
|
47414
47614
|
}
|
|
47415
47615
|
const content = { version: 1, shifts };
|
|
47416
|
-
await import_promises.default.mkdir(
|
|
47616
|
+
await import_promises.default.mkdir(import_node_path17.default.dirname(deps.filePath), { recursive: true });
|
|
47417
47617
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
47418
47618
|
await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
47419
47619
|
await import_promises.default.rename(tmp, deps.filePath);
|
|
@@ -47441,7 +47641,7 @@ function createShiftStore(deps) {
|
|
|
47441
47641
|
const nextRunAtMs = computeNextRunAtMs(input.schedule, now) ?? void 0;
|
|
47442
47642
|
const shift = {
|
|
47443
47643
|
...input,
|
|
47444
|
-
id: (0,
|
|
47644
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
47445
47645
|
createdAtMs: now,
|
|
47446
47646
|
updatedAtMs: now,
|
|
47447
47647
|
state: { nextRunAtMs },
|
|
@@ -48184,13 +48384,13 @@ function mapSkillsListResponse(res) {
|
|
|
48184
48384
|
const r = s ?? {};
|
|
48185
48385
|
const name = str3(r.name);
|
|
48186
48386
|
if (!name) continue;
|
|
48187
|
-
const
|
|
48387
|
+
const path66 = str3(r.path);
|
|
48188
48388
|
const description = str3(r.description);
|
|
48189
48389
|
const isPlugin = name.includes(":");
|
|
48190
48390
|
out.push({
|
|
48191
48391
|
name,
|
|
48192
48392
|
source: isPlugin ? "plugin" : "project",
|
|
48193
|
-
...
|
|
48393
|
+
...path66 ? { path: path66 } : {},
|
|
48194
48394
|
...description ? { description } : {},
|
|
48195
48395
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
48196
48396
|
});
|
|
@@ -48229,23 +48429,23 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
48229
48429
|
}
|
|
48230
48430
|
|
|
48231
48431
|
// src/workspace/browser.ts
|
|
48232
|
-
var
|
|
48432
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
48233
48433
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
48234
|
-
var
|
|
48434
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
48235
48435
|
init_protocol();
|
|
48236
48436
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
48237
48437
|
function resolveInsideCwd(cwd, subpath) {
|
|
48238
|
-
const absCwd =
|
|
48239
|
-
const joined =
|
|
48240
|
-
const rel =
|
|
48241
|
-
if (rel.startsWith("..") ||
|
|
48438
|
+
const absCwd = import_node_path18.default.resolve(cwd);
|
|
48439
|
+
const joined = import_node_path18.default.resolve(absCwd, subpath ?? ".");
|
|
48440
|
+
const rel = import_node_path18.default.relative(absCwd, joined);
|
|
48441
|
+
if (rel.startsWith("..") || import_node_path18.default.isAbsolute(rel)) {
|
|
48242
48442
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
48243
48443
|
}
|
|
48244
48444
|
return joined;
|
|
48245
48445
|
}
|
|
48246
48446
|
function ensureCwd(cwd) {
|
|
48247
48447
|
try {
|
|
48248
|
-
const stat =
|
|
48448
|
+
const stat = import_node_fs20.default.statSync(cwd);
|
|
48249
48449
|
if (!stat.isDirectory()) {
|
|
48250
48450
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
48251
48451
|
}
|
|
@@ -48259,7 +48459,7 @@ var WorkspaceBrowser = class {
|
|
|
48259
48459
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os7.default.homedir();
|
|
48260
48460
|
ensureCwd(cwd);
|
|
48261
48461
|
const full = resolveInsideCwd(cwd, args.path);
|
|
48262
|
-
const dirents =
|
|
48462
|
+
const dirents = import_node_fs20.default.readdirSync(full, { withFileTypes: true });
|
|
48263
48463
|
const entries = [];
|
|
48264
48464
|
for (const d of dirents) {
|
|
48265
48465
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -48269,7 +48469,7 @@ var WorkspaceBrowser = class {
|
|
|
48269
48469
|
mtime: ""
|
|
48270
48470
|
};
|
|
48271
48471
|
try {
|
|
48272
|
-
const st =
|
|
48472
|
+
const st = import_node_fs20.default.statSync(import_node_path18.default.join(full, d.name));
|
|
48273
48473
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
48274
48474
|
if (d.isFile()) entry.size = st.size;
|
|
48275
48475
|
} catch {
|
|
@@ -48285,14 +48485,14 @@ var WorkspaceBrowser = class {
|
|
|
48285
48485
|
read(args) {
|
|
48286
48486
|
ensureCwd(args.cwd);
|
|
48287
48487
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
48288
|
-
const st =
|
|
48488
|
+
const st = import_node_fs20.default.statSync(full);
|
|
48289
48489
|
if (!st.isFile()) {
|
|
48290
48490
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
48291
48491
|
}
|
|
48292
48492
|
if (st.size > MAX_FILE_BYTES) {
|
|
48293
48493
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
48294
48494
|
}
|
|
48295
|
-
const buf =
|
|
48495
|
+
const buf = import_node_fs20.default.readFileSync(full);
|
|
48296
48496
|
const isBinary = buf.includes(0);
|
|
48297
48497
|
if (isBinary) {
|
|
48298
48498
|
return {
|
|
@@ -48314,20 +48514,20 @@ var WorkspaceBrowser = class {
|
|
|
48314
48514
|
};
|
|
48315
48515
|
|
|
48316
48516
|
// src/skills/agents-scanner.ts
|
|
48317
|
-
var
|
|
48517
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
48318
48518
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
48319
|
-
var
|
|
48519
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
48320
48520
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
48321
48521
|
function isDirLikeSync2(p2) {
|
|
48322
48522
|
try {
|
|
48323
|
-
return
|
|
48523
|
+
return import_node_fs21.default.statSync(p2).isDirectory();
|
|
48324
48524
|
} catch {
|
|
48325
48525
|
return false;
|
|
48326
48526
|
}
|
|
48327
48527
|
}
|
|
48328
48528
|
function fileExistsSync(p2) {
|
|
48329
48529
|
try {
|
|
48330
|
-
return
|
|
48530
|
+
return import_node_fs21.default.statSync(p2).isFile();
|
|
48331
48531
|
} catch {
|
|
48332
48532
|
return false;
|
|
48333
48533
|
}
|
|
@@ -48335,7 +48535,7 @@ function fileExistsSync(p2) {
|
|
|
48335
48535
|
function parseAgentFile(filePath) {
|
|
48336
48536
|
let content;
|
|
48337
48537
|
try {
|
|
48338
|
-
content =
|
|
48538
|
+
content = import_node_fs21.default.readFileSync(filePath, "utf8");
|
|
48339
48539
|
} catch {
|
|
48340
48540
|
return {};
|
|
48341
48541
|
}
|
|
@@ -48348,16 +48548,16 @@ function parseAgentFile(filePath) {
|
|
|
48348
48548
|
function scanAgentsDir(dir, source, seen, out) {
|
|
48349
48549
|
let entries;
|
|
48350
48550
|
try {
|
|
48351
|
-
entries =
|
|
48551
|
+
entries = import_node_fs21.default.readdirSync(dir, { withFileTypes: true });
|
|
48352
48552
|
} catch {
|
|
48353
48553
|
return;
|
|
48354
48554
|
}
|
|
48355
48555
|
for (const ent of entries) {
|
|
48356
48556
|
if (!ent.name.endsWith(".md")) continue;
|
|
48357
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
48557
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path19.default.join(dir, ent.name)))) {
|
|
48358
48558
|
continue;
|
|
48359
48559
|
}
|
|
48360
|
-
const filePath =
|
|
48560
|
+
const filePath = import_node_path19.default.join(dir, ent.name);
|
|
48361
48561
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
48362
48562
|
if (seen.has(baseName)) continue;
|
|
48363
48563
|
seen.add(baseName);
|
|
@@ -48375,12 +48575,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
48375
48575
|
function walk2(dir, namespaces) {
|
|
48376
48576
|
let entries;
|
|
48377
48577
|
try {
|
|
48378
|
-
entries =
|
|
48578
|
+
entries = import_node_fs21.default.readdirSync(dir, { withFileTypes: true });
|
|
48379
48579
|
} catch {
|
|
48380
48580
|
return;
|
|
48381
48581
|
}
|
|
48382
48582
|
for (const ent of entries) {
|
|
48383
|
-
const childPath =
|
|
48583
|
+
const childPath = import_node_path19.default.join(dir, ent.name);
|
|
48384
48584
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
48385
48585
|
walk2(childPath, [...namespaces, ent.name]);
|
|
48386
48586
|
continue;
|
|
@@ -48405,13 +48605,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
48405
48605
|
walk2(root, []);
|
|
48406
48606
|
}
|
|
48407
48607
|
function readInstalledPlugins2(home) {
|
|
48408
|
-
const pluginsDir =
|
|
48409
|
-
const v2 =
|
|
48410
|
-
const v1 =
|
|
48608
|
+
const pluginsDir = import_node_path19.default.join(home, ".claude", "plugins");
|
|
48609
|
+
const v2 = import_node_path19.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
48610
|
+
const v1 = import_node_path19.default.join(pluginsDir, "installed_plugins.json");
|
|
48411
48611
|
let raw = null;
|
|
48412
48612
|
for (const candidate of [v2, v1]) {
|
|
48413
48613
|
try {
|
|
48414
|
-
raw =
|
|
48614
|
+
raw = import_node_fs21.default.readFileSync(candidate, "utf8");
|
|
48415
48615
|
break;
|
|
48416
48616
|
} catch {
|
|
48417
48617
|
}
|
|
@@ -48436,19 +48636,19 @@ function readInstalledPlugins2(home) {
|
|
|
48436
48636
|
return out;
|
|
48437
48637
|
}
|
|
48438
48638
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
48439
|
-
let cur =
|
|
48440
|
-
const fsRoot =
|
|
48639
|
+
let cur = import_node_path19.default.resolve(startCwd);
|
|
48640
|
+
const fsRoot = import_node_path19.default.parse(cur).root;
|
|
48441
48641
|
while (true) {
|
|
48442
|
-
scanAgentsDir(
|
|
48642
|
+
scanAgentsDir(import_node_path19.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
48443
48643
|
let hasGit = false;
|
|
48444
48644
|
try {
|
|
48445
|
-
hasGit =
|
|
48645
|
+
hasGit = import_node_fs21.default.existsSync(import_node_path19.default.join(cur, ".git"));
|
|
48446
48646
|
} catch {
|
|
48447
48647
|
}
|
|
48448
48648
|
if (hasGit) return;
|
|
48449
48649
|
if (cur === home) return;
|
|
48450
48650
|
if (cur === fsRoot) return;
|
|
48451
|
-
const parent =
|
|
48651
|
+
const parent = import_node_path19.default.dirname(cur);
|
|
48452
48652
|
if (parent === cur) return;
|
|
48453
48653
|
cur = parent;
|
|
48454
48654
|
}
|
|
@@ -48483,7 +48683,7 @@ var AgentsScanner = class {
|
|
|
48483
48683
|
}
|
|
48484
48684
|
const fsBlock = [];
|
|
48485
48685
|
scanAgentsDir(
|
|
48486
|
-
|
|
48686
|
+
import_node_path19.default.join(this.home, ".claude", "agents"),
|
|
48487
48687
|
"global",
|
|
48488
48688
|
seen,
|
|
48489
48689
|
fsBlock
|
|
@@ -48497,7 +48697,7 @@ var AgentsScanner = class {
|
|
|
48497
48697
|
...this.extraPluginRoots
|
|
48498
48698
|
];
|
|
48499
48699
|
for (const { name, root } of plugins) {
|
|
48500
|
-
const agentsRoot =
|
|
48700
|
+
const agentsRoot = import_node_path19.default.join(root, "agents");
|
|
48501
48701
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
48502
48702
|
}
|
|
48503
48703
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -48505,15 +48705,15 @@ var AgentsScanner = class {
|
|
|
48505
48705
|
};
|
|
48506
48706
|
|
|
48507
48707
|
// src/observer/session-observer.ts
|
|
48508
|
-
var
|
|
48708
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
48509
48709
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
48510
|
-
var
|
|
48710
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
48511
48711
|
init_claude_history();
|
|
48512
48712
|
|
|
48513
48713
|
// src/observer/subagent-meta-observer.ts
|
|
48514
|
-
var
|
|
48714
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
48515
48715
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
48516
|
-
var
|
|
48716
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
48517
48717
|
init_claude_history();
|
|
48518
48718
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
48519
48719
|
var SubagentMetaObserver = class {
|
|
@@ -48526,7 +48726,7 @@ var SubagentMetaObserver = class {
|
|
|
48526
48726
|
watches = /* @__PURE__ */ new Map();
|
|
48527
48727
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
48528
48728
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
48529
|
-
return
|
|
48729
|
+
return import_node_path20.default.join(
|
|
48530
48730
|
this.home,
|
|
48531
48731
|
".claude",
|
|
48532
48732
|
"projects",
|
|
@@ -48556,7 +48756,7 @@ var SubagentMetaObserver = class {
|
|
|
48556
48756
|
attachWatcher(w2) {
|
|
48557
48757
|
if (w2.watcher) return;
|
|
48558
48758
|
try {
|
|
48559
|
-
w2.watcher =
|
|
48759
|
+
w2.watcher = import_node_fs22.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
48560
48760
|
if (!name) return;
|
|
48561
48761
|
const m2 = META_RE.exec(String(name));
|
|
48562
48762
|
if (!m2) return;
|
|
@@ -48568,7 +48768,7 @@ var SubagentMetaObserver = class {
|
|
|
48568
48768
|
scan(w2) {
|
|
48569
48769
|
let entries;
|
|
48570
48770
|
try {
|
|
48571
|
-
entries =
|
|
48771
|
+
entries = import_node_fs22.default.readdirSync(w2.dirPath);
|
|
48572
48772
|
} catch {
|
|
48573
48773
|
return;
|
|
48574
48774
|
}
|
|
@@ -48582,10 +48782,10 @@ var SubagentMetaObserver = class {
|
|
|
48582
48782
|
if (!m2) return;
|
|
48583
48783
|
const agentId = m2[1];
|
|
48584
48784
|
if (w2.emitted.has(agentId)) return;
|
|
48585
|
-
const file =
|
|
48785
|
+
const file = import_node_path20.default.join(w2.dirPath, name);
|
|
48586
48786
|
let raw;
|
|
48587
48787
|
try {
|
|
48588
|
-
raw =
|
|
48788
|
+
raw = import_node_fs22.default.readFileSync(file, "utf8");
|
|
48589
48789
|
} catch {
|
|
48590
48790
|
return;
|
|
48591
48791
|
}
|
|
@@ -48642,14 +48842,14 @@ var SessionObserver = class {
|
|
|
48642
48842
|
metaObserver;
|
|
48643
48843
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
48644
48844
|
if (override) return override;
|
|
48645
|
-
return
|
|
48845
|
+
return import_node_path21.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
48646
48846
|
}
|
|
48647
48847
|
start(args) {
|
|
48648
48848
|
this.stop(args.sessionId);
|
|
48649
48849
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
48650
48850
|
let size = 0;
|
|
48651
48851
|
try {
|
|
48652
|
-
size =
|
|
48852
|
+
size = import_node_fs23.default.statSync(filePath).size;
|
|
48653
48853
|
} catch {
|
|
48654
48854
|
}
|
|
48655
48855
|
const w2 = {
|
|
@@ -48663,10 +48863,10 @@ var SessionObserver = class {
|
|
|
48663
48863
|
prevIsRejectSentinel: false
|
|
48664
48864
|
};
|
|
48665
48865
|
try {
|
|
48666
|
-
|
|
48866
|
+
import_node_fs23.default.mkdirSync(import_node_path21.default.dirname(filePath), { recursive: true });
|
|
48667
48867
|
} catch {
|
|
48668
48868
|
}
|
|
48669
|
-
w2.watcher =
|
|
48869
|
+
w2.watcher = import_node_fs23.default.watch(import_node_path21.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
48670
48870
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
48671
48871
|
this.poll(w2);
|
|
48672
48872
|
});
|
|
@@ -48689,7 +48889,7 @@ var SessionObserver = class {
|
|
|
48689
48889
|
// 异常静默吞,不阻塞 watcher 启动
|
|
48690
48890
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
48691
48891
|
try {
|
|
48692
|
-
const raw =
|
|
48892
|
+
const raw = import_node_fs23.default.readFileSync(w2.filePath, "utf8");
|
|
48693
48893
|
if (!raw) return;
|
|
48694
48894
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
48695
48895
|
if (allLines.length === 0) return;
|
|
@@ -48713,7 +48913,7 @@ var SessionObserver = class {
|
|
|
48713
48913
|
poll(w2) {
|
|
48714
48914
|
let size = 0;
|
|
48715
48915
|
try {
|
|
48716
|
-
size =
|
|
48916
|
+
size = import_node_fs23.default.statSync(w2.filePath).size;
|
|
48717
48917
|
} catch {
|
|
48718
48918
|
return;
|
|
48719
48919
|
}
|
|
@@ -48722,11 +48922,11 @@ var SessionObserver = class {
|
|
|
48722
48922
|
w2.buf = "";
|
|
48723
48923
|
}
|
|
48724
48924
|
if (size === w2.lastSize) return;
|
|
48725
|
-
const fd =
|
|
48925
|
+
const fd = import_node_fs23.default.openSync(w2.filePath, "r");
|
|
48726
48926
|
try {
|
|
48727
48927
|
const len = size - w2.lastSize;
|
|
48728
48928
|
const buf = Buffer.alloc(len);
|
|
48729
|
-
|
|
48929
|
+
import_node_fs23.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
48730
48930
|
w2.lastSize = size;
|
|
48731
48931
|
w2.buf += buf.toString("utf8");
|
|
48732
48932
|
let newlineIndex;
|
|
@@ -48749,7 +48949,7 @@ var SessionObserver = class {
|
|
|
48749
48949
|
}
|
|
48750
48950
|
}
|
|
48751
48951
|
} finally {
|
|
48752
|
-
|
|
48952
|
+
import_node_fs23.default.closeSync(fd);
|
|
48753
48953
|
}
|
|
48754
48954
|
}
|
|
48755
48955
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -49493,9 +49693,6 @@ function constantTimeEqual2(a, b2) {
|
|
|
49493
49693
|
return diff2 === 0;
|
|
49494
49694
|
}
|
|
49495
49695
|
|
|
49496
|
-
// ../protocol/src/index.ts
|
|
49497
|
-
init_runtime();
|
|
49498
|
-
|
|
49499
49696
|
// src/transport/connection-context.ts
|
|
49500
49697
|
function ownerContext(ownerPrincipalId, displayName) {
|
|
49501
49698
|
return {
|
|
@@ -49514,11 +49711,26 @@ function connectGuestContext(subDevice, subOwner, provider, displayName) {
|
|
|
49514
49711
|
provider
|
|
49515
49712
|
};
|
|
49516
49713
|
}
|
|
49714
|
+
function visitorGuestContext(p2) {
|
|
49715
|
+
return {
|
|
49716
|
+
principal: { id: `visitor-${p2.visitorId}`, kind: "guest", displayName: p2.displayName },
|
|
49717
|
+
grants: PERSONAL_CAP_GRANTS.map((g2) => ({
|
|
49718
|
+
resource: { ...g2.resource },
|
|
49719
|
+
actions: [...g2.actions]
|
|
49720
|
+
})),
|
|
49721
|
+
ownerId: p2.visitorId,
|
|
49722
|
+
provider: p2.provider
|
|
49723
|
+
};
|
|
49724
|
+
}
|
|
49517
49725
|
async function authenticate(token, deps) {
|
|
49518
49726
|
if (!token) return { ok: false, code: "NO_TOKEN" };
|
|
49519
49727
|
if (deps.isOwnerToken(token)) {
|
|
49520
49728
|
return { ok: true, context: ownerContext(deps.ownerPrincipalId, deps.ownerDisplayName) };
|
|
49521
49729
|
}
|
|
49730
|
+
if (deps.verifyVisitorToken) {
|
|
49731
|
+
const vr = deps.verifyVisitorToken(token);
|
|
49732
|
+
if (vr.ok) return { ok: true, context: visitorGuestContext(vr.payload) };
|
|
49733
|
+
}
|
|
49522
49734
|
if (!deps.verifyConnectToken) return { ok: false, code: "BAD_TOKEN" };
|
|
49523
49735
|
const result = deps.verifyConnectToken(token);
|
|
49524
49736
|
if (!result.ok) {
|
|
@@ -49533,14 +49745,14 @@ async function authenticate(token, deps) {
|
|
|
49533
49745
|
}
|
|
49534
49746
|
|
|
49535
49747
|
// src/permission/capability-store.ts
|
|
49536
|
-
var
|
|
49537
|
-
var
|
|
49748
|
+
var fs27 = __toESM(require("fs"), 1);
|
|
49749
|
+
var path26 = __toESM(require("path"), 1);
|
|
49538
49750
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
49539
49751
|
var FILE_VERSION = 1;
|
|
49540
49752
|
var CapabilityStore = class {
|
|
49541
49753
|
constructor(dataDir) {
|
|
49542
49754
|
this.dataDir = dataDir;
|
|
49543
|
-
|
|
49755
|
+
fs27.mkdirSync(dataDir, { recursive: true });
|
|
49544
49756
|
this.cache = this.readFromDisk();
|
|
49545
49757
|
}
|
|
49546
49758
|
dataDir;
|
|
@@ -49564,13 +49776,13 @@ var CapabilityStore = class {
|
|
|
49564
49776
|
this.flush();
|
|
49565
49777
|
}
|
|
49566
49778
|
filePath() {
|
|
49567
|
-
return
|
|
49779
|
+
return path26.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
49568
49780
|
}
|
|
49569
49781
|
readFromDisk() {
|
|
49570
49782
|
const file = this.filePath();
|
|
49571
49783
|
let raw;
|
|
49572
49784
|
try {
|
|
49573
|
-
raw =
|
|
49785
|
+
raw = fs27.readFileSync(file, "utf8");
|
|
49574
49786
|
} catch (err) {
|
|
49575
49787
|
if (err?.code === "ENOENT") return [];
|
|
49576
49788
|
return [];
|
|
@@ -49598,17 +49810,17 @@ var CapabilityStore = class {
|
|
|
49598
49810
|
}
|
|
49599
49811
|
atomicWrite(file, content) {
|
|
49600
49812
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
49601
|
-
|
|
49602
|
-
|
|
49813
|
+
fs27.writeFileSync(tmp, content, { mode: 384 });
|
|
49814
|
+
fs27.renameSync(tmp, file);
|
|
49603
49815
|
try {
|
|
49604
|
-
|
|
49816
|
+
fs27.chmodSync(file, 384);
|
|
49605
49817
|
} catch {
|
|
49606
49818
|
}
|
|
49607
49819
|
}
|
|
49608
49820
|
};
|
|
49609
49821
|
|
|
49610
49822
|
// src/permission/capability-registry.ts
|
|
49611
|
-
var
|
|
49823
|
+
var crypto5 = __toESM(require("crypto"), 1);
|
|
49612
49824
|
var CapabilityRegistry = class {
|
|
49613
49825
|
constructor(store, now = () => Date.now()) {
|
|
49614
49826
|
this.store = store;
|
|
@@ -49661,7 +49873,7 @@ var CapabilityRegistry = class {
|
|
|
49661
49873
|
}
|
|
49662
49874
|
};
|
|
49663
49875
|
function sha256Hex(s) {
|
|
49664
|
-
return
|
|
49876
|
+
return crypto5.createHash("sha256").update(s).digest("hex");
|
|
49665
49877
|
}
|
|
49666
49878
|
|
|
49667
49879
|
// src/permission/capability-manager.ts
|
|
@@ -49694,14 +49906,14 @@ var CapabilityManager = class {
|
|
|
49694
49906
|
};
|
|
49695
49907
|
|
|
49696
49908
|
// src/permission/cleanup.ts
|
|
49697
|
-
var
|
|
49909
|
+
var fs28 = __toESM(require("fs"), 1);
|
|
49698
49910
|
function cleanupGuestSessionsForCapability(cap, factory) {
|
|
49699
49911
|
const removed = [];
|
|
49700
49912
|
for (const g2 of cap.grants) {
|
|
49701
49913
|
if (g2.resource.type !== "persona") continue;
|
|
49702
49914
|
const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
|
|
49703
49915
|
try {
|
|
49704
|
-
|
|
49916
|
+
fs28.rmSync(dir, { recursive: true, force: true });
|
|
49705
49917
|
removed.push(dir);
|
|
49706
49918
|
} catch {
|
|
49707
49919
|
}
|
|
@@ -49710,13 +49922,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
49710
49922
|
}
|
|
49711
49923
|
|
|
49712
49924
|
// src/inbox/inbox-store.ts
|
|
49713
|
-
var
|
|
49714
|
-
var
|
|
49925
|
+
var fs29 = __toESM(require("fs"), 1);
|
|
49926
|
+
var path27 = __toESM(require("path"), 1);
|
|
49715
49927
|
var INBOX_SUBDIR = "inbox";
|
|
49716
49928
|
var InboxStore = class {
|
|
49717
49929
|
constructor(dataDir) {
|
|
49718
49930
|
this.dataDir = dataDir;
|
|
49719
|
-
|
|
49931
|
+
fs29.mkdirSync(this.dirPath(), { recursive: true });
|
|
49720
49932
|
}
|
|
49721
49933
|
dataDir;
|
|
49722
49934
|
/**
|
|
@@ -49728,7 +49940,7 @@ var InboxStore = class {
|
|
|
49728
49940
|
const file = this.filePath(peerDeviceId);
|
|
49729
49941
|
let raw;
|
|
49730
49942
|
try {
|
|
49731
|
-
raw =
|
|
49943
|
+
raw = fs29.readFileSync(file, "utf8");
|
|
49732
49944
|
} catch (err) {
|
|
49733
49945
|
if (err?.code === "ENOENT") return [];
|
|
49734
49946
|
return [];
|
|
@@ -49744,7 +49956,7 @@ var InboxStore = class {
|
|
|
49744
49956
|
const dir = this.dirPath();
|
|
49745
49957
|
let entries;
|
|
49746
49958
|
try {
|
|
49747
|
-
entries =
|
|
49959
|
+
entries = fs29.readdirSync(dir);
|
|
49748
49960
|
} catch (err) {
|
|
49749
49961
|
if (err?.code === "ENOENT") return [];
|
|
49750
49962
|
return [];
|
|
@@ -49760,9 +49972,9 @@ var InboxStore = class {
|
|
|
49760
49972
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
49761
49973
|
const file = this.filePath(message.peerDeviceId);
|
|
49762
49974
|
const line = JSON.stringify(message) + "\n";
|
|
49763
|
-
|
|
49975
|
+
fs29.appendFileSync(file, line, { mode: 384 });
|
|
49764
49976
|
try {
|
|
49765
|
-
|
|
49977
|
+
fs29.chmodSync(file, 384);
|
|
49766
49978
|
} catch {
|
|
49767
49979
|
}
|
|
49768
49980
|
}
|
|
@@ -49792,7 +50004,7 @@ var InboxStore = class {
|
|
|
49792
50004
|
removeByPeerDeviceId(peerDeviceId) {
|
|
49793
50005
|
const file = this.filePath(peerDeviceId);
|
|
49794
50006
|
try {
|
|
49795
|
-
|
|
50007
|
+
fs29.unlinkSync(file);
|
|
49796
50008
|
} catch (err) {
|
|
49797
50009
|
if (err?.code === "ENOENT") return;
|
|
49798
50010
|
}
|
|
@@ -49801,18 +50013,18 @@ var InboxStore = class {
|
|
|
49801
50013
|
const file = this.filePath(peerDeviceId);
|
|
49802
50014
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
49803
50015
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
49804
|
-
|
|
49805
|
-
|
|
50016
|
+
fs29.writeFileSync(tmp, content, { mode: 384 });
|
|
50017
|
+
fs29.renameSync(tmp, file);
|
|
49806
50018
|
try {
|
|
49807
|
-
|
|
50019
|
+
fs29.chmodSync(file, 384);
|
|
49808
50020
|
} catch {
|
|
49809
50021
|
}
|
|
49810
50022
|
}
|
|
49811
50023
|
dirPath() {
|
|
49812
|
-
return
|
|
50024
|
+
return path27.join(this.dataDir, INBOX_SUBDIR);
|
|
49813
50025
|
}
|
|
49814
50026
|
filePath(peerDeviceId) {
|
|
49815
|
-
return
|
|
50027
|
+
return path27.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
49816
50028
|
}
|
|
49817
50029
|
};
|
|
49818
50030
|
function parseAllLines(raw) {
|
|
@@ -49899,8 +50111,8 @@ var InboxManager = class {
|
|
|
49899
50111
|
};
|
|
49900
50112
|
|
|
49901
50113
|
// src/state/contact-store.ts
|
|
49902
|
-
var
|
|
49903
|
-
var
|
|
50114
|
+
var fs30 = __toESM(require("fs"), 1);
|
|
50115
|
+
var path28 = __toESM(require("path"), 1);
|
|
49904
50116
|
var FILE_NAME = "contacts.json";
|
|
49905
50117
|
var ContactStore = class {
|
|
49906
50118
|
constructor(dataDir) {
|
|
@@ -49910,10 +50122,10 @@ var ContactStore = class {
|
|
|
49910
50122
|
contacts = /* @__PURE__ */ new Map();
|
|
49911
50123
|
load() {
|
|
49912
50124
|
this.contacts.clear();
|
|
49913
|
-
const file =
|
|
50125
|
+
const file = path28.join(this.dataDir, FILE_NAME);
|
|
49914
50126
|
let raw;
|
|
49915
50127
|
try {
|
|
49916
|
-
raw =
|
|
50128
|
+
raw = fs30.readFileSync(file, "utf8");
|
|
49917
50129
|
} catch (err) {
|
|
49918
50130
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
49919
50131
|
return;
|
|
@@ -49956,27 +50168,27 @@ var ContactStore = class {
|
|
|
49956
50168
|
return existed;
|
|
49957
50169
|
}
|
|
49958
50170
|
flush() {
|
|
49959
|
-
const file =
|
|
50171
|
+
const file = path28.join(this.dataDir, FILE_NAME);
|
|
49960
50172
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
49961
50173
|
const content = JSON.stringify(
|
|
49962
50174
|
{ contacts: Array.from(this.contacts.values()) },
|
|
49963
50175
|
null,
|
|
49964
50176
|
2
|
|
49965
50177
|
);
|
|
49966
|
-
|
|
49967
|
-
|
|
49968
|
-
|
|
50178
|
+
fs30.mkdirSync(this.dataDir, { recursive: true });
|
|
50179
|
+
fs30.writeFileSync(tmp, content, { mode: 384 });
|
|
50180
|
+
fs30.renameSync(tmp, file);
|
|
49969
50181
|
}
|
|
49970
50182
|
renameBak(file) {
|
|
49971
50183
|
try {
|
|
49972
|
-
|
|
50184
|
+
fs30.renameSync(file, `${file}.bak`);
|
|
49973
50185
|
} catch {
|
|
49974
50186
|
}
|
|
49975
50187
|
}
|
|
49976
50188
|
};
|
|
49977
50189
|
|
|
49978
50190
|
// src/contact/connect-remote.ts
|
|
49979
|
-
var
|
|
50191
|
+
var crypto6 = __toESM(require("crypto"), 1);
|
|
49980
50192
|
var HANDSHAKE_TIMEOUT_MS = 5e3;
|
|
49981
50193
|
var RPC_TIMEOUT_MS = 5e3;
|
|
49982
50194
|
async function connectRemote(args) {
|
|
@@ -50040,7 +50252,7 @@ async function connectRemote(args) {
|
|
|
50040
50252
|
ws.once("close", onClose);
|
|
50041
50253
|
});
|
|
50042
50254
|
function call(method, payload) {
|
|
50043
|
-
const requestId =
|
|
50255
|
+
const requestId = crypto6.randomUUID();
|
|
50044
50256
|
return new Promise((resolve6, reject) => {
|
|
50045
50257
|
const onMessage = (raw) => {
|
|
50046
50258
|
let f;
|
|
@@ -50119,61 +50331,61 @@ async function autoReverseContact(args) {
|
|
|
50119
50331
|
}
|
|
50120
50332
|
|
|
50121
50333
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
50122
|
-
var
|
|
50123
|
-
var
|
|
50334
|
+
var fs31 = __toESM(require("fs"), 1);
|
|
50335
|
+
var path29 = __toESM(require("path"), 1);
|
|
50124
50336
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
50125
50337
|
function migrateFlattenSessions(opts) {
|
|
50126
50338
|
const dataDir = opts.dataDir;
|
|
50127
50339
|
const now = opts.now ?? Date.now;
|
|
50128
|
-
const sessionsDir =
|
|
50129
|
-
const flagPath =
|
|
50340
|
+
const sessionsDir = path29.join(dataDir, "sessions");
|
|
50341
|
+
const flagPath = path29.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
50130
50342
|
if (existsSync3(flagPath)) {
|
|
50131
50343
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
50132
50344
|
}
|
|
50133
50345
|
let movedBare = 0;
|
|
50134
50346
|
let movedVmOwner = 0;
|
|
50135
50347
|
let archivedListener = 0;
|
|
50136
|
-
const defaultDir =
|
|
50348
|
+
const defaultDir = path29.join(sessionsDir, "default");
|
|
50137
50349
|
if (existsSync3(defaultDir)) {
|
|
50138
50350
|
for (const entry of readdirSafe(defaultDir)) {
|
|
50139
50351
|
if (!entry.endsWith(".json")) continue;
|
|
50140
|
-
const src =
|
|
50141
|
-
const dst =
|
|
50142
|
-
|
|
50352
|
+
const src = path29.join(defaultDir, entry);
|
|
50353
|
+
const dst = path29.join(sessionsDir, entry);
|
|
50354
|
+
fs31.renameSync(src, dst);
|
|
50143
50355
|
movedBare += 1;
|
|
50144
50356
|
}
|
|
50145
50357
|
rmdirIfEmpty(defaultDir);
|
|
50146
50358
|
}
|
|
50147
50359
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
50148
|
-
const personaDir =
|
|
50360
|
+
const personaDir = path29.join(sessionsDir, pid);
|
|
50149
50361
|
if (!isDir(personaDir)) continue;
|
|
50150
50362
|
if (pid === "default") continue;
|
|
50151
|
-
const ownerSrc =
|
|
50363
|
+
const ownerSrc = path29.join(personaDir, "owner");
|
|
50152
50364
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
50153
|
-
const ownerDst =
|
|
50154
|
-
|
|
50365
|
+
const ownerDst = path29.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
50366
|
+
fs31.mkdirSync(ownerDst, { recursive: true });
|
|
50155
50367
|
for (const file of readdirSafe(ownerSrc)) {
|
|
50156
50368
|
if (!file.endsWith(".json")) continue;
|
|
50157
|
-
|
|
50369
|
+
fs31.renameSync(path29.join(ownerSrc, file), path29.join(ownerDst, file));
|
|
50158
50370
|
movedVmOwner += 1;
|
|
50159
50371
|
}
|
|
50160
50372
|
rmdirIfEmpty(ownerSrc);
|
|
50161
50373
|
}
|
|
50162
|
-
const listenerSrc =
|
|
50374
|
+
const listenerSrc = path29.join(personaDir, "listener");
|
|
50163
50375
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
50164
|
-
const archiveDst =
|
|
50165
|
-
|
|
50376
|
+
const archiveDst = path29.join(dataDir, ".legacy", `listener-${pid}`);
|
|
50377
|
+
fs31.mkdirSync(archiveDst, { recursive: true });
|
|
50166
50378
|
for (const file of readdirSafe(listenerSrc)) {
|
|
50167
50379
|
if (!file.endsWith(".json")) continue;
|
|
50168
|
-
|
|
50380
|
+
fs31.renameSync(path29.join(listenerSrc, file), path29.join(archiveDst, file));
|
|
50169
50381
|
archivedListener += 1;
|
|
50170
50382
|
}
|
|
50171
50383
|
rmdirIfEmpty(listenerSrc);
|
|
50172
50384
|
}
|
|
50173
50385
|
rmdirIfEmpty(personaDir);
|
|
50174
50386
|
}
|
|
50175
|
-
|
|
50176
|
-
|
|
50387
|
+
fs31.mkdirSync(sessionsDir, { recursive: true });
|
|
50388
|
+
fs31.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
50177
50389
|
return {
|
|
50178
50390
|
skipped: false,
|
|
50179
50391
|
flagWritten: true,
|
|
@@ -50184,7 +50396,7 @@ function migrateFlattenSessions(opts) {
|
|
|
50184
50396
|
}
|
|
50185
50397
|
function existsSync3(p2) {
|
|
50186
50398
|
try {
|
|
50187
|
-
|
|
50399
|
+
fs31.statSync(p2);
|
|
50188
50400
|
return true;
|
|
50189
50401
|
} catch {
|
|
50190
50402
|
return false;
|
|
@@ -50192,31 +50404,31 @@ function existsSync3(p2) {
|
|
|
50192
50404
|
}
|
|
50193
50405
|
function isDir(p2) {
|
|
50194
50406
|
try {
|
|
50195
|
-
return
|
|
50407
|
+
return fs31.statSync(p2).isDirectory();
|
|
50196
50408
|
} catch {
|
|
50197
50409
|
return false;
|
|
50198
50410
|
}
|
|
50199
50411
|
}
|
|
50200
50412
|
function readdirSafe(p2) {
|
|
50201
50413
|
try {
|
|
50202
|
-
return
|
|
50414
|
+
return fs31.readdirSync(p2);
|
|
50203
50415
|
} catch {
|
|
50204
50416
|
return [];
|
|
50205
50417
|
}
|
|
50206
50418
|
}
|
|
50207
50419
|
function rmdirIfEmpty(p2) {
|
|
50208
50420
|
try {
|
|
50209
|
-
|
|
50421
|
+
fs31.rmdirSync(p2);
|
|
50210
50422
|
} catch {
|
|
50211
50423
|
}
|
|
50212
50424
|
}
|
|
50213
50425
|
|
|
50214
50426
|
// src/transport/http-router.ts
|
|
50215
|
-
var
|
|
50216
|
-
var
|
|
50427
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
50428
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
50217
50429
|
|
|
50218
50430
|
// src/attachment/mime.ts
|
|
50219
|
-
var
|
|
50431
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
50220
50432
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
50221
50433
|
var EXT_TO_NATIVE_MIME = {
|
|
50222
50434
|
// 图片
|
|
@@ -50323,14 +50535,14 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
50323
50535
|
".mk"
|
|
50324
50536
|
]);
|
|
50325
50537
|
function lookupMime(filePathOrName) {
|
|
50326
|
-
const ext =
|
|
50538
|
+
const ext = import_node_path22.default.extname(filePathOrName).toLowerCase();
|
|
50327
50539
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
50328
50540
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
50329
50541
|
return "application/octet-stream";
|
|
50330
50542
|
}
|
|
50331
50543
|
|
|
50332
50544
|
// src/attachment/sign-url.ts
|
|
50333
|
-
var
|
|
50545
|
+
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
50334
50546
|
var HMAC_ALGO = "sha256";
|
|
50335
50547
|
function base64urlEncode(buf) {
|
|
50336
50548
|
const b2 = typeof buf === "string" ? Buffer.from(buf, "utf8") : buf;
|
|
@@ -50347,7 +50559,7 @@ function decodeAbsPathFromUrl(encoded) {
|
|
|
50347
50559
|
}
|
|
50348
50560
|
function computeSig(secret, absPath, e) {
|
|
50349
50561
|
const msg = e === null ? absPath : `${absPath}|${e}`;
|
|
50350
|
-
return
|
|
50562
|
+
return import_node_crypto6.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
|
|
50351
50563
|
}
|
|
50352
50564
|
function signUrlParts(secret, absPath, ttlSeconds, now = Date.now) {
|
|
50353
50565
|
const e = ttlSeconds === null ? null : Math.floor(now() / 1e3) + ttlSeconds;
|
|
@@ -50382,7 +50594,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
50382
50594
|
if (provided.length !== expected.length) {
|
|
50383
50595
|
return { ok: false, code: "BAD_SIG" };
|
|
50384
50596
|
}
|
|
50385
|
-
if (!
|
|
50597
|
+
if (!import_node_crypto6.default.timingSafeEqual(provided, expected)) {
|
|
50386
50598
|
return { ok: false, code: "BAD_SIG" };
|
|
50387
50599
|
}
|
|
50388
50600
|
if (e !== null && now() / 1e3 > e) {
|
|
@@ -50392,9 +50604,9 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
50392
50604
|
}
|
|
50393
50605
|
|
|
50394
50606
|
// src/attachment/upload.ts
|
|
50395
|
-
var
|
|
50396
|
-
var
|
|
50397
|
-
var
|
|
50607
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
50608
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
50609
|
+
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
50398
50610
|
var import_promises2 = require("stream/promises");
|
|
50399
50611
|
var UploadError = class extends Error {
|
|
50400
50612
|
constructor(code, message) {
|
|
@@ -50405,24 +50617,24 @@ var UploadError = class extends Error {
|
|
|
50405
50617
|
code;
|
|
50406
50618
|
};
|
|
50407
50619
|
function assertValidFileName(fileName) {
|
|
50408
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
50620
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path23.default.basename(fileName)) {
|
|
50409
50621
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
50410
50622
|
}
|
|
50411
50623
|
}
|
|
50412
50624
|
var HASH_PREFIX_LEN = 16;
|
|
50413
50625
|
async function writeUploadedAttachment(args) {
|
|
50414
50626
|
assertValidFileName(args.fileName);
|
|
50415
|
-
const attachmentsRoot =
|
|
50627
|
+
const attachmentsRoot = import_node_path23.default.join(args.sessionDir, ".attachments");
|
|
50416
50628
|
try {
|
|
50417
|
-
|
|
50629
|
+
import_node_fs24.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
50418
50630
|
} catch (err) {
|
|
50419
50631
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
50420
50632
|
}
|
|
50421
|
-
const hasher =
|
|
50633
|
+
const hasher = import_node_crypto7.default.createHash("sha256");
|
|
50422
50634
|
let actualSize = 0;
|
|
50423
|
-
const tmpPath =
|
|
50635
|
+
const tmpPath = import_node_path23.default.join(
|
|
50424
50636
|
attachmentsRoot,
|
|
50425
|
-
`.upload-${process.pid}-${Date.now()}-${
|
|
50637
|
+
`.upload-${process.pid}-${Date.now()}-${import_node_crypto7.default.randomBytes(4).toString("hex")}`
|
|
50426
50638
|
);
|
|
50427
50639
|
try {
|
|
50428
50640
|
await (0, import_promises2.pipeline)(
|
|
@@ -50435,18 +50647,18 @@ async function writeUploadedAttachment(args) {
|
|
|
50435
50647
|
yield buf;
|
|
50436
50648
|
}
|
|
50437
50649
|
},
|
|
50438
|
-
|
|
50650
|
+
import_node_fs24.default.createWriteStream(tmpPath, { mode: 384 })
|
|
50439
50651
|
);
|
|
50440
50652
|
} catch (err) {
|
|
50441
50653
|
try {
|
|
50442
|
-
|
|
50654
|
+
import_node_fs24.default.unlinkSync(tmpPath);
|
|
50443
50655
|
} catch {
|
|
50444
50656
|
}
|
|
50445
50657
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
50446
50658
|
}
|
|
50447
50659
|
if (actualSize !== args.contentLength) {
|
|
50448
50660
|
try {
|
|
50449
|
-
|
|
50661
|
+
import_node_fs24.default.unlinkSync(tmpPath);
|
|
50450
50662
|
} catch {
|
|
50451
50663
|
}
|
|
50452
50664
|
throw new UploadError(
|
|
@@ -50455,35 +50667,35 @@ async function writeUploadedAttachment(args) {
|
|
|
50455
50667
|
);
|
|
50456
50668
|
}
|
|
50457
50669
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
50458
|
-
const hashDir =
|
|
50670
|
+
const hashDir = import_node_path23.default.join(attachmentsRoot, attachmentId);
|
|
50459
50671
|
let finalFileName;
|
|
50460
50672
|
let hashDirExists = false;
|
|
50461
50673
|
try {
|
|
50462
|
-
hashDirExists =
|
|
50674
|
+
hashDirExists = import_node_fs24.default.statSync(hashDir).isDirectory();
|
|
50463
50675
|
} catch {
|
|
50464
50676
|
}
|
|
50465
50677
|
if (hashDirExists) {
|
|
50466
|
-
const existing =
|
|
50678
|
+
const existing = import_node_fs24.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
50467
50679
|
finalFileName = existing[0] ?? args.fileName;
|
|
50468
50680
|
try {
|
|
50469
|
-
|
|
50681
|
+
import_node_fs24.default.unlinkSync(tmpPath);
|
|
50470
50682
|
} catch {
|
|
50471
50683
|
}
|
|
50472
50684
|
} else {
|
|
50473
50685
|
try {
|
|
50474
|
-
|
|
50686
|
+
import_node_fs24.default.mkdirSync(hashDir, { recursive: true });
|
|
50475
50687
|
finalFileName = args.fileName;
|
|
50476
|
-
|
|
50688
|
+
import_node_fs24.default.renameSync(tmpPath, import_node_path23.default.join(hashDir, finalFileName));
|
|
50477
50689
|
} catch (err) {
|
|
50478
50690
|
try {
|
|
50479
|
-
|
|
50691
|
+
import_node_fs24.default.unlinkSync(tmpPath);
|
|
50480
50692
|
} catch {
|
|
50481
50693
|
}
|
|
50482
50694
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
50483
50695
|
}
|
|
50484
50696
|
}
|
|
50485
|
-
const absPath =
|
|
50486
|
-
const relPath =
|
|
50697
|
+
const absPath = import_node_path23.default.join(hashDir, finalFileName);
|
|
50698
|
+
const relPath = import_node_path23.default.relative(args.sessionDir, absPath);
|
|
50487
50699
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
50488
50700
|
relPath: absPath,
|
|
50489
50701
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -50497,7 +50709,7 @@ async function writeUploadedAttachment(args) {
|
|
|
50497
50709
|
|
|
50498
50710
|
// src/extension/import.ts
|
|
50499
50711
|
var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
50500
|
-
var
|
|
50712
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
50501
50713
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
50502
50714
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
50503
50715
|
var ImportError = class extends Error {
|
|
@@ -50515,7 +50727,7 @@ async function importZip(buf, root) {
|
|
|
50515
50727
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
50516
50728
|
}
|
|
50517
50729
|
for (const name of Object.keys(zip.files)) {
|
|
50518
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
50730
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path24.default.isAbsolute(name)) {
|
|
50519
50731
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
50520
50732
|
}
|
|
50521
50733
|
}
|
|
@@ -50548,7 +50760,7 @@ async function importZip(buf, root) {
|
|
|
50548
50760
|
);
|
|
50549
50761
|
}
|
|
50550
50762
|
}
|
|
50551
|
-
const destDir =
|
|
50763
|
+
const destDir = import_node_path24.default.join(root, manifest.id);
|
|
50552
50764
|
let destExists = false;
|
|
50553
50765
|
try {
|
|
50554
50766
|
await import_promises3.default.access(destDir);
|
|
@@ -50558,15 +50770,15 @@ async function importZip(buf, root) {
|
|
|
50558
50770
|
if (destExists) {
|
|
50559
50771
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
50560
50772
|
}
|
|
50561
|
-
const stage = await import_promises3.default.mkdtemp(
|
|
50773
|
+
const stage = await import_promises3.default.mkdtemp(import_node_path24.default.join(import_node_os11.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
50562
50774
|
try {
|
|
50563
50775
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
50564
|
-
const dest =
|
|
50776
|
+
const dest = import_node_path24.default.join(stage, name);
|
|
50565
50777
|
if (entry.dir) {
|
|
50566
50778
|
await import_promises3.default.mkdir(dest, { recursive: true });
|
|
50567
50779
|
continue;
|
|
50568
50780
|
}
|
|
50569
|
-
await import_promises3.default.mkdir(
|
|
50781
|
+
await import_promises3.default.mkdir(import_node_path24.default.dirname(dest), { recursive: true });
|
|
50570
50782
|
const content = await entry.async("nodebuffer");
|
|
50571
50783
|
await import_promises3.default.writeFile(dest, content);
|
|
50572
50784
|
}
|
|
@@ -50583,6 +50795,23 @@ async function importZip(buf, root) {
|
|
|
50583
50795
|
// src/transport/http-router.ts
|
|
50584
50796
|
var RPC_ROUTE_PREFIX = "/api/rpc/";
|
|
50585
50797
|
var RPC_BODY_MAX_BYTES = 1 * 1024 * 1024;
|
|
50798
|
+
var SHARE_UI_ASSETS_PREFIX = "/share-ui/assets/";
|
|
50799
|
+
var SHARE_UI_ASSET_MIME = {
|
|
50800
|
+
".js": "text/javascript; charset=utf-8",
|
|
50801
|
+
".mjs": "text/javascript; charset=utf-8",
|
|
50802
|
+
".css": "text/css; charset=utf-8",
|
|
50803
|
+
".json": "application/json; charset=utf-8",
|
|
50804
|
+
".map": "application/json; charset=utf-8",
|
|
50805
|
+
".svg": "image/svg+xml",
|
|
50806
|
+
".woff": "font/woff",
|
|
50807
|
+
".woff2": "font/woff2",
|
|
50808
|
+
".ttf": "font/ttf",
|
|
50809
|
+
".wasm": "application/wasm"
|
|
50810
|
+
};
|
|
50811
|
+
function shareUiAssetMime(filePath) {
|
|
50812
|
+
const ext = import_node_path25.default.extname(filePath).toLowerCase();
|
|
50813
|
+
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
50814
|
+
}
|
|
50586
50815
|
var DISPATCH_HEARTBEAT_MS = 25e3;
|
|
50587
50816
|
var DISPATCH_HOLD_METHOD = "personaDispatch:run";
|
|
50588
50817
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -50667,7 +50896,7 @@ function isValidUploadFileName(fileName) {
|
|
|
50667
50896
|
if (fileName === "." || fileName === "..") return false;
|
|
50668
50897
|
if (fileName.startsWith(".")) return false;
|
|
50669
50898
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
50670
|
-
return fileName ===
|
|
50899
|
+
return fileName === import_node_path25.default.basename(fileName);
|
|
50671
50900
|
}
|
|
50672
50901
|
function createHttpRouter(deps) {
|
|
50673
50902
|
return async (req, res) => {
|
|
@@ -50701,6 +50930,59 @@ function createHttpRouter(deps) {
|
|
|
50701
50930
|
res.end(html);
|
|
50702
50931
|
return true;
|
|
50703
50932
|
}
|
|
50933
|
+
if (url.pathname === "/share/exchange" && req.method === "OPTIONS") {
|
|
50934
|
+
res.writeHead(204, AUTHED_RPC_CORS_HEADERS);
|
|
50935
|
+
res.end();
|
|
50936
|
+
return true;
|
|
50937
|
+
}
|
|
50938
|
+
if (url.pathname === "/share/exchange" && req.method === "POST") {
|
|
50939
|
+
if (!deps.visitorExchange) {
|
|
50940
|
+
sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "visitor exchange not wired" }, AUTHED_RPC_CORS_HEADERS);
|
|
50941
|
+
return true;
|
|
50942
|
+
}
|
|
50943
|
+
let body;
|
|
50944
|
+
try {
|
|
50945
|
+
body = await readJsonBody(req, RPC_BODY_MAX_BYTES);
|
|
50946
|
+
} catch (err) {
|
|
50947
|
+
sendJson(res, 400, { code: "INVALID_BODY", message: err instanceof Error ? err.message : String(err) }, AUTHED_RPC_CORS_HEADERS);
|
|
50948
|
+
return true;
|
|
50949
|
+
}
|
|
50950
|
+
const r = await deps.visitorExchange({ ttcToken: body.ttcToken ?? "" });
|
|
50951
|
+
if (r.ok) sendJson(res, 200, { visitorToken: r.visitorToken }, AUTHED_RPC_CORS_HEADERS);
|
|
50952
|
+
else sendJson(res, 403, { code: r.reason }, AUTHED_RPC_CORS_HEADERS);
|
|
50953
|
+
return true;
|
|
50954
|
+
}
|
|
50955
|
+
if ((url.pathname === "/s" || url.pathname.startsWith("/s/")) && req.method === "GET") {
|
|
50956
|
+
if (!deps.shareUiAssetLoader) {
|
|
50957
|
+
sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "share-ui assets not loaded" });
|
|
50958
|
+
return true;
|
|
50959
|
+
}
|
|
50960
|
+
sendHtml(res, 200, deps.shareUiAssetLoader.renderIndexHtml());
|
|
50961
|
+
return true;
|
|
50962
|
+
}
|
|
50963
|
+
if (url.pathname.startsWith(SHARE_UI_ASSETS_PREFIX) && req.method === "GET") {
|
|
50964
|
+
const abs = deps.shareUiAssetLoader?.resolveAssetPath(url.pathname.slice(SHARE_UI_ASSETS_PREFIX.length));
|
|
50965
|
+
if (!abs) {
|
|
50966
|
+
sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
50967
|
+
return true;
|
|
50968
|
+
}
|
|
50969
|
+
let buf;
|
|
50970
|
+
try {
|
|
50971
|
+
buf = await import_node_fs25.default.promises.readFile(abs);
|
|
50972
|
+
} catch {
|
|
50973
|
+
sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
50974
|
+
return true;
|
|
50975
|
+
}
|
|
50976
|
+
res.writeHead(200, {
|
|
50977
|
+
"Content-Type": shareUiAssetMime(abs),
|
|
50978
|
+
"Content-Length": String(buf.length),
|
|
50979
|
+
// vite 产物文件名带内容 hash,可永久强缓存
|
|
50980
|
+
"Cache-Control": "public, max-age=31536000, immutable",
|
|
50981
|
+
"X-Content-Type-Options": "nosniff"
|
|
50982
|
+
});
|
|
50983
|
+
res.end(buf);
|
|
50984
|
+
return true;
|
|
50985
|
+
}
|
|
50704
50986
|
if (url.pathname.startsWith(AUTHED_RPC_ROUTE_PREFIX)) {
|
|
50705
50987
|
if (req.method === "OPTIONS") {
|
|
50706
50988
|
res.writeHead(204, AUTHED_RPC_CORS_HEADERS);
|
|
@@ -50910,7 +51192,7 @@ function createHttpRouter(deps) {
|
|
|
50910
51192
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
50911
51193
|
return true;
|
|
50912
51194
|
}
|
|
50913
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
51195
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path25.default.basename(r.absPath)));
|
|
50914
51196
|
return true;
|
|
50915
51197
|
}
|
|
50916
51198
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -51031,7 +51313,7 @@ function createHttpRouter(deps) {
|
|
|
51031
51313
|
return true;
|
|
51032
51314
|
}
|
|
51033
51315
|
let absPath;
|
|
51034
|
-
if (
|
|
51316
|
+
if (import_node_path25.default.isAbsolute(pathParam)) {
|
|
51035
51317
|
absPath = pathParam;
|
|
51036
51318
|
} else if (deps.sessionStore) {
|
|
51037
51319
|
const file = deps.sessionStore.read(sid);
|
|
@@ -51039,7 +51321,7 @@ function createHttpRouter(deps) {
|
|
|
51039
51321
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
51040
51322
|
return true;
|
|
51041
51323
|
}
|
|
51042
|
-
absPath =
|
|
51324
|
+
absPath = import_node_path25.default.join(file.cwd, pathParam);
|
|
51043
51325
|
} else {
|
|
51044
51326
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
51045
51327
|
return true;
|
|
@@ -51126,7 +51408,7 @@ function withCtx(ctx, body) {
|
|
|
51126
51408
|
function streamFile(res, absPath, logger) {
|
|
51127
51409
|
let stat;
|
|
51128
51410
|
try {
|
|
51129
|
-
stat =
|
|
51411
|
+
stat = import_node_fs25.default.statSync(absPath);
|
|
51130
51412
|
} catch (err) {
|
|
51131
51413
|
const code = err?.code;
|
|
51132
51414
|
if (code === "ENOENT") {
|
|
@@ -51141,7 +51423,7 @@ function streamFile(res, absPath, logger) {
|
|
|
51141
51423
|
return;
|
|
51142
51424
|
}
|
|
51143
51425
|
const mime = lookupMime(absPath);
|
|
51144
|
-
const basename =
|
|
51426
|
+
const basename = import_node_path25.default.basename(absPath);
|
|
51145
51427
|
res.writeHead(200, {
|
|
51146
51428
|
"Content-Type": mime,
|
|
51147
51429
|
"Content-Length": String(stat.size),
|
|
@@ -51149,7 +51431,7 @@ function streamFile(res, absPath, logger) {
|
|
|
51149
51431
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
51150
51432
|
"X-Content-Type-Options": "nosniff"
|
|
51151
51433
|
});
|
|
51152
|
-
const stream =
|
|
51434
|
+
const stream = import_node_fs25.default.createReadStream(absPath);
|
|
51153
51435
|
stream.on("error", (err) => {
|
|
51154
51436
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
51155
51437
|
res.destroy();
|
|
@@ -51158,8 +51440,8 @@ function streamFile(res, absPath, logger) {
|
|
|
51158
51440
|
}
|
|
51159
51441
|
|
|
51160
51442
|
// src/attachment/gc.ts
|
|
51161
|
-
var
|
|
51162
|
-
var
|
|
51443
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
51444
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
51163
51445
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
51164
51446
|
function runAttachmentGc(args) {
|
|
51165
51447
|
const now = (args.now ?? Date.now)();
|
|
@@ -51168,38 +51450,38 @@ function runAttachmentGc(args) {
|
|
|
51168
51450
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
51169
51451
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
51170
51452
|
if (entry.stale) continue;
|
|
51171
|
-
if (
|
|
51453
|
+
if (import_node_path26.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
51172
51454
|
}
|
|
51173
51455
|
}
|
|
51174
51456
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
51175
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
51457
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path26.default.join(
|
|
51176
51458
|
args.dataDir,
|
|
51177
51459
|
"sessions",
|
|
51178
51460
|
...scopeSubPath(scope).map(safeFileName),
|
|
51179
51461
|
safeFileName(sessionId)
|
|
51180
51462
|
);
|
|
51181
|
-
const attRoot =
|
|
51463
|
+
const attRoot = import_node_path26.default.join(sessionDir, ".attachments");
|
|
51182
51464
|
let hashDirs;
|
|
51183
51465
|
try {
|
|
51184
|
-
hashDirs =
|
|
51466
|
+
hashDirs = import_node_fs26.default.readdirSync(attRoot);
|
|
51185
51467
|
} catch (err) {
|
|
51186
51468
|
if (err.code === "ENOENT") continue;
|
|
51187
51469
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
51188
51470
|
continue;
|
|
51189
51471
|
}
|
|
51190
51472
|
for (const hashDir of hashDirs) {
|
|
51191
|
-
const hashDirAbs =
|
|
51473
|
+
const hashDirAbs = import_node_path26.default.join(attRoot, hashDir);
|
|
51192
51474
|
let files;
|
|
51193
51475
|
try {
|
|
51194
|
-
files =
|
|
51476
|
+
files = import_node_fs26.default.readdirSync(hashDirAbs);
|
|
51195
51477
|
} catch {
|
|
51196
51478
|
continue;
|
|
51197
51479
|
}
|
|
51198
51480
|
for (const name of files) {
|
|
51199
|
-
const file =
|
|
51481
|
+
const file = import_node_path26.default.join(hashDirAbs, name);
|
|
51200
51482
|
let stat;
|
|
51201
51483
|
try {
|
|
51202
|
-
stat =
|
|
51484
|
+
stat = import_node_fs26.default.statSync(file);
|
|
51203
51485
|
} catch {
|
|
51204
51486
|
continue;
|
|
51205
51487
|
}
|
|
@@ -51208,27 +51490,27 @@ function runAttachmentGc(args) {
|
|
|
51208
51490
|
if (age < ttlMs) continue;
|
|
51209
51491
|
if (liveAbs.has(file)) continue;
|
|
51210
51492
|
try {
|
|
51211
|
-
|
|
51493
|
+
import_node_fs26.default.unlinkSync(file);
|
|
51212
51494
|
} catch (err) {
|
|
51213
51495
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
51214
51496
|
}
|
|
51215
51497
|
}
|
|
51216
51498
|
try {
|
|
51217
|
-
if (
|
|
51499
|
+
if (import_node_fs26.default.readdirSync(hashDirAbs).length === 0) import_node_fs26.default.rmdirSync(hashDirAbs);
|
|
51218
51500
|
} catch {
|
|
51219
51501
|
}
|
|
51220
51502
|
}
|
|
51221
51503
|
try {
|
|
51222
|
-
if (
|
|
51504
|
+
if (import_node_fs26.default.readdirSync(attRoot).length === 0) import_node_fs26.default.rmdirSync(attRoot);
|
|
51223
51505
|
} catch {
|
|
51224
51506
|
}
|
|
51225
51507
|
}
|
|
51226
51508
|
}
|
|
51227
51509
|
|
|
51228
51510
|
// src/attachment/group.ts
|
|
51229
|
-
var
|
|
51230
|
-
var
|
|
51231
|
-
var
|
|
51511
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
51512
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
51513
|
+
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
51232
51514
|
init_protocol();
|
|
51233
51515
|
var GroupFileStore = class {
|
|
51234
51516
|
dataDir;
|
|
@@ -51239,11 +51521,11 @@ var GroupFileStore = class {
|
|
|
51239
51521
|
this.logger = opts.logger;
|
|
51240
51522
|
}
|
|
51241
51523
|
rootForScope(scope) {
|
|
51242
|
-
return
|
|
51524
|
+
return import_node_path27.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
51243
51525
|
}
|
|
51244
51526
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
51245
51527
|
filePath(scope, sessionId) {
|
|
51246
|
-
return
|
|
51528
|
+
return import_node_path27.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
51247
51529
|
}
|
|
51248
51530
|
cacheKey(scope, sessionId) {
|
|
51249
51531
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -51252,7 +51534,7 @@ var GroupFileStore = class {
|
|
|
51252
51534
|
readFile(scope, sessionId) {
|
|
51253
51535
|
const file = this.filePath(scope, sessionId);
|
|
51254
51536
|
try {
|
|
51255
|
-
const raw =
|
|
51537
|
+
const raw = import_node_fs27.default.readFileSync(file, "utf8");
|
|
51256
51538
|
const parsed = JSON.parse(raw);
|
|
51257
51539
|
if (!Array.isArray(parsed)) {
|
|
51258
51540
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -51278,10 +51560,10 @@ var GroupFileStore = class {
|
|
|
51278
51560
|
}
|
|
51279
51561
|
writeFile(scope, sessionId, entries) {
|
|
51280
51562
|
const file = this.filePath(scope, sessionId);
|
|
51281
|
-
|
|
51563
|
+
import_node_fs27.default.mkdirSync(import_node_path27.default.dirname(file), { recursive: true });
|
|
51282
51564
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
51283
|
-
|
|
51284
|
-
|
|
51565
|
+
import_node_fs27.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
51566
|
+
import_node_fs27.default.renameSync(tmp, file);
|
|
51285
51567
|
}
|
|
51286
51568
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
51287
51569
|
list(scope, sessionId) {
|
|
@@ -51317,7 +51599,7 @@ var GroupFileStore = class {
|
|
|
51317
51599
|
entries[idx] = next;
|
|
51318
51600
|
} else {
|
|
51319
51601
|
next = {
|
|
51320
|
-
id: `gf-${
|
|
51602
|
+
id: `gf-${import_node_crypto8.default.randomBytes(6).toString("base64url")}`,
|
|
51321
51603
|
relPath: input.relPath,
|
|
51322
51604
|
from: input.from,
|
|
51323
51605
|
label: input.label,
|
|
@@ -51367,10 +51649,10 @@ var GroupFileStore = class {
|
|
|
51367
51649
|
};
|
|
51368
51650
|
|
|
51369
51651
|
// src/discovery/state-file.ts
|
|
51370
|
-
var
|
|
51371
|
-
var
|
|
51652
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
51653
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
51372
51654
|
function defaultStateFilePath(dataDir) {
|
|
51373
|
-
return
|
|
51655
|
+
return import_node_path28.default.join(dataDir, "state.json");
|
|
51374
51656
|
}
|
|
51375
51657
|
function isPidAlive(pid) {
|
|
51376
51658
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -51392,7 +51674,7 @@ var StateFileManager = class {
|
|
|
51392
51674
|
}
|
|
51393
51675
|
read() {
|
|
51394
51676
|
try {
|
|
51395
|
-
const raw =
|
|
51677
|
+
const raw = import_node_fs28.default.readFileSync(this.file, "utf8");
|
|
51396
51678
|
const parsed = JSON.parse(raw);
|
|
51397
51679
|
return parsed;
|
|
51398
51680
|
} catch {
|
|
@@ -51406,20 +51688,20 @@ var StateFileManager = class {
|
|
|
51406
51688
|
return { status: "stale", existing };
|
|
51407
51689
|
}
|
|
51408
51690
|
write(state) {
|
|
51409
|
-
|
|
51691
|
+
import_node_fs28.default.mkdirSync(import_node_path28.default.dirname(this.file), { recursive: true });
|
|
51410
51692
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
51411
|
-
|
|
51412
|
-
|
|
51693
|
+
import_node_fs28.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
51694
|
+
import_node_fs28.default.renameSync(tmp, this.file);
|
|
51413
51695
|
if (process.platform !== "win32") {
|
|
51414
51696
|
try {
|
|
51415
|
-
|
|
51697
|
+
import_node_fs28.default.chmodSync(this.file, 384);
|
|
51416
51698
|
} catch {
|
|
51417
51699
|
}
|
|
51418
51700
|
}
|
|
51419
51701
|
}
|
|
51420
51702
|
delete() {
|
|
51421
51703
|
try {
|
|
51422
|
-
|
|
51704
|
+
import_node_fs28.default.unlinkSync(this.file);
|
|
51423
51705
|
} catch {
|
|
51424
51706
|
}
|
|
51425
51707
|
}
|
|
@@ -51434,14 +51716,14 @@ function readDaemonSourceFromEnv(env = process.env) {
|
|
|
51434
51716
|
}
|
|
51435
51717
|
|
|
51436
51718
|
// src/tunnel/tunnel-manager.ts
|
|
51437
|
-
var
|
|
51438
|
-
var
|
|
51439
|
-
var
|
|
51719
|
+
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
51720
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
51721
|
+
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
51440
51722
|
var import_node_child_process9 = require("child_process");
|
|
51441
51723
|
|
|
51442
51724
|
// src/tunnel/tunnel-store.ts
|
|
51443
|
-
var
|
|
51444
|
-
var
|
|
51725
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
51726
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
51445
51727
|
var TunnelStore = class {
|
|
51446
51728
|
constructor(filePath) {
|
|
51447
51729
|
this.filePath = filePath;
|
|
@@ -51449,7 +51731,7 @@ var TunnelStore = class {
|
|
|
51449
51731
|
filePath;
|
|
51450
51732
|
async get() {
|
|
51451
51733
|
try {
|
|
51452
|
-
const raw = await
|
|
51734
|
+
const raw = await import_node_fs29.default.promises.readFile(this.filePath, "utf8");
|
|
51453
51735
|
const obj = JSON.parse(raw);
|
|
51454
51736
|
if (!isPersistedTunnel(obj)) return null;
|
|
51455
51737
|
return obj;
|
|
@@ -51460,22 +51742,22 @@ var TunnelStore = class {
|
|
|
51460
51742
|
}
|
|
51461
51743
|
}
|
|
51462
51744
|
async set(v2) {
|
|
51463
|
-
const dir =
|
|
51464
|
-
await
|
|
51745
|
+
const dir = import_node_path29.default.dirname(this.filePath);
|
|
51746
|
+
await import_node_fs29.default.promises.mkdir(dir, { recursive: true });
|
|
51465
51747
|
const data = JSON.stringify(v2, null, 2);
|
|
51466
51748
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
51467
|
-
await
|
|
51749
|
+
await import_node_fs29.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
51468
51750
|
if (process.platform !== "win32") {
|
|
51469
51751
|
try {
|
|
51470
|
-
await
|
|
51752
|
+
await import_node_fs29.default.promises.chmod(tmp, 384);
|
|
51471
51753
|
} catch {
|
|
51472
51754
|
}
|
|
51473
51755
|
}
|
|
51474
|
-
await
|
|
51756
|
+
await import_node_fs29.default.promises.rename(tmp, this.filePath);
|
|
51475
51757
|
}
|
|
51476
51758
|
async clear() {
|
|
51477
51759
|
try {
|
|
51478
|
-
await
|
|
51760
|
+
await import_node_fs29.default.promises.unlink(this.filePath);
|
|
51479
51761
|
} catch (err) {
|
|
51480
51762
|
const code = err?.code;
|
|
51481
51763
|
if (code !== "ENOENT") throw err;
|
|
@@ -51570,9 +51852,9 @@ function escape(v2) {
|
|
|
51570
51852
|
}
|
|
51571
51853
|
|
|
51572
51854
|
// src/tunnel/frpc-binary.ts
|
|
51573
|
-
var
|
|
51855
|
+
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
51574
51856
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
51575
|
-
var
|
|
51857
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
51576
51858
|
var import_node_child_process7 = require("child_process");
|
|
51577
51859
|
var import_node_stream3 = require("stream");
|
|
51578
51860
|
var import_promises4 = require("stream/promises");
|
|
@@ -51604,20 +51886,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
51604
51886
|
}
|
|
51605
51887
|
async function ensureFrpcBinary(opts) {
|
|
51606
51888
|
if (opts.override) {
|
|
51607
|
-
if (!
|
|
51889
|
+
if (!import_node_fs30.default.existsSync(opts.override)) {
|
|
51608
51890
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
51609
51891
|
}
|
|
51610
51892
|
return opts.override;
|
|
51611
51893
|
}
|
|
51612
51894
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
51613
51895
|
const platform = opts.platform ?? detectPlatform();
|
|
51614
|
-
const binDir =
|
|
51615
|
-
|
|
51896
|
+
const binDir = import_node_path30.default.join(opts.dataDir, "bin");
|
|
51897
|
+
import_node_fs30.default.mkdirSync(binDir, { recursive: true });
|
|
51616
51898
|
cleanupStaleArtifacts(binDir);
|
|
51617
|
-
const stableBin =
|
|
51618
|
-
if (
|
|
51899
|
+
const stableBin = import_node_path30.default.join(binDir, "frpc");
|
|
51900
|
+
if (import_node_fs30.default.existsSync(stableBin)) return stableBin;
|
|
51619
51901
|
const partialBin = `${stableBin}.partial`;
|
|
51620
|
-
const tarballPath =
|
|
51902
|
+
const tarballPath = import_node_path30.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
51621
51903
|
try {
|
|
51622
51904
|
const url = frpcDownloadUrl(version2, platform);
|
|
51623
51905
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -51626,8 +51908,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
51626
51908
|
} else {
|
|
51627
51909
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
51628
51910
|
}
|
|
51629
|
-
|
|
51630
|
-
|
|
51911
|
+
import_node_fs30.default.chmodSync(partialBin, 493);
|
|
51912
|
+
import_node_fs30.default.renameSync(partialBin, stableBin);
|
|
51631
51913
|
} finally {
|
|
51632
51914
|
safeUnlink(tarballPath);
|
|
51633
51915
|
safeUnlink(partialBin);
|
|
@@ -51637,15 +51919,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
51637
51919
|
function cleanupStaleArtifacts(binDir) {
|
|
51638
51920
|
let entries;
|
|
51639
51921
|
try {
|
|
51640
|
-
entries =
|
|
51922
|
+
entries = import_node_fs30.default.readdirSync(binDir);
|
|
51641
51923
|
} catch {
|
|
51642
51924
|
return;
|
|
51643
51925
|
}
|
|
51644
51926
|
for (const name of entries) {
|
|
51645
51927
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
51646
|
-
const full =
|
|
51928
|
+
const full = import_node_path30.default.join(binDir, name);
|
|
51647
51929
|
try {
|
|
51648
|
-
|
|
51930
|
+
import_node_fs30.default.rmSync(full, { recursive: true, force: true });
|
|
51649
51931
|
} catch {
|
|
51650
51932
|
}
|
|
51651
51933
|
}
|
|
@@ -51653,7 +51935,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
51653
51935
|
}
|
|
51654
51936
|
function safeUnlink(p2) {
|
|
51655
51937
|
try {
|
|
51656
|
-
|
|
51938
|
+
import_node_fs30.default.unlinkSync(p2);
|
|
51657
51939
|
} catch {
|
|
51658
51940
|
}
|
|
51659
51941
|
}
|
|
@@ -51664,13 +51946,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
51664
51946
|
if (!res.ok || !res.body) {
|
|
51665
51947
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
51666
51948
|
}
|
|
51667
|
-
const out =
|
|
51949
|
+
const out = import_node_fs30.default.createWriteStream(dest);
|
|
51668
51950
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
51669
51951
|
await (0, import_promises4.pipeline)(nodeStream, out);
|
|
51670
51952
|
}
|
|
51671
51953
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
51672
|
-
const work =
|
|
51673
|
-
|
|
51954
|
+
const work = import_node_path30.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
51955
|
+
import_node_fs30.default.mkdirSync(work, { recursive: true });
|
|
51674
51956
|
try {
|
|
51675
51957
|
await new Promise((resolve6, reject) => {
|
|
51676
51958
|
const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -51678,32 +51960,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
51678
51960
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
51679
51961
|
});
|
|
51680
51962
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
51681
|
-
const src =
|
|
51682
|
-
if (!
|
|
51963
|
+
const src = import_node_path30.default.join(work, dirName, "frpc");
|
|
51964
|
+
if (!import_node_fs30.default.existsSync(src)) {
|
|
51683
51965
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
51684
51966
|
}
|
|
51685
|
-
|
|
51967
|
+
import_node_fs30.default.copyFileSync(src, destBin);
|
|
51686
51968
|
} finally {
|
|
51687
|
-
|
|
51969
|
+
import_node_fs30.default.rmSync(work, { recursive: true, force: true });
|
|
51688
51970
|
}
|
|
51689
51971
|
}
|
|
51690
51972
|
|
|
51691
51973
|
// src/tunnel/frpc-process.ts
|
|
51692
|
-
var
|
|
51693
|
-
var
|
|
51974
|
+
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
51975
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
51694
51976
|
var import_node_child_process8 = require("child_process");
|
|
51695
51977
|
function frpcPidFilePath(dataDir) {
|
|
51696
|
-
return
|
|
51978
|
+
return import_node_path31.default.join(dataDir, "frpc.pid");
|
|
51697
51979
|
}
|
|
51698
51980
|
function writeFrpcPid(dataDir, pid) {
|
|
51699
51981
|
try {
|
|
51700
|
-
|
|
51982
|
+
import_node_fs31.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
51701
51983
|
} catch {
|
|
51702
51984
|
}
|
|
51703
51985
|
}
|
|
51704
51986
|
function clearFrpcPid(dataDir) {
|
|
51705
51987
|
try {
|
|
51706
|
-
|
|
51988
|
+
import_node_fs31.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
51707
51989
|
} catch {
|
|
51708
51990
|
}
|
|
51709
51991
|
}
|
|
@@ -51719,7 +52001,7 @@ function defaultIsPidAlive(pid) {
|
|
|
51719
52001
|
}
|
|
51720
52002
|
function defaultReadPidFile(file) {
|
|
51721
52003
|
try {
|
|
51722
|
-
return
|
|
52004
|
+
return import_node_fs31.default.readFileSync(file, "utf8");
|
|
51723
52005
|
} catch {
|
|
51724
52006
|
return null;
|
|
51725
52007
|
}
|
|
@@ -51735,7 +52017,7 @@ function defaultSleep(ms) {
|
|
|
51735
52017
|
}
|
|
51736
52018
|
async function killStaleFrpc(deps) {
|
|
51737
52019
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
51738
|
-
const tomlPath =
|
|
52020
|
+
const tomlPath = import_node_path31.default.join(deps.dataDir, "frpc.toml");
|
|
51739
52021
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
51740
52022
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
51741
52023
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -51759,7 +52041,7 @@ async function killStaleFrpc(deps) {
|
|
|
51759
52041
|
}
|
|
51760
52042
|
if (victims.size === 0) {
|
|
51761
52043
|
try {
|
|
51762
|
-
|
|
52044
|
+
import_node_fs31.default.unlinkSync(pidFile);
|
|
51763
52045
|
} catch {
|
|
51764
52046
|
}
|
|
51765
52047
|
return;
|
|
@@ -51770,7 +52052,7 @@ async function killStaleFrpc(deps) {
|
|
|
51770
52052
|
}
|
|
51771
52053
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
51772
52054
|
try {
|
|
51773
|
-
|
|
52055
|
+
import_node_fs31.default.unlinkSync(pidFile);
|
|
51774
52056
|
} catch {
|
|
51775
52057
|
}
|
|
51776
52058
|
}
|
|
@@ -51807,7 +52089,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
51807
52089
|
var TunnelManager = class {
|
|
51808
52090
|
constructor(deps) {
|
|
51809
52091
|
this.deps = deps;
|
|
51810
|
-
this.store = deps.store ?? new TunnelStore(
|
|
52092
|
+
this.store = deps.store ?? new TunnelStore(import_node_path32.default.join(deps.dataDir, "tunnel.json"));
|
|
51811
52093
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
51812
52094
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
51813
52095
|
}
|
|
@@ -51934,8 +52216,8 @@ var TunnelManager = class {
|
|
|
51934
52216
|
dataDir: this.deps.dataDir,
|
|
51935
52217
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
51936
52218
|
});
|
|
51937
|
-
const tomlPath =
|
|
51938
|
-
const proxyName = `clawd-${t.subdomain}-${localPort}-${
|
|
52219
|
+
const tomlPath = import_node_path32.default.join(this.deps.dataDir, "frpc.toml");
|
|
52220
|
+
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto9.default.randomBytes(3).toString("hex")}`;
|
|
51939
52221
|
const toml = buildFrpcToml({
|
|
51940
52222
|
serverAddr: t.frpsHost,
|
|
51941
52223
|
serverPort: t.frpsPort,
|
|
@@ -51945,12 +52227,12 @@ var TunnelManager = class {
|
|
|
51945
52227
|
localPort,
|
|
51946
52228
|
logLevel: "info"
|
|
51947
52229
|
});
|
|
51948
|
-
await
|
|
52230
|
+
await import_node_fs32.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
51949
52231
|
const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
|
|
51950
52232
|
stdio: ["ignore", "pipe", "pipe"]
|
|
51951
52233
|
});
|
|
51952
|
-
const logFilePath =
|
|
51953
|
-
const logStream =
|
|
52234
|
+
const logFilePath = import_node_path32.default.join(this.deps.dataDir, "frpc.log");
|
|
52235
|
+
const logStream = import_node_fs32.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
51954
52236
|
logStream.on("error", () => {
|
|
51955
52237
|
});
|
|
51956
52238
|
const tee = (chunk) => {
|
|
@@ -52033,27 +52315,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
52033
52315
|
|
|
52034
52316
|
// src/tunnel/device-key.ts
|
|
52035
52317
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
52036
|
-
var
|
|
52037
|
-
var
|
|
52318
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
52319
|
+
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
52038
52320
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
52039
52321
|
function deriveStableDeviceKey(opts = {}) {
|
|
52040
52322
|
const hostname = opts.hostname ?? import_node_os13.default.hostname();
|
|
52041
52323
|
const uid = opts.uid ?? (typeof import_node_os13.default.userInfo === "function" ? import_node_os13.default.userInfo().uid : 0);
|
|
52042
52324
|
const home = opts.home ?? import_node_os13.default.homedir();
|
|
52043
|
-
const defaultDataDir =
|
|
52044
|
-
const normalizedDataDir = opts.dataDir ?
|
|
52325
|
+
const defaultDataDir = import_node_path33.default.resolve(import_node_path33.default.join(home, ".clawd"));
|
|
52326
|
+
const normalizedDataDir = opts.dataDir ? import_node_path33.default.resolve(opts.dataDir) : null;
|
|
52045
52327
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
52046
52328
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
52047
|
-
return
|
|
52329
|
+
return import_node_crypto10.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
52048
52330
|
}
|
|
52049
52331
|
|
|
52050
52332
|
// src/auth-store.ts
|
|
52051
|
-
var
|
|
52052
|
-
var
|
|
52053
|
-
var
|
|
52333
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
52334
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
52335
|
+
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
52054
52336
|
var AUTH_FILE_NAME = "auth.json";
|
|
52055
52337
|
function authFilePath(dataDir) {
|
|
52056
|
-
return
|
|
52338
|
+
return import_node_path34.default.join(dataDir, AUTH_FILE_NAME);
|
|
52057
52339
|
}
|
|
52058
52340
|
function loadOrCreateAuthFile(opts) {
|
|
52059
52341
|
const file = authFilePath(opts.dataDir);
|
|
@@ -52061,10 +52343,11 @@ function loadOrCreateAuthFile(opts) {
|
|
|
52061
52343
|
const genId = opts.genOwnerPrincipalId ?? defaultGenerateOwnerPrincipalId;
|
|
52062
52344
|
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
52063
52345
|
const existing = readAuthFile(file);
|
|
52064
|
-
if (existing && existing.token && existing.signSecret && existing.ownerPrincipalId && existing.deviceId && existing.deviceId === existing.ownerPrincipalId) {
|
|
52346
|
+
if (existing && existing.token && existing.signSecret && existing.visitorTokenSecret && existing.ownerPrincipalId && existing.deviceId && existing.deviceId === existing.ownerPrincipalId) {
|
|
52065
52347
|
return {
|
|
52066
52348
|
token: existing.token,
|
|
52067
52349
|
signSecret: existing.signSecret,
|
|
52350
|
+
visitorTokenSecret: existing.visitorTokenSecret,
|
|
52068
52351
|
ownerPrincipalId: existing.ownerPrincipalId,
|
|
52069
52352
|
deviceId: existing.deviceId,
|
|
52070
52353
|
createdAt: existing.createdAt ?? (/* @__PURE__ */ new Date(0)).toISOString()
|
|
@@ -52072,22 +52355,23 @@ function loadOrCreateAuthFile(opts) {
|
|
|
52072
52355
|
}
|
|
52073
52356
|
const token = existing?.token || generate();
|
|
52074
52357
|
const signSecret = existing?.signSecret || generate();
|
|
52358
|
+
const visitorTokenSecret = existing?.visitorTokenSecret || generate();
|
|
52075
52359
|
const ownerPrincipalId = existing?.ownerPrincipalId || genId();
|
|
52076
52360
|
const deviceId = ownerPrincipalId;
|
|
52077
52361
|
const createdAt = existing?.createdAt || now().toISOString();
|
|
52078
|
-
const next = { token, signSecret, ownerPrincipalId, deviceId, createdAt };
|
|
52362
|
+
const next = { token, signSecret, visitorTokenSecret, ownerPrincipalId, deviceId, createdAt };
|
|
52079
52363
|
writeAuthFile(file, next);
|
|
52080
52364
|
return next;
|
|
52081
52365
|
}
|
|
52082
52366
|
function defaultGenerateToken() {
|
|
52083
|
-
return
|
|
52367
|
+
return import_node_crypto11.default.randomBytes(32).toString("base64url");
|
|
52084
52368
|
}
|
|
52085
52369
|
function defaultGenerateOwnerPrincipalId() {
|
|
52086
|
-
return `owner-${
|
|
52370
|
+
return `owner-${import_node_crypto11.default.randomUUID()}`;
|
|
52087
52371
|
}
|
|
52088
52372
|
function readAuthFile(file) {
|
|
52089
52373
|
try {
|
|
52090
|
-
const raw =
|
|
52374
|
+
const raw = import_node_fs33.default.readFileSync(file, "utf8");
|
|
52091
52375
|
const parsed = JSON.parse(raw);
|
|
52092
52376
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
52093
52377
|
return null;
|
|
@@ -52095,6 +52379,7 @@ function readAuthFile(file) {
|
|
|
52095
52379
|
return {
|
|
52096
52380
|
token: parsed.token,
|
|
52097
52381
|
signSecret: typeof parsed.signSecret === "string" && parsed.signSecret.length > 0 ? parsed.signSecret : void 0,
|
|
52382
|
+
visitorTokenSecret: typeof parsed.visitorTokenSecret === "string" && parsed.visitorTokenSecret.length > 0 ? parsed.visitorTokenSecret : void 0,
|
|
52098
52383
|
ownerPrincipalId: typeof parsed.ownerPrincipalId === "string" && parsed.ownerPrincipalId.length > 0 ? parsed.ownerPrincipalId : void 0,
|
|
52099
52384
|
deviceId: typeof parsed.deviceId === "string" && parsed.deviceId.length > 0 ? parsed.deviceId : void 0,
|
|
52100
52385
|
createdAt: typeof parsed.createdAt === "string" ? parsed.createdAt : void 0
|
|
@@ -52106,25 +52391,25 @@ function readAuthFile(file) {
|
|
|
52106
52391
|
}
|
|
52107
52392
|
}
|
|
52108
52393
|
function writeAuthFile(file, content) {
|
|
52109
|
-
|
|
52110
|
-
|
|
52394
|
+
import_node_fs33.default.mkdirSync(import_node_path34.default.dirname(file), { recursive: true });
|
|
52395
|
+
import_node_fs33.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
52111
52396
|
try {
|
|
52112
|
-
|
|
52397
|
+
import_node_fs33.default.chmodSync(file, 384);
|
|
52113
52398
|
} catch {
|
|
52114
52399
|
}
|
|
52115
52400
|
}
|
|
52116
52401
|
|
|
52117
52402
|
// src/owner-profile.ts
|
|
52118
|
-
var
|
|
52403
|
+
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
52119
52404
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
52120
|
-
var
|
|
52405
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
52121
52406
|
var PROFILE_FILENAME = "profile.json";
|
|
52122
52407
|
function loadOwnerDisplayName(dataDir) {
|
|
52123
52408
|
const fallback = import_node_os14.default.userInfo().username;
|
|
52124
|
-
const profilePath =
|
|
52409
|
+
const profilePath = import_node_path35.default.join(dataDir, PROFILE_FILENAME);
|
|
52125
52410
|
let raw;
|
|
52126
52411
|
try {
|
|
52127
|
-
raw =
|
|
52412
|
+
raw = import_node_fs34.default.readFileSync(profilePath, "utf8");
|
|
52128
52413
|
} catch {
|
|
52129
52414
|
return fallback;
|
|
52130
52415
|
}
|
|
@@ -52147,18 +52432,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
52147
52432
|
}
|
|
52148
52433
|
|
|
52149
52434
|
// src/feishu-auth/owner-identity-store.ts
|
|
52150
|
-
var
|
|
52151
|
-
var
|
|
52435
|
+
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
52436
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
52152
52437
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
52153
52438
|
var OwnerIdentityStore = class {
|
|
52154
52439
|
file;
|
|
52155
52440
|
constructor(dataDir) {
|
|
52156
|
-
this.file =
|
|
52441
|
+
this.file = import_node_path36.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
52157
52442
|
}
|
|
52158
52443
|
read() {
|
|
52159
52444
|
let raw;
|
|
52160
52445
|
try {
|
|
52161
|
-
raw =
|
|
52446
|
+
raw = import_node_fs35.default.readFileSync(this.file, "utf8");
|
|
52162
52447
|
} catch {
|
|
52163
52448
|
return null;
|
|
52164
52449
|
}
|
|
@@ -52186,16 +52471,16 @@ var OwnerIdentityStore = class {
|
|
|
52186
52471
|
};
|
|
52187
52472
|
}
|
|
52188
52473
|
write(record) {
|
|
52189
|
-
|
|
52190
|
-
|
|
52474
|
+
import_node_fs35.default.mkdirSync(import_node_path36.default.dirname(this.file), { recursive: true });
|
|
52475
|
+
import_node_fs35.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
52191
52476
|
try {
|
|
52192
|
-
|
|
52477
|
+
import_node_fs35.default.chmodSync(this.file, 384);
|
|
52193
52478
|
} catch {
|
|
52194
52479
|
}
|
|
52195
52480
|
}
|
|
52196
52481
|
clear() {
|
|
52197
52482
|
try {
|
|
52198
|
-
|
|
52483
|
+
import_node_fs35.default.unlinkSync(this.file);
|
|
52199
52484
|
} catch (err) {
|
|
52200
52485
|
const code = err?.code;
|
|
52201
52486
|
if (code !== "ENOENT") throw err;
|
|
@@ -52204,7 +52489,7 @@ var OwnerIdentityStore = class {
|
|
|
52204
52489
|
};
|
|
52205
52490
|
|
|
52206
52491
|
// src/feishu-auth/login-flow.ts
|
|
52207
|
-
var
|
|
52492
|
+
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
52208
52493
|
var STATE_TTL_MS = 5 * 60 * 1e3;
|
|
52209
52494
|
var LoginFlow = class {
|
|
52210
52495
|
constructor(deps) {
|
|
@@ -52213,7 +52498,7 @@ var LoginFlow = class {
|
|
|
52213
52498
|
deps;
|
|
52214
52499
|
pendingStates = /* @__PURE__ */ new Map();
|
|
52215
52500
|
start() {
|
|
52216
|
-
const state =
|
|
52501
|
+
const state = import_node_crypto12.default.randomBytes(16).toString("base64url");
|
|
52217
52502
|
const now = (this.deps.now ?? Date.now)();
|
|
52218
52503
|
this.pendingStates.set(state, now);
|
|
52219
52504
|
this.gcExpired(now);
|
|
@@ -52316,9 +52601,9 @@ var CentralClientError = class extends Error {
|
|
|
52316
52601
|
code;
|
|
52317
52602
|
cause;
|
|
52318
52603
|
};
|
|
52319
|
-
async function centralRequest(opts,
|
|
52604
|
+
async function centralRequest(opts, path66, init) {
|
|
52320
52605
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
52321
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
52606
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path66}`;
|
|
52322
52607
|
const ctrl = new AbortController();
|
|
52323
52608
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
52324
52609
|
let res;
|
|
@@ -52411,7 +52696,7 @@ async function centralListDevices(opts) {
|
|
|
52411
52696
|
}
|
|
52412
52697
|
|
|
52413
52698
|
// src/feishu-auth/verify-token.ts
|
|
52414
|
-
var
|
|
52699
|
+
var crypto14 = __toESM(require("crypto"), 1);
|
|
52415
52700
|
var CONNECT_TOKEN_PREFIX = "clawdtk1";
|
|
52416
52701
|
function verifyConnectToken(args) {
|
|
52417
52702
|
const now = args.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
@@ -52423,7 +52708,7 @@ function verifyConnectToken(args) {
|
|
|
52423
52708
|
const data = `${prefix}.${payloadB64}`;
|
|
52424
52709
|
let signatureValid = false;
|
|
52425
52710
|
try {
|
|
52426
|
-
signatureValid =
|
|
52711
|
+
signatureValid = crypto14.verify(
|
|
52427
52712
|
null,
|
|
52428
52713
|
Buffer.from(data, "utf8"),
|
|
52429
52714
|
args.publicKeyPem,
|
|
@@ -52460,8 +52745,8 @@ function verifyConnectToken(args) {
|
|
|
52460
52745
|
}
|
|
52461
52746
|
|
|
52462
52747
|
// src/feishu-auth/server-key.ts
|
|
52463
|
-
var
|
|
52464
|
-
var
|
|
52748
|
+
var fs45 = __toESM(require("fs"), 1);
|
|
52749
|
+
var path45 = __toESM(require("path"), 1);
|
|
52465
52750
|
var FILE_NAME2 = "server-signing-key.json";
|
|
52466
52751
|
var ServerKeyStore = class {
|
|
52467
52752
|
constructor(dataDir) {
|
|
@@ -52469,12 +52754,12 @@ var ServerKeyStore = class {
|
|
|
52469
52754
|
}
|
|
52470
52755
|
dataDir;
|
|
52471
52756
|
filePath() {
|
|
52472
|
-
return
|
|
52757
|
+
return path45.join(this.dataDir, FILE_NAME2);
|
|
52473
52758
|
}
|
|
52474
52759
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
52475
52760
|
read() {
|
|
52476
52761
|
try {
|
|
52477
|
-
const raw =
|
|
52762
|
+
const raw = fs45.readFileSync(this.filePath(), "utf8");
|
|
52478
52763
|
const parsed = JSON.parse(raw);
|
|
52479
52764
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
52480
52765
|
return parsed.publicKeyPem;
|
|
@@ -52489,12 +52774,12 @@ var ServerKeyStore = class {
|
|
|
52489
52774
|
publicKeyPem,
|
|
52490
52775
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
52491
52776
|
};
|
|
52492
|
-
|
|
52493
|
-
|
|
52777
|
+
fs45.mkdirSync(this.dataDir, { recursive: true });
|
|
52778
|
+
fs45.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
52494
52779
|
}
|
|
52495
52780
|
clear() {
|
|
52496
52781
|
try {
|
|
52497
|
-
|
|
52782
|
+
fs45.unlinkSync(this.filePath());
|
|
52498
52783
|
} catch {
|
|
52499
52784
|
}
|
|
52500
52785
|
}
|
|
@@ -52507,12 +52792,12 @@ init_protocol();
|
|
|
52507
52792
|
init_protocol();
|
|
52508
52793
|
|
|
52509
52794
|
// src/session/fork.ts
|
|
52510
|
-
var
|
|
52795
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
52511
52796
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
52512
|
-
var
|
|
52797
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
52513
52798
|
init_claude_history();
|
|
52514
52799
|
function readJsonlEntries(file) {
|
|
52515
|
-
const raw =
|
|
52800
|
+
const raw = import_node_fs36.default.readFileSync(file, "utf8");
|
|
52516
52801
|
const out = [];
|
|
52517
52802
|
for (const line of raw.split("\n")) {
|
|
52518
52803
|
const t = line.trim();
|
|
@@ -52525,10 +52810,10 @@ function readJsonlEntries(file) {
|
|
|
52525
52810
|
return out;
|
|
52526
52811
|
}
|
|
52527
52812
|
function forkSession(input) {
|
|
52528
|
-
const baseDir = input.baseDir ??
|
|
52529
|
-
const projectDir =
|
|
52530
|
-
const sourceFile =
|
|
52531
|
-
if (!
|
|
52813
|
+
const baseDir = input.baseDir ?? import_node_path37.default.join(import_node_os15.default.homedir(), ".claude");
|
|
52814
|
+
const projectDir = import_node_path37.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
52815
|
+
const sourceFile = import_node_path37.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
52816
|
+
if (!import_node_fs36.default.existsSync(sourceFile)) {
|
|
52532
52817
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
52533
52818
|
}
|
|
52534
52819
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -52558,9 +52843,9 @@ function forkSession(input) {
|
|
|
52558
52843
|
}
|
|
52559
52844
|
forkedLines.push(JSON.stringify(forked));
|
|
52560
52845
|
}
|
|
52561
|
-
const forkedFilePath =
|
|
52562
|
-
|
|
52563
|
-
|
|
52846
|
+
const forkedFilePath = import_node_path37.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
52847
|
+
import_node_fs36.default.mkdirSync(projectDir, { recursive: true });
|
|
52848
|
+
import_node_fs36.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
52564
52849
|
return { forkedToolSessionId, forkedFilePath };
|
|
52565
52850
|
}
|
|
52566
52851
|
|
|
@@ -52912,7 +53197,7 @@ function buildPermissionHandlers(deps) {
|
|
|
52912
53197
|
}
|
|
52913
53198
|
|
|
52914
53199
|
// src/handlers/history.ts
|
|
52915
|
-
var
|
|
53200
|
+
var path48 = __toESM(require("path"), 1);
|
|
52916
53201
|
init_protocol();
|
|
52917
53202
|
|
|
52918
53203
|
// src/session/recent-dirs.ts
|
|
@@ -52930,7 +53215,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
52930
53215
|
}
|
|
52931
53216
|
|
|
52932
53217
|
// src/permission/persona-paths.ts
|
|
52933
|
-
var
|
|
53218
|
+
var path47 = __toESM(require("path"), 1);
|
|
52934
53219
|
function getAllowedPersonaIds(grants, action) {
|
|
52935
53220
|
const ids = /* @__PURE__ */ new Set();
|
|
52936
53221
|
for (const g2 of grants) {
|
|
@@ -52943,42 +53228,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
52943
53228
|
return ids;
|
|
52944
53229
|
}
|
|
52945
53230
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
52946
|
-
const target =
|
|
53231
|
+
const target = path47.resolve(absPath);
|
|
52947
53232
|
if (userWorkDir) {
|
|
52948
|
-
const u =
|
|
52949
|
-
const usep = u.endsWith(
|
|
53233
|
+
const u = path47.resolve(userWorkDir);
|
|
53234
|
+
const usep = u.endsWith(path47.sep) ? "" : path47.sep;
|
|
52950
53235
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
52951
53236
|
}
|
|
52952
|
-
const root =
|
|
52953
|
-
const sep3 = root.endsWith(
|
|
53237
|
+
const root = path47.resolve(personaRoot);
|
|
53238
|
+
const sep3 = root.endsWith(path47.sep) ? "" : path47.sep;
|
|
52954
53239
|
if (!target.startsWith(root + sep3)) return false;
|
|
52955
|
-
const rel =
|
|
53240
|
+
const rel = path47.relative(root, target);
|
|
52956
53241
|
if (!rel || rel.startsWith("..")) return false;
|
|
52957
|
-
const personaId = rel.split(
|
|
53242
|
+
const personaId = rel.split(path47.sep)[0];
|
|
52958
53243
|
if (!personaId) return false;
|
|
52959
53244
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
52960
53245
|
if (allowed === "*") return true;
|
|
52961
53246
|
return allowed.has(personaId);
|
|
52962
53247
|
}
|
|
52963
53248
|
function personaIdFromPath(absPath, personaRoot) {
|
|
52964
|
-
const root =
|
|
52965
|
-
const target =
|
|
52966
|
-
const sep3 = root.endsWith(
|
|
53249
|
+
const root = path47.resolve(personaRoot);
|
|
53250
|
+
const target = path47.resolve(absPath);
|
|
53251
|
+
const sep3 = root.endsWith(path47.sep) ? "" : path47.sep;
|
|
52967
53252
|
if (!target.startsWith(root + sep3)) return null;
|
|
52968
|
-
const rel =
|
|
53253
|
+
const rel = path47.relative(root, target);
|
|
52969
53254
|
if (!rel || rel.startsWith("..")) return null;
|
|
52970
|
-
const id = rel.split(
|
|
53255
|
+
const id = rel.split(path47.sep)[0];
|
|
52971
53256
|
return id || null;
|
|
52972
53257
|
}
|
|
52973
53258
|
function isPathWithin(dir, absPath) {
|
|
52974
|
-
const d =
|
|
52975
|
-
const t =
|
|
52976
|
-
const sep3 = d.endsWith(
|
|
53259
|
+
const d = path47.resolve(dir);
|
|
53260
|
+
const t = path47.resolve(absPath);
|
|
53261
|
+
const sep3 = d.endsWith(path47.sep) ? "" : path47.sep;
|
|
52977
53262
|
return t === d || t.startsWith(d + sep3);
|
|
52978
53263
|
}
|
|
52979
53264
|
function isPathInGuestBoundary(personaRoot, personaId, userWorkDir, absPath) {
|
|
52980
53265
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
52981
|
-
return personaIdFromPath(
|
|
53266
|
+
return personaIdFromPath(path47.resolve(absPath), personaRoot) === personaId;
|
|
52982
53267
|
}
|
|
52983
53268
|
|
|
52984
53269
|
// src/handlers/history.ts
|
|
@@ -53004,7 +53289,7 @@ function buildHistoryHandlers(deps) {
|
|
|
53004
53289
|
if (!pid) return false;
|
|
53005
53290
|
return isGuestPathAllowed(
|
|
53006
53291
|
ctx.grants,
|
|
53007
|
-
|
|
53292
|
+
path48.join(personaRoot, pid),
|
|
53008
53293
|
personaRoot,
|
|
53009
53294
|
"read",
|
|
53010
53295
|
userWorkDir
|
|
@@ -53016,7 +53301,7 @@ function buildHistoryHandlers(deps) {
|
|
|
53016
53301
|
};
|
|
53017
53302
|
const list = async (frame, _client, ctx) => {
|
|
53018
53303
|
const args = HistoryListArgs.parse(frame);
|
|
53019
|
-
assertGuestPath(ctx,
|
|
53304
|
+
assertGuestPath(ctx, path48.resolve(args.projectPath), personaRoot, "history:list");
|
|
53020
53305
|
const sessions = await history.listSessions(args);
|
|
53021
53306
|
return { response: { type: "history:list", sessions } };
|
|
53022
53307
|
};
|
|
@@ -53048,13 +53333,13 @@ function buildHistoryHandlers(deps) {
|
|
|
53048
53333
|
};
|
|
53049
53334
|
const subagents = async (frame, _client, ctx) => {
|
|
53050
53335
|
const args = HistorySubagentsArgs.parse(frame);
|
|
53051
|
-
assertGuestPath(ctx,
|
|
53336
|
+
assertGuestPath(ctx, path48.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
53052
53337
|
const subs = await history.listSubagents(args);
|
|
53053
53338
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
53054
53339
|
};
|
|
53055
53340
|
const subagentRead = async (frame, _client, ctx) => {
|
|
53056
53341
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
53057
|
-
assertGuestPath(ctx,
|
|
53342
|
+
assertGuestPath(ctx, path48.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
53058
53343
|
const res = await history.readSubagent(args);
|
|
53059
53344
|
return { response: { type: "history:subagent-read", ...res } };
|
|
53060
53345
|
};
|
|
@@ -53063,7 +53348,7 @@ function buildHistoryHandlers(deps) {
|
|
|
53063
53348
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
53064
53349
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
53065
53350
|
const filtered = dirs.filter(
|
|
53066
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
53351
|
+
(d) => isGuestPathAllowed(ctx.grants, path48.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
53067
53352
|
);
|
|
53068
53353
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
53069
53354
|
}
|
|
@@ -53080,7 +53365,7 @@ function buildHistoryHandlers(deps) {
|
|
|
53080
53365
|
}
|
|
53081
53366
|
|
|
53082
53367
|
// src/handlers/workspace.ts
|
|
53083
|
-
var
|
|
53368
|
+
var path49 = __toESM(require("path"), 1);
|
|
53084
53369
|
var os15 = __toESM(require("os"), 1);
|
|
53085
53370
|
init_protocol();
|
|
53086
53371
|
init_protocol();
|
|
@@ -53122,22 +53407,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
53122
53407
|
const args = WorkspaceListArgs.parse(frame);
|
|
53123
53408
|
const isGuest = ctx?.principal.kind === "guest";
|
|
53124
53409
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
|
|
53125
|
-
const resolvedCwd =
|
|
53126
|
-
const target = args.path ?
|
|
53410
|
+
const resolvedCwd = path49.resolve(args.cwd ?? fallbackCwd);
|
|
53411
|
+
const target = args.path ? path49.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
53127
53412
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
53128
53413
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
53129
53414
|
return { response: { type: "workspace:list", ...res } };
|
|
53130
53415
|
};
|
|
53131
53416
|
const read = async (frame, _client, ctx) => {
|
|
53132
53417
|
const args = WorkspaceReadArgs.parse(frame);
|
|
53133
|
-
const target =
|
|
53418
|
+
const target = path49.isAbsolute(args.path) ? path49.resolve(args.path) : path49.resolve(args.cwd, args.path);
|
|
53134
53419
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
53135
53420
|
const res = workspace.read(args);
|
|
53136
53421
|
return { response: { type: "workspace:read", ...res } };
|
|
53137
53422
|
};
|
|
53138
53423
|
const skillsList = async (frame, _client, ctx) => {
|
|
53139
53424
|
const args = SkillsListArgs.parse(frame);
|
|
53140
|
-
const cwdAbs =
|
|
53425
|
+
const cwdAbs = path49.resolve(args.cwd);
|
|
53141
53426
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
53142
53427
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
53143
53428
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -53149,7 +53434,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
53149
53434
|
};
|
|
53150
53435
|
const agentsList = async (frame, _client, ctx) => {
|
|
53151
53436
|
const args = AgentsListArgs.parse(frame);
|
|
53152
|
-
const cwdAbs =
|
|
53437
|
+
const cwdAbs = path49.resolve(args.cwd);
|
|
53153
53438
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
53154
53439
|
if (args.tool === "codex") {
|
|
53155
53440
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -53171,20 +53456,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
53171
53456
|
}
|
|
53172
53457
|
|
|
53173
53458
|
// src/handlers/git.ts
|
|
53174
|
-
var
|
|
53459
|
+
var path51 = __toESM(require("path"), 1);
|
|
53175
53460
|
init_protocol();
|
|
53176
53461
|
init_protocol();
|
|
53177
53462
|
|
|
53178
53463
|
// src/workspace/git.ts
|
|
53179
53464
|
var import_node_child_process10 = require("child_process");
|
|
53180
|
-
var
|
|
53181
|
-
var
|
|
53465
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
53466
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
53182
53467
|
var import_node_util = require("util");
|
|
53183
53468
|
var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
|
|
53184
53469
|
function normalizePath(p2) {
|
|
53185
|
-
const resolved =
|
|
53470
|
+
const resolved = import_node_path38.default.resolve(p2);
|
|
53186
53471
|
try {
|
|
53187
|
-
return
|
|
53472
|
+
return import_node_fs37.default.realpathSync(resolved);
|
|
53188
53473
|
} catch {
|
|
53189
53474
|
return resolved;
|
|
53190
53475
|
}
|
|
@@ -53258,7 +53543,7 @@ async function listGitBranches(cwd) {
|
|
|
53258
53543
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
53259
53544
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
53260
53545
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
53261
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
53546
|
+
if (!isGuestPathAllowed(ctx.grants, path51.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
53262
53547
|
throw new ClawdError(
|
|
53263
53548
|
ERROR_CODES.UNAUTHORIZED,
|
|
53264
53549
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -53776,7 +54061,7 @@ function buildPersonaHandlers(deps) {
|
|
|
53776
54061
|
}
|
|
53777
54062
|
|
|
53778
54063
|
// src/handlers/attachment.ts
|
|
53779
|
-
var
|
|
54064
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
53780
54065
|
init_protocol();
|
|
53781
54066
|
init_protocol();
|
|
53782
54067
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -53856,12 +54141,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
53856
54141
|
`session ${args.sessionId} scope unresolved`
|
|
53857
54142
|
);
|
|
53858
54143
|
}
|
|
53859
|
-
const cwdAbs =
|
|
53860
|
-
const candidateAbs =
|
|
54144
|
+
const cwdAbs = import_node_path39.default.resolve(sessionFile.cwd);
|
|
54145
|
+
const candidateAbs = import_node_path39.default.isAbsolute(args.relPath) ? import_node_path39.default.resolve(args.relPath) : import_node_path39.default.resolve(cwdAbs, args.relPath);
|
|
53861
54146
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
53862
54147
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
53863
54148
|
const entry = entries.find((e) => {
|
|
53864
|
-
const storedAbs =
|
|
54149
|
+
const storedAbs = import_node_path39.default.isAbsolute(e.relPath) ? import_node_path39.default.resolve(e.relPath) : import_node_path39.default.resolve(cwdAbs, e.relPath);
|
|
53865
54150
|
return storedAbs === candidateAbs && !e.stale;
|
|
53866
54151
|
});
|
|
53867
54152
|
if (!entry) {
|
|
@@ -53886,7 +54171,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
53886
54171
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
53887
54172
|
const f = deps.sessionStore.read(sessionId);
|
|
53888
54173
|
if (!f) return;
|
|
53889
|
-
assertGuestAttachmentPath(ctx,
|
|
54174
|
+
assertGuestAttachmentPath(ctx, import_node_path39.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
53890
54175
|
}
|
|
53891
54176
|
const groupAdd = async (frame, _client, ctx) => {
|
|
53892
54177
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -53901,8 +54186,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
53901
54186
|
if (!scope) {
|
|
53902
54187
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
53903
54188
|
}
|
|
53904
|
-
const cwdAbs =
|
|
53905
|
-
const candidateAbs =
|
|
54189
|
+
const cwdAbs = import_node_path39.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
54190
|
+
const candidateAbs = import_node_path39.default.isAbsolute(args.relPath) ? import_node_path39.default.resolve(args.relPath) : import_node_path39.default.resolve(cwdAbs, args.relPath);
|
|
53906
54191
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
53907
54192
|
const from = ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
53908
54193
|
const size = 0;
|
|
@@ -53961,19 +54246,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
53961
54246
|
|
|
53962
54247
|
// src/handlers/extension.ts
|
|
53963
54248
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
53964
|
-
var
|
|
54249
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
53965
54250
|
init_protocol();
|
|
53966
54251
|
|
|
53967
54252
|
// src/extension/bundle-zip.ts
|
|
53968
54253
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
53969
|
-
var
|
|
53970
|
-
var
|
|
54254
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
54255
|
+
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
53971
54256
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
53972
54257
|
async function bundleExtensionDir(dir) {
|
|
53973
54258
|
const entries = await listFilesSorted(dir);
|
|
53974
54259
|
const zip = new import_jszip2.default();
|
|
53975
54260
|
for (const rel of entries) {
|
|
53976
|
-
const abs =
|
|
54261
|
+
const abs = import_node_path40.default.join(dir, rel);
|
|
53977
54262
|
const content = await import_promises5.default.readFile(abs);
|
|
53978
54263
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
53979
54264
|
}
|
|
@@ -53982,7 +54267,7 @@ async function bundleExtensionDir(dir) {
|
|
|
53982
54267
|
compression: "DEFLATE",
|
|
53983
54268
|
compressionOptions: { level: 6 }
|
|
53984
54269
|
});
|
|
53985
|
-
const sha256 =
|
|
54270
|
+
const sha256 = import_node_crypto13.default.createHash("sha256").update(buffer).digest("hex");
|
|
53986
54271
|
return { buffer, sha256 };
|
|
53987
54272
|
}
|
|
53988
54273
|
var FIXED_DATE = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
|
|
@@ -53994,7 +54279,7 @@ async function listFilesSorted(rootDir) {
|
|
|
53994
54279
|
return out;
|
|
53995
54280
|
}
|
|
53996
54281
|
async function walk(absRoot, relPrefix, out) {
|
|
53997
|
-
const dirAbs =
|
|
54282
|
+
const dirAbs = import_node_path40.default.join(absRoot, relPrefix);
|
|
53998
54283
|
const entries = await import_promises5.default.readdir(dirAbs, { withFileTypes: true });
|
|
53999
54284
|
for (const e of entries) {
|
|
54000
54285
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -54048,25 +54333,25 @@ function computePublishCheck(args) {
|
|
|
54048
54333
|
|
|
54049
54334
|
// src/extension/install-flow.ts
|
|
54050
54335
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
54051
|
-
var
|
|
54336
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
54052
54337
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
54053
|
-
var
|
|
54338
|
+
var import_node_crypto14 = __toESM(require("crypto"), 1);
|
|
54054
54339
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
54055
54340
|
|
|
54056
54341
|
// src/extension/paths.ts
|
|
54057
54342
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
54058
|
-
var
|
|
54343
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
54059
54344
|
function clawdHomeRoot(override) {
|
|
54060
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
54345
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path41.default.join(import_node_os17.default.homedir(), ".clawd");
|
|
54061
54346
|
}
|
|
54062
54347
|
function extensionsRoot(override) {
|
|
54063
|
-
return
|
|
54348
|
+
return import_node_path41.default.join(clawdHomeRoot(override), "extensions");
|
|
54064
54349
|
}
|
|
54065
54350
|
function publishedChannelsFile(override) {
|
|
54066
|
-
return
|
|
54351
|
+
return import_node_path41.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
54067
54352
|
}
|
|
54068
54353
|
function bundleCacheRoot(override) {
|
|
54069
|
-
return
|
|
54354
|
+
return import_node_path41.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
54070
54355
|
}
|
|
54071
54356
|
|
|
54072
54357
|
// src/extension/install-flow.ts
|
|
@@ -54079,7 +54364,7 @@ var InstallError = class extends Error {
|
|
|
54079
54364
|
};
|
|
54080
54365
|
async function installFromChannel(args, deps) {
|
|
54081
54366
|
const { channelRef, snapshotHash, bundleZip } = args;
|
|
54082
|
-
const computed =
|
|
54367
|
+
const computed = import_node_crypto14.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
54083
54368
|
if (computed !== snapshotHash) {
|
|
54084
54369
|
throw new InstallError(
|
|
54085
54370
|
"HASH_MISMATCH",
|
|
@@ -54093,7 +54378,7 @@ async function installFromChannel(args, deps) {
|
|
|
54093
54378
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
54094
54379
|
}
|
|
54095
54380
|
for (const name of Object.keys(zip.files)) {
|
|
54096
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
54381
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path42.default.isAbsolute(name)) {
|
|
54097
54382
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
54098
54383
|
}
|
|
54099
54384
|
}
|
|
@@ -54125,7 +54410,7 @@ async function installFromChannel(args, deps) {
|
|
|
54125
54410
|
);
|
|
54126
54411
|
}
|
|
54127
54412
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
54128
|
-
const destDir =
|
|
54413
|
+
const destDir = import_node_path42.default.join(deps.extensionsRoot, localExtId);
|
|
54129
54414
|
let destExists = false;
|
|
54130
54415
|
try {
|
|
54131
54416
|
await import_promises6.default.access(destDir);
|
|
@@ -54139,16 +54424,16 @@ async function installFromChannel(args, deps) {
|
|
|
54139
54424
|
);
|
|
54140
54425
|
}
|
|
54141
54426
|
const stage = await import_promises6.default.mkdtemp(
|
|
54142
|
-
|
|
54427
|
+
import_node_path42.default.join(import_node_os18.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
54143
54428
|
);
|
|
54144
54429
|
try {
|
|
54145
54430
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
54146
|
-
const dest =
|
|
54431
|
+
const dest = import_node_path42.default.join(stage, name);
|
|
54147
54432
|
if (entry.dir) {
|
|
54148
54433
|
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
54149
54434
|
continue;
|
|
54150
54435
|
}
|
|
54151
|
-
await import_promises6.default.mkdir(
|
|
54436
|
+
await import_promises6.default.mkdir(import_node_path42.default.dirname(dest), { recursive: true });
|
|
54152
54437
|
if (name === "manifest.json") {
|
|
54153
54438
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
54154
54439
|
await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -54169,9 +54454,9 @@ async function installFromChannel(args, deps) {
|
|
|
54169
54454
|
|
|
54170
54455
|
// src/extension/update-flow.ts
|
|
54171
54456
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
54172
|
-
var
|
|
54457
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
54173
54458
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
54174
|
-
var
|
|
54459
|
+
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
54175
54460
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
54176
54461
|
var UpdateError = class extends Error {
|
|
54177
54462
|
constructor(code, message) {
|
|
@@ -54186,11 +54471,11 @@ async function updateFromChannel(args, deps) {
|
|
|
54186
54471
|
channelRef.extId,
|
|
54187
54472
|
channelRef.ownerPrincipalId
|
|
54188
54473
|
);
|
|
54189
|
-
const liveDir =
|
|
54474
|
+
const liveDir = import_node_path43.default.join(deps.extensionsRoot, localExtId);
|
|
54190
54475
|
const prevDir = `${liveDir}.prev`;
|
|
54191
54476
|
let existingVersion;
|
|
54192
54477
|
try {
|
|
54193
|
-
const raw = await import_promises7.default.readFile(
|
|
54478
|
+
const raw = await import_promises7.default.readFile(import_node_path43.default.join(liveDir, "manifest.json"), "utf8");
|
|
54194
54479
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
54195
54480
|
if (!parsed2.success) {
|
|
54196
54481
|
throw new UpdateError(
|
|
@@ -54209,7 +54494,7 @@ async function updateFromChannel(args, deps) {
|
|
|
54209
54494
|
if (e instanceof UpdateError) throw e;
|
|
54210
54495
|
throw e;
|
|
54211
54496
|
}
|
|
54212
|
-
const computed =
|
|
54497
|
+
const computed = import_node_crypto15.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
54213
54498
|
if (computed !== snapshotHash) {
|
|
54214
54499
|
throw new UpdateError(
|
|
54215
54500
|
"HASH_MISMATCH",
|
|
@@ -54223,7 +54508,7 @@ async function updateFromChannel(args, deps) {
|
|
|
54223
54508
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
54224
54509
|
}
|
|
54225
54510
|
for (const name of Object.keys(zip.files)) {
|
|
54226
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
54511
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path43.default.isAbsolute(name)) {
|
|
54227
54512
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
54228
54513
|
}
|
|
54229
54514
|
}
|
|
@@ -54258,16 +54543,16 @@ async function updateFromChannel(args, deps) {
|
|
|
54258
54543
|
await import_promises7.default.rm(prevDir, { recursive: true, force: true });
|
|
54259
54544
|
await import_promises7.default.rename(liveDir, prevDir);
|
|
54260
54545
|
const stage = await import_promises7.default.mkdtemp(
|
|
54261
|
-
|
|
54546
|
+
import_node_path43.default.join(import_node_os19.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
54262
54547
|
);
|
|
54263
54548
|
try {
|
|
54264
54549
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
54265
|
-
const dest =
|
|
54550
|
+
const dest = import_node_path43.default.join(stage, name);
|
|
54266
54551
|
if (entry.dir) {
|
|
54267
54552
|
await import_promises7.default.mkdir(dest, { recursive: true });
|
|
54268
54553
|
continue;
|
|
54269
54554
|
}
|
|
54270
|
-
await import_promises7.default.mkdir(
|
|
54555
|
+
await import_promises7.default.mkdir(import_node_path43.default.dirname(dest), { recursive: true });
|
|
54271
54556
|
if (name === "manifest.json") {
|
|
54272
54557
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
54273
54558
|
await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -54360,7 +54645,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
54360
54645
|
);
|
|
54361
54646
|
}
|
|
54362
54647
|
}
|
|
54363
|
-
const manifestPath =
|
|
54648
|
+
const manifestPath = import_node_path44.default.join(root, extId, "manifest.json");
|
|
54364
54649
|
const manifest = await readManifest(root, extId);
|
|
54365
54650
|
const next = { ...manifest, version: newVersion };
|
|
54366
54651
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -54368,7 +54653,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
54368
54653
|
await import_promises8.default.rename(tmp, manifestPath);
|
|
54369
54654
|
}
|
|
54370
54655
|
async function readManifest(root, extId) {
|
|
54371
|
-
const file =
|
|
54656
|
+
const file = import_node_path44.default.join(root, extId, "manifest.json");
|
|
54372
54657
|
let raw;
|
|
54373
54658
|
try {
|
|
54374
54659
|
raw = await import_promises8.default.readFile(file, "utf8");
|
|
@@ -54459,7 +54744,7 @@ function buildExtensionHandlers(deps) {
|
|
|
54459
54744
|
};
|
|
54460
54745
|
async function buildSnapshotMeta(extId) {
|
|
54461
54746
|
const manifest = await readManifest(deps.root, extId);
|
|
54462
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
54747
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path44.default.join(deps.root, extId));
|
|
54463
54748
|
return { manifest, contentHash: sha256, buffer };
|
|
54464
54749
|
}
|
|
54465
54750
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -54640,9 +54925,9 @@ function buildExtensionHandlers(deps) {
|
|
|
54640
54925
|
}
|
|
54641
54926
|
|
|
54642
54927
|
// src/app-builder/project-store.ts
|
|
54643
|
-
var
|
|
54928
|
+
var import_node_fs38 = require("fs");
|
|
54644
54929
|
var import_node_child_process11 = require("child_process");
|
|
54645
|
-
var
|
|
54930
|
+
var import_node_path45 = require("path");
|
|
54646
54931
|
init_protocol();
|
|
54647
54932
|
var PROJECTS_DIR = "projects";
|
|
54648
54933
|
var META_FILE = ".clawd-project.json";
|
|
@@ -54656,19 +54941,19 @@ var ProjectStore = class {
|
|
|
54656
54941
|
root;
|
|
54657
54942
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
54658
54943
|
metaPath(name) {
|
|
54659
|
-
return (0,
|
|
54944
|
+
return (0, import_node_path45.join)(this.projectsRoot(), name, META_FILE);
|
|
54660
54945
|
}
|
|
54661
54946
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
54662
54947
|
projectDir(name) {
|
|
54663
|
-
return (0,
|
|
54948
|
+
return (0, import_node_path45.join)(this.projectsRoot(), name);
|
|
54664
54949
|
}
|
|
54665
54950
|
projectsRoot() {
|
|
54666
|
-
return (0,
|
|
54951
|
+
return (0, import_node_path45.join)(this.root, PROJECTS_DIR);
|
|
54667
54952
|
}
|
|
54668
54953
|
async list() {
|
|
54669
54954
|
let entries;
|
|
54670
54955
|
try {
|
|
54671
|
-
entries = await
|
|
54956
|
+
entries = await import_node_fs38.promises.readdir(this.projectsRoot());
|
|
54672
54957
|
} catch (err) {
|
|
54673
54958
|
if (err.code === "ENOENT") return [];
|
|
54674
54959
|
throw err;
|
|
@@ -54676,7 +54961,7 @@ var ProjectStore = class {
|
|
|
54676
54961
|
const out = [];
|
|
54677
54962
|
for (const name of entries) {
|
|
54678
54963
|
try {
|
|
54679
|
-
const raw = await
|
|
54964
|
+
const raw = await import_node_fs38.promises.readFile(this.metaPath(name), "utf8");
|
|
54680
54965
|
const json = JSON.parse(raw);
|
|
54681
54966
|
let migrated = false;
|
|
54682
54967
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -54687,7 +54972,7 @@ var ProjectStore = class {
|
|
|
54687
54972
|
if (parsed.success) {
|
|
54688
54973
|
out.push(parsed.data);
|
|
54689
54974
|
if (migrated) {
|
|
54690
|
-
void
|
|
54975
|
+
void import_node_fs38.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
54691
54976
|
});
|
|
54692
54977
|
}
|
|
54693
54978
|
}
|
|
@@ -54731,8 +55016,8 @@ var ProjectStore = class {
|
|
|
54731
55016
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
54732
55017
|
}
|
|
54733
55018
|
const dir = this.projectDir(name);
|
|
54734
|
-
await
|
|
54735
|
-
await
|
|
55019
|
+
await import_node_fs38.promises.mkdir(dir, { recursive: true });
|
|
55020
|
+
await import_node_fs38.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
54736
55021
|
return meta;
|
|
54737
55022
|
}
|
|
54738
55023
|
/**
|
|
@@ -54775,7 +55060,7 @@ var ProjectStore = class {
|
|
|
54775
55060
|
}
|
|
54776
55061
|
async delete(name) {
|
|
54777
55062
|
const dir = this.projectDir(name);
|
|
54778
|
-
await
|
|
55063
|
+
await import_node_fs38.promises.rm(dir, { recursive: true, force: true });
|
|
54779
55064
|
}
|
|
54780
55065
|
async updatePort(name, newPort) {
|
|
54781
55066
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -54791,7 +55076,7 @@ var ProjectStore = class {
|
|
|
54791
55076
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
54792
55077
|
}
|
|
54793
55078
|
const updated = { ...target, port: newPort };
|
|
54794
|
-
await
|
|
55079
|
+
await import_node_fs38.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
54795
55080
|
return updated;
|
|
54796
55081
|
}
|
|
54797
55082
|
/**
|
|
@@ -54808,7 +55093,7 @@ var ProjectStore = class {
|
|
|
54808
55093
|
if (!validated.success) {
|
|
54809
55094
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
54810
55095
|
}
|
|
54811
|
-
await
|
|
55096
|
+
await import_node_fs38.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
54812
55097
|
return validated.data;
|
|
54813
55098
|
}
|
|
54814
55099
|
/**
|
|
@@ -54829,7 +55114,7 @@ var ProjectStore = class {
|
|
|
54829
55114
|
if (!validated.success) {
|
|
54830
55115
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
54831
55116
|
}
|
|
54832
|
-
await
|
|
55117
|
+
await import_node_fs38.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
54833
55118
|
return validated.data;
|
|
54834
55119
|
}
|
|
54835
55120
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -54844,7 +55129,7 @@ var ProjectStore = class {
|
|
|
54844
55129
|
if (!validated.success) {
|
|
54845
55130
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
54846
55131
|
}
|
|
54847
|
-
await
|
|
55132
|
+
await import_node_fs38.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
54848
55133
|
return validated.data;
|
|
54849
55134
|
}
|
|
54850
55135
|
};
|
|
@@ -54914,7 +55199,7 @@ function listPidsOnPort(port) {
|
|
|
54914
55199
|
}
|
|
54915
55200
|
|
|
54916
55201
|
// src/app-builder/publish-registry.ts
|
|
54917
|
-
var
|
|
55202
|
+
var import_node_crypto16 = require("crypto");
|
|
54918
55203
|
var PublishJobRegistry = class {
|
|
54919
55204
|
jobs = /* @__PURE__ */ new Map();
|
|
54920
55205
|
has(name) {
|
|
@@ -54931,7 +55216,7 @@ var PublishJobRegistry = class {
|
|
|
54931
55216
|
if (this.jobs.has(args.name)) {
|
|
54932
55217
|
throw new Error(`already publishing: ${args.name}`);
|
|
54933
55218
|
}
|
|
54934
|
-
const jobId = args.jobId ?? `job-${(0,
|
|
55219
|
+
const jobId = args.jobId ?? `job-${(0, import_node_crypto16.randomUUID)()}`;
|
|
54935
55220
|
this.jobs.set(args.name, {
|
|
54936
55221
|
jobId,
|
|
54937
55222
|
name: args.name,
|
|
@@ -54965,8 +55250,8 @@ var PublishJobRegistry = class {
|
|
|
54965
55250
|
|
|
54966
55251
|
// src/app-builder/publish-job-runner.ts
|
|
54967
55252
|
var import_node_child_process13 = require("child_process");
|
|
54968
|
-
var
|
|
54969
|
-
var
|
|
55253
|
+
var import_node_fs39 = require("fs");
|
|
55254
|
+
var import_node_path46 = require("path");
|
|
54970
55255
|
|
|
54971
55256
|
// src/app-builder/publish-stage-parser.ts
|
|
54972
55257
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -54998,10 +55283,10 @@ async function startPublishJob(deps, args) {
|
|
|
54998
55283
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
54999
55284
|
}
|
|
55000
55285
|
const projDir = projectDir(args.name);
|
|
55001
|
-
const logPath = (0,
|
|
55286
|
+
const logPath = (0, import_node_path46.join)(projDir, ".publish.log");
|
|
55002
55287
|
let logStream = null;
|
|
55003
55288
|
try {
|
|
55004
|
-
logStream = (0,
|
|
55289
|
+
logStream = (0, import_node_fs39.createWriteStream)(logPath, { flags: "w" });
|
|
55005
55290
|
} catch {
|
|
55006
55291
|
logStream = null;
|
|
55007
55292
|
}
|
|
@@ -55258,8 +55543,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
55258
55543
|
|
|
55259
55544
|
// src/handlers/app-builder.ts
|
|
55260
55545
|
init_protocol();
|
|
55261
|
-
var
|
|
55262
|
-
var
|
|
55546
|
+
var import_node_path47 = require("path");
|
|
55547
|
+
var import_node_fs40 = require("fs");
|
|
55263
55548
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
55264
55549
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
55265
55550
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -55340,7 +55625,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
55340
55625
|
async function listAllUsersProjects() {
|
|
55341
55626
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
55342
55627
|
const getStore = deps.getStore;
|
|
55343
|
-
const userIds = await
|
|
55628
|
+
const userIds = await import_node_fs40.promises.readdir(deps.usersRoot).catch(() => []);
|
|
55344
55629
|
const perUser = await Promise.all(
|
|
55345
55630
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
55346
55631
|
);
|
|
@@ -55416,8 +55701,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
55416
55701
|
const project = await userStore.create(f.name, reservedPorts);
|
|
55417
55702
|
try {
|
|
55418
55703
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
55419
|
-
const templateSrcDir = (0,
|
|
55420
|
-
const scaffoldScript = (0,
|
|
55704
|
+
const templateSrcDir = (0, import_node_path47.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
55705
|
+
const scaffoldScript = (0, import_node_path47.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
55421
55706
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
55422
55707
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
55423
55708
|
name: project.name,
|
|
@@ -55638,7 +55923,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
55638
55923
|
await userStore.clearPublishJob(args.name);
|
|
55639
55924
|
}
|
|
55640
55925
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
55641
|
-
const scriptPath = (0,
|
|
55926
|
+
const scriptPath = (0, import_node_path47.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
55642
55927
|
deps.logger?.info("app-builder.publish.start", {
|
|
55643
55928
|
name: args.name,
|
|
55644
55929
|
sessionId: boundSession.sessionId,
|
|
@@ -55745,16 +56030,11 @@ function daemonShiftToUiShift(d, _nowMs) {
|
|
|
55745
56030
|
}
|
|
55746
56031
|
if (!d.enabled) noteParts.push("(disabled)");
|
|
55747
56032
|
const note = noteParts.join(" \u2014 ");
|
|
55748
|
-
const runs = d.runs.map((r) => ({
|
|
55749
|
-
startedAtMs: r.startedAtMs,
|
|
55750
|
-
...r.sessionId ? { sessionId: r.sessionId } : {}
|
|
55751
|
-
}));
|
|
55752
56033
|
return {
|
|
55753
56034
|
id: d.id,
|
|
55754
56035
|
agentId: d.targetPersona,
|
|
55755
56036
|
schedule: d.schedule,
|
|
55756
|
-
note
|
|
55757
|
-
...runs.length > 0 ? { runs } : {}
|
|
56037
|
+
note
|
|
55758
56038
|
};
|
|
55759
56039
|
}
|
|
55760
56040
|
function buildShiftHandlers(deps) {
|
|
@@ -55780,9 +56060,34 @@ function buildShiftHandlers(deps) {
|
|
|
55780
56060
|
};
|
|
55781
56061
|
}
|
|
55782
56062
|
|
|
56063
|
+
// src/handlers/visitor.ts
|
|
56064
|
+
init_protocol();
|
|
56065
|
+
function ensureOwner3(ctx) {
|
|
56066
|
+
if (!ctx || ctx.principal.kind !== "owner") {
|
|
56067
|
+
throw new ClawdError(
|
|
56068
|
+
ERROR_CODES.UNAUTHORIZED,
|
|
56069
|
+
"UNAUTHORIZED: visitor:* requires owner ctx"
|
|
56070
|
+
);
|
|
56071
|
+
}
|
|
56072
|
+
}
|
|
56073
|
+
function buildVisitorHandlers(deps) {
|
|
56074
|
+
const list = async (_frame, _client, ctx) => {
|
|
56075
|
+
ensureOwner3(ctx);
|
|
56076
|
+
return {
|
|
56077
|
+
response: {
|
|
56078
|
+
type: "visitor:list",
|
|
56079
|
+
visitors: deps.visitorStore.list()
|
|
56080
|
+
}
|
|
56081
|
+
};
|
|
56082
|
+
};
|
|
56083
|
+
return {
|
|
56084
|
+
"visitor:list": list
|
|
56085
|
+
};
|
|
56086
|
+
}
|
|
56087
|
+
|
|
55783
56088
|
// src/extension/registry.ts
|
|
55784
56089
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
55785
|
-
var
|
|
56090
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
55786
56091
|
async function loadAll(root) {
|
|
55787
56092
|
let entries;
|
|
55788
56093
|
try {
|
|
@@ -55795,13 +56100,13 @@ async function loadAll(root) {
|
|
|
55795
56100
|
for (const ent of entries) {
|
|
55796
56101
|
if (!ent.isDirectory()) continue;
|
|
55797
56102
|
if (ent.name.startsWith(".")) continue;
|
|
55798
|
-
records.push(await loadOne(
|
|
56103
|
+
records.push(await loadOne(import_node_path48.default.join(root, ent.name), ent.name));
|
|
55799
56104
|
}
|
|
55800
56105
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
55801
56106
|
return records;
|
|
55802
56107
|
}
|
|
55803
56108
|
async function loadOne(dir, dirName) {
|
|
55804
|
-
const manifestPath =
|
|
56109
|
+
const manifestPath = import_node_path48.default.join(dir, "manifest.json");
|
|
55805
56110
|
let raw;
|
|
55806
56111
|
try {
|
|
55807
56112
|
raw = await import_promises9.default.readFile(manifestPath, "utf8");
|
|
@@ -55846,7 +56151,7 @@ async function loadOne(dir, dirName) {
|
|
|
55846
56151
|
|
|
55847
56152
|
// src/extension/uninstall.ts
|
|
55848
56153
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
55849
|
-
var
|
|
56154
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
55850
56155
|
var UninstallError = class extends Error {
|
|
55851
56156
|
constructor(code, message) {
|
|
55852
56157
|
super(message);
|
|
@@ -55855,7 +56160,7 @@ var UninstallError = class extends Error {
|
|
|
55855
56160
|
code;
|
|
55856
56161
|
};
|
|
55857
56162
|
async function uninstall(deps) {
|
|
55858
|
-
const dir =
|
|
56163
|
+
const dir = import_node_path49.default.join(deps.root, deps.extId);
|
|
55859
56164
|
try {
|
|
55860
56165
|
await import_promises10.default.access(dir);
|
|
55861
56166
|
} catch {
|
|
@@ -55936,7 +56241,8 @@ function buildMethodHandlers(deps) {
|
|
|
55936
56241
|
shiftStore: deps.shiftStore,
|
|
55937
56242
|
ownerIdProvider: deps.shiftOwnerIdProvider,
|
|
55938
56243
|
now: () => Date.now()
|
|
55939
|
-
})
|
|
56244
|
+
}),
|
|
56245
|
+
...buildVisitorHandlers({ visitorStore: deps.visitorStore })
|
|
55940
56246
|
};
|
|
55941
56247
|
}
|
|
55942
56248
|
|
|
@@ -56229,6 +56535,9 @@ var METHOD_GRANT_MAP = {
|
|
|
56229
56535
|
// 写入路径在 device:connect / 自动反向;list / remove 作联系人读 / 删,owner-only。
|
|
56230
56536
|
"contact:list": ADMIN_ANY,
|
|
56231
56537
|
"contact:remove": ADMIN_ANY,
|
|
56538
|
+
// ---- visitor:* (访客名单,owner-only) ----
|
|
56539
|
+
// owner 看完整访客名单(含没开会话的);guest 不可调(handler 内再 assertOwner 兜底)。
|
|
56540
|
+
"visitor:list": ADMIN_ANY,
|
|
56232
56541
|
// ---- session:* / chat:* 业务方法(v2 Phase 8 两层模型)----
|
|
56233
56542
|
// dispatcher 不验资源,handler 内按 ctx + frame.args 反查 ownerPersonaId 调 assertGrant。
|
|
56234
56543
|
// owner 自动通过(ctx 自带 '*':'admin' grant 一切 match);guest 在被授权 persona 内可调。
|
|
@@ -56407,7 +56716,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
56407
56716
|
|
|
56408
56717
|
// src/extension/runtime.ts
|
|
56409
56718
|
var import_node_child_process15 = require("child_process");
|
|
56410
|
-
var
|
|
56719
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
56411
56720
|
var import_promises11 = require("timers/promises");
|
|
56412
56721
|
|
|
56413
56722
|
// src/extension/port-allocator.ts
|
|
@@ -56508,7 +56817,7 @@ var Runtime = class {
|
|
|
56508
56817
|
/\$CLAWOS_EXT_PORT/g,
|
|
56509
56818
|
String(port)
|
|
56510
56819
|
);
|
|
56511
|
-
const dir =
|
|
56820
|
+
const dir = import_node_path50.default.join(this.root, extId);
|
|
56512
56821
|
const env = {
|
|
56513
56822
|
...process.env,
|
|
56514
56823
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -56620,7 +56929,7 @@ ${handle.stderrTail}`
|
|
|
56620
56929
|
|
|
56621
56930
|
// src/extension/published-channels.ts
|
|
56622
56931
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
56623
|
-
var
|
|
56932
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
56624
56933
|
init_zod();
|
|
56625
56934
|
var PublishedChannelsError = class extends Error {
|
|
56626
56935
|
constructor(code, message) {
|
|
@@ -56719,7 +57028,7 @@ var PublishedChannelStore = class {
|
|
|
56719
57028
|
)
|
|
56720
57029
|
};
|
|
56721
57030
|
const tmp = `${this.filePath}.tmp`;
|
|
56722
|
-
await import_promises12.default.mkdir(
|
|
57031
|
+
await import_promises12.default.mkdir(import_node_path51.default.dirname(this.filePath), { recursive: true });
|
|
56723
57032
|
await import_promises12.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
56724
57033
|
await import_promises12.default.rename(tmp, this.filePath);
|
|
56725
57034
|
}
|
|
@@ -56727,7 +57036,7 @@ var PublishedChannelStore = class {
|
|
|
56727
57036
|
|
|
56728
57037
|
// src/extension/bundle-cache.ts
|
|
56729
57038
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
56730
|
-
var
|
|
57039
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
56731
57040
|
var BundleCache = class {
|
|
56732
57041
|
constructor(rootDir) {
|
|
56733
57042
|
this.rootDir = rootDir;
|
|
@@ -56736,14 +57045,14 @@ var BundleCache = class {
|
|
|
56736
57045
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
56737
57046
|
async write(snapshotHash, buffer) {
|
|
56738
57047
|
await import_promises13.default.mkdir(this.rootDir, { recursive: true });
|
|
56739
|
-
const file =
|
|
57048
|
+
const file = import_node_path52.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
56740
57049
|
const tmp = `${file}.tmp`;
|
|
56741
57050
|
await import_promises13.default.writeFile(tmp, buffer, { mode: 384 });
|
|
56742
57051
|
await import_promises13.default.rename(tmp, file);
|
|
56743
57052
|
}
|
|
56744
57053
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
56745
57054
|
async read(snapshotHash) {
|
|
56746
|
-
const file =
|
|
57055
|
+
const file = import_node_path52.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
56747
57056
|
try {
|
|
56748
57057
|
return await import_promises13.default.readFile(file);
|
|
56749
57058
|
} catch (e) {
|
|
@@ -56753,13 +57062,13 @@ var BundleCache = class {
|
|
|
56753
57062
|
}
|
|
56754
57063
|
/** Idempotent — missing file is not an error. */
|
|
56755
57064
|
async delete(snapshotHash) {
|
|
56756
|
-
const file =
|
|
57065
|
+
const file = import_node_path52.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
56757
57066
|
await import_promises13.default.rm(file, { force: true });
|
|
56758
57067
|
}
|
|
56759
57068
|
};
|
|
56760
57069
|
|
|
56761
57070
|
// src/index.ts
|
|
56762
|
-
var
|
|
57071
|
+
var import_meta6 = {};
|
|
56763
57072
|
async function startDaemon(config) {
|
|
56764
57073
|
const authFile = loadOrCreateAuthFile({ dataDir: config.dataDir });
|
|
56765
57074
|
const logShippingCfg = config.logShipping ?? { endpoint: null, sampling: {}, mode: "off" };
|
|
@@ -56778,7 +57087,7 @@ async function startDaemon(config) {
|
|
|
56778
57087
|
});
|
|
56779
57088
|
const logger = createLogger({
|
|
56780
57089
|
level: config.logLevel,
|
|
56781
|
-
file:
|
|
57090
|
+
file: import_node_path53.default.join(config.dataDir, "clawd.log"),
|
|
56782
57091
|
logClient
|
|
56783
57092
|
});
|
|
56784
57093
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
@@ -56815,6 +57124,12 @@ async function startDaemon(config) {
|
|
|
56815
57124
|
isOwnerToken: (x) => resolvedAuthToken != null && constantTimeEqual(x, resolvedAuthToken),
|
|
56816
57125
|
ownerPrincipalId,
|
|
56817
57126
|
ownerDisplayName,
|
|
57127
|
+
// persona web 分享:访客 visitor token = daemon 自签 HMAC(无 aud),独立于飞书 connect token
|
|
57128
|
+
// 基建——secret 恒存在(auth-store backfill),故无条件注入。验签 ok → guest ctx(persona wildcard)。
|
|
57129
|
+
verifyVisitorToken: (t) => {
|
|
57130
|
+
const r = verifyVisitorToken(authFile.visitorTokenSecret, t, Math.floor(Date.now() / 1e3));
|
|
57131
|
+
return r.ok ? { ok: true, payload: r.payload } : { ok: false };
|
|
57132
|
+
},
|
|
56818
57133
|
...feishuActive ? {
|
|
56819
57134
|
verifyConnectToken: (token) => {
|
|
56820
57135
|
const publicKeyPem = serverKeyStore.read();
|
|
@@ -56912,8 +57227,8 @@ async function startDaemon(config) {
|
|
|
56912
57227
|
const agents = new AgentsScanner();
|
|
56913
57228
|
const history = new ClaudeHistoryReader();
|
|
56914
57229
|
let transport = null;
|
|
56915
|
-
const personaStore = new PersonaStore(
|
|
56916
|
-
const usersRoot =
|
|
57230
|
+
const personaStore = new PersonaStore(import_node_path53.default.join(config.dataDir, "personas"));
|
|
57231
|
+
const usersRoot = import_node_path53.default.join(config.dataDir, "users");
|
|
56917
57232
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
56918
57233
|
if (defaultsRoot) {
|
|
56919
57234
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -56933,17 +57248,17 @@ async function startDaemon(config) {
|
|
|
56933
57248
|
migrateCodexSandbox({ store: personaStore, logger });
|
|
56934
57249
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
56935
57250
|
const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
|
|
56936
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
57251
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path53.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
|
|
56937
57252
|
const dispatchServerCandidates = [
|
|
56938
|
-
|
|
57253
|
+
import_node_path53.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
56939
57254
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
56940
|
-
|
|
57255
|
+
import_node_path53.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
56941
57256
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
56942
57257
|
];
|
|
56943
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
57258
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs41.default.existsSync(p2));
|
|
56944
57259
|
let dispatchMcpConfigPath2;
|
|
56945
57260
|
if (dispatchServerScriptPath) {
|
|
56946
|
-
const dispatchLogPath =
|
|
57261
|
+
const dispatchLogPath = import_node_path53.default.join(config.dataDir, "dispatch-mcp-server.log");
|
|
56947
57262
|
dispatchMcpConfigPath2 = writeDispatchMcpConfig({
|
|
56948
57263
|
dataDir: config.dataDir,
|
|
56949
57264
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -56960,15 +57275,15 @@ async function startDaemon(config) {
|
|
|
56960
57275
|
});
|
|
56961
57276
|
}
|
|
56962
57277
|
const ticketServerCandidates = [
|
|
56963
|
-
|
|
56964
|
-
|
|
57278
|
+
import_node_path53.default.join(here, "ticket", "mcp-server.cjs"),
|
|
57279
|
+
import_node_path53.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
56965
57280
|
];
|
|
56966
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p2) =>
|
|
57281
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs41.default.existsSync(p2));
|
|
56967
57282
|
const ticketOwnerUnionId = feishuIdentity?.identity.unionId ?? "";
|
|
56968
57283
|
const ticketOwnerName = feishuIdentity?.identity.displayName ?? "";
|
|
56969
57284
|
let ticketMcpConfigPath2;
|
|
56970
57285
|
if (ticketServerScriptPath && ticketOwnerUnionId) {
|
|
56971
|
-
const ticketLogPath =
|
|
57286
|
+
const ticketLogPath = import_node_path53.default.join(config.dataDir, "ticket-mcp-server.log");
|
|
56972
57287
|
ticketMcpConfigPath2 = writeTicketMcpConfig({
|
|
56973
57288
|
dataDir: config.dataDir,
|
|
56974
57289
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -56989,13 +57304,13 @@ async function startDaemon(config) {
|
|
|
56989
57304
|
});
|
|
56990
57305
|
}
|
|
56991
57306
|
const shiftServerCandidates = [
|
|
56992
|
-
|
|
56993
|
-
|
|
57307
|
+
import_node_path53.default.join(here, "shift", "mcp-server.cjs"),
|
|
57308
|
+
import_node_path53.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
56994
57309
|
];
|
|
56995
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p2) =>
|
|
57310
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs41.default.existsSync(p2));
|
|
56996
57311
|
let shiftMcpConfigPath2;
|
|
56997
57312
|
if (shiftServerScriptPath) {
|
|
56998
|
-
const shiftLogPath =
|
|
57313
|
+
const shiftLogPath = import_node_path53.default.join(config.dataDir, "shift-mcp-server.log");
|
|
56999
57314
|
shiftMcpConfigPath2 = await writeShiftMcpConfig({
|
|
57000
57315
|
dataDir: config.dataDir,
|
|
57001
57316
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -57013,7 +57328,7 @@ async function startDaemon(config) {
|
|
|
57013
57328
|
);
|
|
57014
57329
|
}
|
|
57015
57330
|
const shiftStore = createShiftStore({
|
|
57016
|
-
filePath:
|
|
57331
|
+
filePath: import_node_path53.default.join(config.dataDir, "shift.json"),
|
|
57017
57332
|
ownerIdProvider: () => ownerPrincipalId,
|
|
57018
57333
|
now: () => Date.now()
|
|
57019
57334
|
});
|
|
@@ -57031,7 +57346,7 @@ async function startDaemon(config) {
|
|
|
57031
57346
|
getAdapter,
|
|
57032
57347
|
historyReader: history,
|
|
57033
57348
|
dataDir: config.dataDir,
|
|
57034
|
-
personaRoot:
|
|
57349
|
+
personaRoot: import_node_path53.default.join(config.dataDir, "personas"),
|
|
57035
57350
|
usersRoot,
|
|
57036
57351
|
personaStore,
|
|
57037
57352
|
ownerDisplayName,
|
|
@@ -57072,10 +57387,10 @@ async function startDaemon(config) {
|
|
|
57072
57387
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
57073
57388
|
attachmentGroup: {
|
|
57074
57389
|
onFileEdit: (input) => {
|
|
57075
|
-
const absPath =
|
|
57390
|
+
const absPath = import_node_path53.default.isAbsolute(input.relPath) ? input.relPath : import_node_path53.default.join(input.cwd, input.relPath);
|
|
57076
57391
|
let size = 0;
|
|
57077
57392
|
try {
|
|
57078
|
-
size =
|
|
57393
|
+
size = import_node_fs41.default.statSync(absPath).size;
|
|
57079
57394
|
} catch (err) {
|
|
57080
57395
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
57081
57396
|
sessionId: input.sessionId,
|
|
@@ -57208,6 +57523,14 @@ async function startDaemon(config) {
|
|
|
57208
57523
|
ttcAuthBase: TTC_HOSTS.auth,
|
|
57209
57524
|
getCallbackUrl: () => `http://127.0.0.1:${config.port}/auth/callback`
|
|
57210
57525
|
});
|
|
57526
|
+
const visitorStore = createVisitorStore({ dir: config.dataDir });
|
|
57527
|
+
const exchangeVisitorToken = buildVisitorLogin({
|
|
57528
|
+
getSecret: () => authFile.visitorTokenSecret,
|
|
57529
|
+
fetchUserInfo: (ttcToken) => fetchTtcUserInfo({ apiBase: TTC_HOSTS.api, token: ttcToken }),
|
|
57530
|
+
visitorStore,
|
|
57531
|
+
now: () => Date.now(),
|
|
57532
|
+
ttlSeconds: 7 * 24 * 3600
|
|
57533
|
+
});
|
|
57211
57534
|
const getProjectStore = (userId) => new ProjectStore(deriveUserWorkDir(userId, usersRoot));
|
|
57212
57535
|
const appBuilderStore = getProjectStore(ownerPrincipalId);
|
|
57213
57536
|
recoverInterruptedPublishJobs(appBuilderStore, logger).catch((err) => {
|
|
@@ -57265,11 +57588,11 @@ async function startDaemon(config) {
|
|
|
57265
57588
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
57266
57589
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
57267
57590
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
57268
|
-
personaRoot:
|
|
57591
|
+
personaRoot: import_node_path53.default.join(config.dataDir, "personas"),
|
|
57269
57592
|
usersRoot
|
|
57270
57593
|
},
|
|
57271
57594
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
57272
|
-
personaRoot:
|
|
57595
|
+
personaRoot: import_node_path53.default.join(config.dataDir, "personas"),
|
|
57273
57596
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
57274
57597
|
usersRoot,
|
|
57275
57598
|
// capability:list / delete handler 依赖
|
|
@@ -57376,11 +57699,11 @@ async function startDaemon(config) {
|
|
|
57376
57699
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
57377
57700
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
57378
57701
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
57379
|
-
appBuilderPersonaRoot:
|
|
57702
|
+
appBuilderPersonaRoot: import_node_path53.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
57380
57703
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
57381
|
-
deployKitRoot:
|
|
57704
|
+
deployKitRoot: import_node_path53.default.join(config.dataDir, "deploy-kit"),
|
|
57382
57705
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
57383
|
-
resolvePersonaRoot: (personaId) =>
|
|
57706
|
+
resolvePersonaRoot: (personaId) => import_node_path53.default.join(config.dataDir, "personas", personaId),
|
|
57384
57707
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
57385
57708
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
57386
57709
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -57403,7 +57726,9 @@ async function startDaemon(config) {
|
|
|
57403
57726
|
// shift-internal:* MCP loopback handler)。owner 过滤用 ownerPrincipalId(跨
|
|
57404
57727
|
// daemon 稳定身份),跟我们 ShiftStore boot 时用的 provider 一致。
|
|
57405
57728
|
shiftStore,
|
|
57406
|
-
shiftOwnerIdProvider: () => ownerPrincipalId
|
|
57729
|
+
shiftOwnerIdProvider: () => ownerPrincipalId,
|
|
57730
|
+
// persona web 分享:visitor:list owner RPC 读访客名单(同 exchange upsert 的实例)
|
|
57731
|
+
visitorStore
|
|
57407
57732
|
});
|
|
57408
57733
|
let handlers = makeHandlers();
|
|
57409
57734
|
const dispatchHandlers = buildPersonaDispatchHandlers({
|
|
@@ -57421,7 +57746,7 @@ async function startDaemon(config) {
|
|
|
57421
57746
|
}
|
|
57422
57747
|
let sourceJsonlPath = "(no transcript yet \u2014 operate from the task description alone)";
|
|
57423
57748
|
if (sourceFile && sourceFile.toolSessionId) {
|
|
57424
|
-
sourceJsonlPath =
|
|
57749
|
+
sourceJsonlPath = import_node_path53.default.join(
|
|
57425
57750
|
import_node_os20.default.homedir(),
|
|
57426
57751
|
".claude",
|
|
57427
57752
|
"projects",
|
|
@@ -57510,6 +57835,7 @@ async function startDaemon(config) {
|
|
|
57510
57835
|
}
|
|
57511
57836
|
};
|
|
57512
57837
|
const viewerAssetLoader = tryLoadViewerAssets(logger);
|
|
57838
|
+
const shareUiAssetLoader = tryLoadShareUi(logger);
|
|
57513
57839
|
const httpRouter = createHttpRouter({
|
|
57514
57840
|
authResolver,
|
|
57515
57841
|
daemonVersion: version,
|
|
@@ -57518,6 +57844,9 @@ async function startDaemon(config) {
|
|
|
57518
57844
|
rpcDispatcher,
|
|
57519
57845
|
authedRpc,
|
|
57520
57846
|
...viewerAssetLoader ? { viewerAssetLoader } : {},
|
|
57847
|
+
// persona web 分享:访客换 token(POST /share/exchange)+ guest SPA serve(GET /s)
|
|
57848
|
+
visitorExchange: exchangeVisitorToken,
|
|
57849
|
+
...shareUiAssetLoader ? { shareUiAssetLoader } : {},
|
|
57521
57850
|
// /files HMAC verify 用 auth.json 的 signSecret 字段(与 attachment.signUrl 同源)。
|
|
57522
57851
|
// --auth-token CLI 模式没 signSecret → 路由返 501,sign URL 功能整体禁用。
|
|
57523
57852
|
getSignSecret: () => authFile?.signSecret ?? null,
|
|
@@ -57592,11 +57921,15 @@ async function startDaemon(config) {
|
|
|
57592
57921
|
// 命中 cap → attach guest ctx; 空 token / 未命中 → 保持 noAuth 行为 (handler fallback owner).
|
|
57593
57922
|
tryVerifyCapabilityToken: (token) => {
|
|
57594
57923
|
const v2 = capabilityRegistry.verifyToken(token);
|
|
57595
|
-
if (
|
|
57596
|
-
|
|
57597
|
-
|
|
57598
|
-
|
|
57599
|
-
|
|
57924
|
+
if (v2.ok) {
|
|
57925
|
+
return {
|
|
57926
|
+
principal: { id: v2.capability.id, kind: "guest", displayName: v2.capability.displayName },
|
|
57927
|
+
grants: v2.capability.grants
|
|
57928
|
+
};
|
|
57929
|
+
}
|
|
57930
|
+
const vis = verifyVisitorToken(authFile.visitorTokenSecret, token, Math.floor(Date.now() / 1e3));
|
|
57931
|
+
if (vis.ok) return visitorGuestContext(vis.payload);
|
|
57932
|
+
return null;
|
|
57600
57933
|
},
|
|
57601
57934
|
// file-sharing HTTP 路由复用 daemon 同端口(spec §5 第 3 条);router 自己处理 auth + 404
|
|
57602
57935
|
httpRequestHandler: httpRouter,
|
|
@@ -57713,8 +58046,8 @@ async function startDaemon(config) {
|
|
|
57713
58046
|
const lines = [
|
|
57714
58047
|
`Tunnel: ${r.url}`,
|
|
57715
58048
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
57716
|
-
`Frpc config: ${
|
|
57717
|
-
`Frpc log: ${
|
|
58049
|
+
`Frpc config: ${import_node_path53.default.join(config.dataDir, "frpc.toml")}`,
|
|
58050
|
+
`Frpc log: ${import_node_path53.default.join(config.dataDir, "frpc.log")}`
|
|
57718
58051
|
];
|
|
57719
58052
|
const width = Math.max(...lines.map((l) => l.length));
|
|
57720
58053
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -57727,8 +58060,8 @@ ${bar}
|
|
|
57727
58060
|
|
|
57728
58061
|
`);
|
|
57729
58062
|
try {
|
|
57730
|
-
const connectPath =
|
|
57731
|
-
|
|
58063
|
+
const connectPath = import_node_path53.default.join(config.dataDir, "connect.txt");
|
|
58064
|
+
import_node_fs41.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
57732
58065
|
} catch {
|
|
57733
58066
|
}
|
|
57734
58067
|
} catch (err) {
|
|
@@ -57800,9 +58133,9 @@ ${bar}
|
|
|
57800
58133
|
};
|
|
57801
58134
|
}
|
|
57802
58135
|
function migrateDropPersonsDir(dataDir) {
|
|
57803
|
-
const dir =
|
|
58136
|
+
const dir = import_node_path53.default.join(dataDir, "persons");
|
|
57804
58137
|
try {
|
|
57805
|
-
|
|
58138
|
+
import_node_fs41.default.rmSync(dir, { recursive: true, force: true });
|
|
57806
58139
|
} catch {
|
|
57807
58140
|
}
|
|
57808
58141
|
}
|