@clawos-dev/clawd 0.2.468 → 0.2.469
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/app-builder-plugin/mcp-server.cjs +10 -0
- package/dist/cli.cjs +562 -467
- package/dist/dispatch/mcp-server.cjs +10 -0
- package/dist/persona-defaults/persona-clawd-butler/.claude/skills/scan-persona-for-deploy/SKILL.md +20 -1
- package/dist/share-ui/assets/{guest-BCPZNGfX.js → guest-DNeZJT0N.js} +1 -1
- package/dist/share-ui/guest.html +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -450,8 +450,8 @@ var init_parseUtil = __esm({
|
|
|
450
450
|
init_errors();
|
|
451
451
|
init_en();
|
|
452
452
|
makeIssue = (params) => {
|
|
453
|
-
const { data, path:
|
|
454
|
-
const fullPath = [...
|
|
453
|
+
const { data, path: path100, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path100, ...issueData.path || []];
|
|
455
455
|
const fullIssue = {
|
|
456
456
|
...issueData,
|
|
457
457
|
path: fullPath
|
|
@@ -762,11 +762,11 @@ var init_types = __esm({
|
|
|
762
762
|
init_parseUtil();
|
|
763
763
|
init_util();
|
|
764
764
|
ParseInputLazyPath = class {
|
|
765
|
-
constructor(parent, value,
|
|
765
|
+
constructor(parent, value, path100, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path100;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -6077,6 +6077,16 @@ var init_deploy_schemas = __esm({
|
|
|
6077
6077
|
evidence: external_exports.array(EnvEvidenceSchema).optional(),
|
|
6078
6078
|
smokeTask: external_exports.string().optional(),
|
|
6079
6079
|
notes: external_exports.array(external_exports.string()).default([]),
|
|
6080
|
+
/**
|
|
6081
|
+
* 这次扫描**被告知有哪些共享资产**(daemon 的 `SCANNABLE_ASSETS` 在 finishScan 那一刻的名单)。
|
|
6082
|
+
*
|
|
6083
|
+
* 记它是为了回答一个只有它答得了的问题:「这张单据是不是用还不知道某个资产的扫描器扫的」。
|
|
6084
|
+
* 没有它就只能拿「当前资产表 ⊄ 单据的 assets」当判据——而一个 persona 本来就可能真的用不到
|
|
6085
|
+
* 某个资产,那会变成对每张单据的常态唠叨。
|
|
6086
|
+
*
|
|
6087
|
+
* 缺席 = M1b 及以前扫的老单据(那时候扫描器只被告知了 deploy-kit 一条)。
|
|
6088
|
+
*/
|
|
6089
|
+
scannedAssets: external_exports.array(external_exports.string()).optional(),
|
|
6080
6090
|
/**
|
|
6081
6091
|
* 每条凭据的履约选择:secret name → 'deployer' | 'user'。
|
|
6082
6092
|
* **只记「谁出」,不记值。** 没做选择的凭据不在这个 map 里(缺席即未定),
|
|
@@ -9905,8 +9915,8 @@ var require_req = __commonJS({
|
|
|
9905
9915
|
if (req.originalUrl) {
|
|
9906
9916
|
_req.url = req.originalUrl;
|
|
9907
9917
|
} else {
|
|
9908
|
-
const
|
|
9909
|
-
_req.url = typeof
|
|
9918
|
+
const path100 = req.path;
|
|
9919
|
+
_req.url = typeof path100 === "string" ? path100 : req.url ? req.url.path || req.url : void 0;
|
|
9910
9920
|
}
|
|
9911
9921
|
if (req.query) {
|
|
9912
9922
|
_req.query = req.query;
|
|
@@ -10071,14 +10081,14 @@ var require_redact = __commonJS({
|
|
|
10071
10081
|
}
|
|
10072
10082
|
return obj;
|
|
10073
10083
|
}
|
|
10074
|
-
function parsePath(
|
|
10084
|
+
function parsePath(path100) {
|
|
10075
10085
|
const parts = [];
|
|
10076
10086
|
let current = "";
|
|
10077
10087
|
let inBrackets = false;
|
|
10078
10088
|
let inQuotes = false;
|
|
10079
10089
|
let quoteChar = "";
|
|
10080
|
-
for (let i = 0; i <
|
|
10081
|
-
const char =
|
|
10090
|
+
for (let i = 0; i < path100.length; i++) {
|
|
10091
|
+
const char = path100[i];
|
|
10082
10092
|
if (!inBrackets && char === ".") {
|
|
10083
10093
|
if (current) {
|
|
10084
10094
|
parts.push(current);
|
|
@@ -10209,10 +10219,10 @@ var require_redact = __commonJS({
|
|
|
10209
10219
|
return current;
|
|
10210
10220
|
}
|
|
10211
10221
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
10212
|
-
for (const
|
|
10213
|
-
const parts = parsePath(
|
|
10222
|
+
for (const path100 of paths) {
|
|
10223
|
+
const parts = parsePath(path100);
|
|
10214
10224
|
if (parts.includes("*")) {
|
|
10215
|
-
redactWildcardPath(obj, parts, censor,
|
|
10225
|
+
redactWildcardPath(obj, parts, censor, path100, remove);
|
|
10216
10226
|
} else {
|
|
10217
10227
|
if (remove) {
|
|
10218
10228
|
removeKey(obj, parts);
|
|
@@ -10297,8 +10307,8 @@ var require_redact = __commonJS({
|
|
|
10297
10307
|
}
|
|
10298
10308
|
} else {
|
|
10299
10309
|
if (afterWildcard.includes("*")) {
|
|
10300
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10301
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
10310
|
+
const wrappedCensor = typeof censor === "function" ? (value, path100) => {
|
|
10311
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path100];
|
|
10302
10312
|
return censor(value, fullPath);
|
|
10303
10313
|
} : censor;
|
|
10304
10314
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -10333,8 +10343,8 @@ var require_redact = __commonJS({
|
|
|
10333
10343
|
return null;
|
|
10334
10344
|
}
|
|
10335
10345
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
10336
|
-
for (const
|
|
10337
|
-
const parts = parsePath(
|
|
10346
|
+
for (const path100 of pathsToClone) {
|
|
10347
|
+
const parts = parsePath(path100);
|
|
10338
10348
|
let current = pathStructure;
|
|
10339
10349
|
for (let i = 0; i < parts.length; i++) {
|
|
10340
10350
|
const part = parts[i];
|
|
@@ -10386,24 +10396,24 @@ var require_redact = __commonJS({
|
|
|
10386
10396
|
}
|
|
10387
10397
|
return cloneSelectively(obj, pathStructure);
|
|
10388
10398
|
}
|
|
10389
|
-
function validatePath(
|
|
10390
|
-
if (typeof
|
|
10399
|
+
function validatePath(path100) {
|
|
10400
|
+
if (typeof path100 !== "string") {
|
|
10391
10401
|
throw new Error("Paths must be (non-empty) strings");
|
|
10392
10402
|
}
|
|
10393
|
-
if (
|
|
10403
|
+
if (path100 === "") {
|
|
10394
10404
|
throw new Error("Invalid redaction path ()");
|
|
10395
10405
|
}
|
|
10396
|
-
if (
|
|
10397
|
-
throw new Error(`Invalid redaction path (${
|
|
10406
|
+
if (path100.includes("..")) {
|
|
10407
|
+
throw new Error(`Invalid redaction path (${path100})`);
|
|
10398
10408
|
}
|
|
10399
|
-
if (
|
|
10400
|
-
throw new Error(`Invalid redaction path (${
|
|
10409
|
+
if (path100.includes(",")) {
|
|
10410
|
+
throw new Error(`Invalid redaction path (${path100})`);
|
|
10401
10411
|
}
|
|
10402
10412
|
let bracketCount = 0;
|
|
10403
10413
|
let inQuotes = false;
|
|
10404
10414
|
let quoteChar = "";
|
|
10405
|
-
for (let i = 0; i <
|
|
10406
|
-
const char =
|
|
10415
|
+
for (let i = 0; i < path100.length; i++) {
|
|
10416
|
+
const char = path100[i];
|
|
10407
10417
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
10408
10418
|
if (!inQuotes) {
|
|
10409
10419
|
inQuotes = true;
|
|
@@ -10417,20 +10427,20 @@ var require_redact = __commonJS({
|
|
|
10417
10427
|
} else if (char === "]" && !inQuotes) {
|
|
10418
10428
|
bracketCount--;
|
|
10419
10429
|
if (bracketCount < 0) {
|
|
10420
|
-
throw new Error(`Invalid redaction path (${
|
|
10430
|
+
throw new Error(`Invalid redaction path (${path100})`);
|
|
10421
10431
|
}
|
|
10422
10432
|
}
|
|
10423
10433
|
}
|
|
10424
10434
|
if (bracketCount !== 0) {
|
|
10425
|
-
throw new Error(`Invalid redaction path (${
|
|
10435
|
+
throw new Error(`Invalid redaction path (${path100})`);
|
|
10426
10436
|
}
|
|
10427
10437
|
}
|
|
10428
10438
|
function validatePaths(paths) {
|
|
10429
10439
|
if (!Array.isArray(paths)) {
|
|
10430
10440
|
throw new TypeError("paths must be an array");
|
|
10431
10441
|
}
|
|
10432
|
-
for (const
|
|
10433
|
-
validatePath(
|
|
10442
|
+
for (const path100 of paths) {
|
|
10443
|
+
validatePath(path100);
|
|
10434
10444
|
}
|
|
10435
10445
|
}
|
|
10436
10446
|
function slowRedact(options = {}) {
|
|
@@ -10598,8 +10608,8 @@ var require_redaction = __commonJS({
|
|
|
10598
10608
|
if (shape[k2] === null) {
|
|
10599
10609
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
10600
10610
|
} else {
|
|
10601
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10602
|
-
return censor(value, [k2, ...
|
|
10611
|
+
const wrappedCensor = typeof censor === "function" ? (value, path100) => {
|
|
10612
|
+
return censor(value, [k2, ...path100]);
|
|
10603
10613
|
} : censor;
|
|
10604
10614
|
o[k2] = Redact({
|
|
10605
10615
|
paths: shape[k2],
|
|
@@ -10820,7 +10830,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10820
10830
|
var fs88 = require("fs");
|
|
10821
10831
|
var EventEmitter3 = require("events");
|
|
10822
10832
|
var inherits = require("util").inherits;
|
|
10823
|
-
var
|
|
10833
|
+
var path100 = require("path");
|
|
10824
10834
|
var sleep2 = require_atomic_sleep();
|
|
10825
10835
|
var assert = require("assert");
|
|
10826
10836
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -10874,7 +10884,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10874
10884
|
const mode = sonic.mode;
|
|
10875
10885
|
if (sonic.sync) {
|
|
10876
10886
|
try {
|
|
10877
|
-
if (sonic.mkdir) fs88.mkdirSync(
|
|
10887
|
+
if (sonic.mkdir) fs88.mkdirSync(path100.dirname(file), { recursive: true });
|
|
10878
10888
|
const fd = fs88.openSync(file, flags, mode);
|
|
10879
10889
|
fileOpened(null, fd);
|
|
10880
10890
|
} catch (err) {
|
|
@@ -10882,7 +10892,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10882
10892
|
throw err;
|
|
10883
10893
|
}
|
|
10884
10894
|
} else if (sonic.mkdir) {
|
|
10885
|
-
fs88.mkdir(
|
|
10895
|
+
fs88.mkdir(path100.dirname(file), { recursive: true }, (err) => {
|
|
10886
10896
|
if (err) return fileOpened(err);
|
|
10887
10897
|
fs88.open(file, flags, mode, fileOpened);
|
|
10888
10898
|
});
|
|
@@ -14513,11 +14523,11 @@ var init_lib = __esm({
|
|
|
14513
14523
|
}
|
|
14514
14524
|
}
|
|
14515
14525
|
},
|
|
14516
|
-
addToPath: function addToPath(
|
|
14517
|
-
var last =
|
|
14526
|
+
addToPath: function addToPath(path100, added, removed, oldPosInc, options) {
|
|
14527
|
+
var last = path100.lastComponent;
|
|
14518
14528
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14519
14529
|
return {
|
|
14520
|
-
oldPos:
|
|
14530
|
+
oldPos: path100.oldPos + oldPosInc,
|
|
14521
14531
|
lastComponent: {
|
|
14522
14532
|
count: last.count + 1,
|
|
14523
14533
|
added,
|
|
@@ -14527,7 +14537,7 @@ var init_lib = __esm({
|
|
|
14527
14537
|
};
|
|
14528
14538
|
} else {
|
|
14529
14539
|
return {
|
|
14530
|
-
oldPos:
|
|
14540
|
+
oldPos: path100.oldPos + oldPosInc,
|
|
14531
14541
|
lastComponent: {
|
|
14532
14542
|
count: 1,
|
|
14533
14543
|
added,
|
|
@@ -15109,10 +15119,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
15109
15119
|
const memories = raw.map((m2) => {
|
|
15110
15120
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15111
15121
|
const rec4 = m2;
|
|
15112
|
-
const
|
|
15122
|
+
const path100 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15113
15123
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15114
|
-
if (!
|
|
15115
|
-
const entry = { path:
|
|
15124
|
+
if (!path100 || content == null) return null;
|
|
15125
|
+
const entry = { path: path100, content };
|
|
15116
15126
|
if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
|
|
15117
15127
|
return entry;
|
|
15118
15128
|
}).filter((m2) => m2 !== null);
|
|
@@ -15978,10 +15988,10 @@ function parseAttachment(obj) {
|
|
|
15978
15988
|
const memories = raw.map((m2) => {
|
|
15979
15989
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15980
15990
|
const rec4 = m2;
|
|
15981
|
-
const
|
|
15991
|
+
const path100 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15982
15992
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15983
|
-
if (!
|
|
15984
|
-
const out = { path:
|
|
15993
|
+
if (!path100 || content == null) return null;
|
|
15994
|
+
const out = { path: path100, content };
|
|
15985
15995
|
if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
|
|
15986
15996
|
return out;
|
|
15987
15997
|
}).filter((m2) => m2 !== null);
|
|
@@ -36955,8 +36965,8 @@ var require_utils = __commonJS({
|
|
|
36955
36965
|
var result = transform[inputType][outputType](input);
|
|
36956
36966
|
return result;
|
|
36957
36967
|
};
|
|
36958
|
-
exports2.resolve = function(
|
|
36959
|
-
var parts =
|
|
36968
|
+
exports2.resolve = function(path100) {
|
|
36969
|
+
var parts = path100.split("/");
|
|
36960
36970
|
var result = [];
|
|
36961
36971
|
for (var index = 0; index < parts.length; index++) {
|
|
36962
36972
|
var part = parts[index];
|
|
@@ -42809,18 +42819,18 @@ var require_object = __commonJS({
|
|
|
42809
42819
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
42810
42820
|
this.files[name] = object;
|
|
42811
42821
|
};
|
|
42812
|
-
var parentFolder = function(
|
|
42813
|
-
if (
|
|
42814
|
-
|
|
42822
|
+
var parentFolder = function(path100) {
|
|
42823
|
+
if (path100.slice(-1) === "/") {
|
|
42824
|
+
path100 = path100.substring(0, path100.length - 1);
|
|
42815
42825
|
}
|
|
42816
|
-
var lastSlash =
|
|
42817
|
-
return lastSlash > 0 ?
|
|
42826
|
+
var lastSlash = path100.lastIndexOf("/");
|
|
42827
|
+
return lastSlash > 0 ? path100.substring(0, lastSlash) : "";
|
|
42818
42828
|
};
|
|
42819
|
-
var forceTrailingSlash = function(
|
|
42820
|
-
if (
|
|
42821
|
-
|
|
42829
|
+
var forceTrailingSlash = function(path100) {
|
|
42830
|
+
if (path100.slice(-1) !== "/") {
|
|
42831
|
+
path100 += "/";
|
|
42822
42832
|
}
|
|
42823
|
-
return
|
|
42833
|
+
return path100;
|
|
42824
42834
|
};
|
|
42825
42835
|
var folderAdd = function(name, createFolders) {
|
|
42826
42836
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -43822,7 +43832,7 @@ var require_lib3 = __commonJS({
|
|
|
43822
43832
|
// src/run-case/recorder.ts
|
|
43823
43833
|
function startRunCaseRecorder(opts) {
|
|
43824
43834
|
const now = opts.now ?? Date.now;
|
|
43825
|
-
const dir =
|
|
43835
|
+
const dir = import_node_path82.default.dirname(opts.recordPath);
|
|
43826
43836
|
let stream = null;
|
|
43827
43837
|
let closing = false;
|
|
43828
43838
|
let closedSettled = false;
|
|
@@ -43862,12 +43872,12 @@ function startRunCaseRecorder(opts) {
|
|
|
43862
43872
|
};
|
|
43863
43873
|
return { tap, close, closed };
|
|
43864
43874
|
}
|
|
43865
|
-
var import_node_fs57,
|
|
43875
|
+
var import_node_fs57, import_node_path82;
|
|
43866
43876
|
var init_recorder = __esm({
|
|
43867
43877
|
"src/run-case/recorder.ts"() {
|
|
43868
43878
|
"use strict";
|
|
43869
43879
|
import_node_fs57 = __toESM(require("fs"), 1);
|
|
43870
|
-
|
|
43880
|
+
import_node_path82 = __toESM(require("path"), 1);
|
|
43871
43881
|
}
|
|
43872
43882
|
});
|
|
43873
43883
|
|
|
@@ -43910,7 +43920,7 @@ var init_wire = __esm({
|
|
|
43910
43920
|
// src/run-case/controller.ts
|
|
43911
43921
|
async function runController(opts) {
|
|
43912
43922
|
const now = opts.now ?? Date.now;
|
|
43913
|
-
const cwd = opts.cwd ?? (0, import_node_fs58.mkdtempSync)(
|
|
43923
|
+
const cwd = opts.cwd ?? (0, import_node_fs58.mkdtempSync)(import_node_path83.default.join(import_node_os29.default.tmpdir(), "clawd-runcase-"));
|
|
43914
43924
|
const ownsCwd = opts.cwd === void 0;
|
|
43915
43925
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
43916
43926
|
const spawnCtx = { cwd };
|
|
@@ -44077,13 +44087,13 @@ async function runController(opts) {
|
|
|
44077
44087
|
}
|
|
44078
44088
|
return exitCode ?? 0;
|
|
44079
44089
|
}
|
|
44080
|
-
var import_node_fs58, import_node_os29,
|
|
44090
|
+
var import_node_fs58, import_node_os29, import_node_path83;
|
|
44081
44091
|
var init_controller = __esm({
|
|
44082
44092
|
"src/run-case/controller.ts"() {
|
|
44083
44093
|
"use strict";
|
|
44084
44094
|
import_node_fs58 = require("fs");
|
|
44085
44095
|
import_node_os29 = __toESM(require("os"), 1);
|
|
44086
|
-
|
|
44096
|
+
import_node_path83 = __toESM(require("path"), 1);
|
|
44087
44097
|
init_claude();
|
|
44088
44098
|
init_stdout_splitter();
|
|
44089
44099
|
init_permission_stdio();
|
|
@@ -44358,7 +44368,7 @@ Env (advanced):
|
|
|
44358
44368
|
`;
|
|
44359
44369
|
|
|
44360
44370
|
// src/index.ts
|
|
44361
|
-
var
|
|
44371
|
+
var import_node_path81 = __toESM(require("path"), 1);
|
|
44362
44372
|
var import_node_fs56 = __toESM(require("fs"), 1);
|
|
44363
44373
|
var import_node_os28 = __toESM(require("os"), 1);
|
|
44364
44374
|
var import_node_crypto23 = require("crypto");
|
|
@@ -51616,8 +51626,8 @@ function turnStartInput(text) {
|
|
|
51616
51626
|
const items = [];
|
|
51617
51627
|
let leftover = text;
|
|
51618
51628
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
51619
|
-
const [marker, name,
|
|
51620
|
-
items.push({ type: "skill", name, path:
|
|
51629
|
+
const [marker, name, path100] = m2;
|
|
51630
|
+
items.push({ type: "skill", name, path: path100 });
|
|
51621
51631
|
leftover = leftover.replace(marker, "");
|
|
51622
51632
|
}
|
|
51623
51633
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -54712,6 +54722,56 @@ function nextReadiness(receipt, filledEnv) {
|
|
|
54712
54722
|
return next === receipt.status ? void 0 : next;
|
|
54713
54723
|
}
|
|
54714
54724
|
|
|
54725
|
+
// src/deploy/scan-task.ts
|
|
54726
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
54727
|
+
var BUTLER_PERSONA_ID = "persona-clawd-butler";
|
|
54728
|
+
var SCANNABLE_ASSETS = [
|
|
54729
|
+
{
|
|
54730
|
+
name: "deploy-kit",
|
|
54731
|
+
path: (dataDir) => import_node_path30.default.join(dataDir, "deploy-kit"),
|
|
54732
|
+
what: "FC \u90E8\u7F72\u80FD\u529B\uFF08publish.sh / new-extension.sh / \u5DE5\u5177\u94FE / \u51ED\u8BC1\u76EE\u5F55\uFF09\u3002persona \u7528\u7EDD\u5BF9\u8DEF\u5F84\u53BB\u8C03\u8FD9\u91CC\u7684\u811A\u672C\u65F6\uFF0C\u5C31\u8BE5\u62A5\u4E00\u6761 asset\u3002"
|
|
54733
|
+
},
|
|
54734
|
+
{
|
|
54735
|
+
name: "app-builder-plugin",
|
|
54736
|
+
what: "clawd-app-builder MCP server \u7684\u6784\u5EFA\u4EA7\u7269\uFF08daemon \u7684 tsup \u4EA7\u7269\uFF0C\u672C\u673A\u4E0D\u5728\u76D8\u4E0A\u5355\u72EC\u5B58\u4E00\u4EFD\uFF09\u3002**\u5224\u636E**\uFF1Apersona \u7684\u4E3B\u5E72\u52A8\u4F5C\u8D70\u7684\u662F daemon \u63D0\u4F9B\u7684 MCP\uFF08clawd-rpc / app-builder \u90A3\u7C7B\uFF09\u65F6\uFF0C\u4E91\u4E0A\u5BB9\u5668\u91CC\u6CA1\u6709 daemon\uFF0C\u8DD1\u7684\u5C31\u662F\u8FD9\u4EFD\u4EA7\u7269\u2014\u2014\u7528\u5230\u5B83\u5C31\u62A5\u4E00\u6761 asset\uFF0C\u5426\u5219\u5B83\u8FDB\u4E0D\u4E86\u955C\u50CF\u3002"
|
|
54737
|
+
}
|
|
54738
|
+
];
|
|
54739
|
+
function staleScannerAssets(receipt, known = SCANNABLE_ASSETS) {
|
|
54740
|
+
const knew = new Set(receipt.scannedAssets ?? []);
|
|
54741
|
+
return known.filter((a) => !knew.has(a.name));
|
|
54742
|
+
}
|
|
54743
|
+
var STALE_ASSETS_NOTE_PREFIX = "\u3010\u4E0A\u4E91\u626B\u63CF\u3011";
|
|
54744
|
+
function describeStaleAssets(stale) {
|
|
54745
|
+
if (stale.length === 0) return void 0;
|
|
54746
|
+
const plain = (s) => s.replace(/\*\*/g, "").replace(/\s+/g, " ").trim();
|
|
54747
|
+
return `${STALE_ASSETS_NOTE_PREFIX}\u8FD9\u5F20\u5355\u636E\u626B\u7684\u65F6\u5019\uFF0C\u626B\u63CF\u5668\u8FD8\u4E0D\u77E5\u9053\u6709${stale.map((a) => `\u300C${a.name}\u300D`).join("\u3001")}\u8FD9${stale.length > 1 ? "\u51E0" : ""}\u9879\u5171\u4EAB\u8D44\u4EA7\uFF0C\u6240\u4EE5\u6E05\u5355\u91CC\u53EF\u80FD\u6F0F\u4E86\u58F0\u660E\u3002${stale.map((a) => ` ${a.name} \u662F\uFF1A${plain(a.what)}`).join("")} \u7528\u5F97\u4E0A\u7684\u8BDD\uFF0C\u5728\u6E05\u5355\u91CC\u8865\u4E00\u6761 asset\uFF0C\u6216\u8005\u91CD\u626B\uFF08deploy:rescan\uFF09\u4E00\u904D\u3002`;
|
|
54748
|
+
}
|
|
54749
|
+
function settleEndedScan(outcome, current) {
|
|
54750
|
+
if (current?.status !== "scanning") return void 0;
|
|
54751
|
+
return {
|
|
54752
|
+
status: "scanFailed",
|
|
54753
|
+
error: "error" in outcome ? outcome.error : "butler \u4F1A\u8BDD\u7ED3\u675F\u4E86\u4F46\u6CA1\u6709\u8C03 finishScan"
|
|
54754
|
+
};
|
|
54755
|
+
}
|
|
54756
|
+
function reconcileInterruptedScans(deps) {
|
|
54757
|
+
const stale = deps.list().filter((r) => r.status === "scanning");
|
|
54758
|
+
for (const r of stale) {
|
|
54759
|
+
deps.update(r.deployId, { status: "scanFailed", error: "daemon \u91CD\u542F\uFF0C\u626B\u63CF\u4F1A\u8BDD\u5DF2\u4E2D\u65AD\u2014\u2014\u8BF7\u91CD\u65B0\u626B\u63CF" });
|
|
54760
|
+
}
|
|
54761
|
+
return stale.map((r) => r.deployId);
|
|
54762
|
+
}
|
|
54763
|
+
function reconcileInterruptedTrials(deps) {
|
|
54764
|
+
const stale = deps.list().filter((r) => r.status === "trialing");
|
|
54765
|
+
for (const r of stale) {
|
|
54766
|
+
deps.update(r.deployId, {
|
|
54767
|
+
status: "failed",
|
|
54768
|
+
trialStage: void 0,
|
|
54769
|
+
gaps: [{ errorText: "daemon \u91CD\u542F\uFF0C\u8FD9\u4E00\u8F6E\u8BD5\u88C5\u88AB\u6253\u65AD\u4E86\u2014\u2014\u6CA1\u7ED3\u8BBA\uFF0C\u91CD\u8DD1\u4E00\u6B21\u5373\u53EF\u3002" }]
|
|
54770
|
+
});
|
|
54771
|
+
}
|
|
54772
|
+
return stale.map((r) => r.deployId);
|
|
54773
|
+
}
|
|
54774
|
+
|
|
54715
54775
|
// src/handlers/deploy.ts
|
|
54716
54776
|
function ensureOwner(ctx) {
|
|
54717
54777
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
@@ -54892,6 +54952,9 @@ function buildDeployHandlers(deps) {
|
|
|
54892
54952
|
status: "draft",
|
|
54893
54953
|
smokeTask: args.smokeTask ? redactSecretValues(args.smokeTask) : args.smokeTask,
|
|
54894
54954
|
notes: args.notes?.map(redactSecretValues),
|
|
54955
|
+
// 记下这次扫描**被告知有哪些共享资产**。以后资产表长出新条目时,只有扫的时候还不知道
|
|
54956
|
+
// 它的那些单据会被提示一次(见 staleScannerAssets)——不记的话就只能对每张单据都唠叨。
|
|
54957
|
+
scannedAssets: SCANNABLE_ASSETS.map((a) => a.name),
|
|
54895
54958
|
error: void 0
|
|
54896
54959
|
});
|
|
54897
54960
|
return view(applyReadiness(deps, next));
|
|
@@ -54928,12 +54991,16 @@ function buildDeployHandlers(deps) {
|
|
|
54928
54991
|
`VALIDATION_ERROR: \u5DF2\u7ECF\u8BD5\u88C5 ${receipt.trialRound} \u8F6E\u4E86\uFF08\u4E0A\u9650 ${TRIAL_ROUND_MAX}\uFF09\u3002\u4E00\u8F6E\u662F\u4E00\u6B21\u771F\u7684\u955C\u50CF\u6784\u5EFA\u52A0\u4E00\u6B21\u771F\u7684\u53D1\u5E03\uFF0C\u5230\u8FD9\u4E2A\u6570\u8BF4\u660E\u7F3A\u7684\u591A\u534A\u4E0D\u662F\u4E00\u6761\u4F9D\u8D56\u2014\u2014\u56DE\u53BB\u91CD\u626B\u4E00\u904D\uFF0C\u6216\u8005\u627E\u4EBA\u770B\u770B\u8FD9\u6761\u8DEF\u662F\u4E0D\u662F\u8D70\u4E0D\u901A`
|
|
54929
54992
|
);
|
|
54930
54993
|
}
|
|
54994
|
+
const stale = describeStaleAssets(staleScannerAssets(receipt));
|
|
54995
|
+
const kept = receipt.notes.filter((n) => !n.startsWith(STALE_ASSETS_NOTE_PREFIX));
|
|
54996
|
+
const notes = stale ? [...kept, stale] : kept.length === receipt.notes.length ? void 0 : kept;
|
|
54931
54997
|
const next = deps.receipts.update(args.deployId, {
|
|
54932
54998
|
status: "trialing",
|
|
54933
54999
|
trialRound: receipt.trialRound + 1,
|
|
54934
55000
|
trialStage: "\u6392\u961F\u51C6\u5907\u4E2D",
|
|
54935
55001
|
// 上一轮的缺口不留到这一轮:人已经照着补过了,留着会让人以为没改动
|
|
54936
55002
|
gaps: [],
|
|
55003
|
+
...notes ? { notes } : {},
|
|
54937
55004
|
error: void 0
|
|
54938
55005
|
});
|
|
54939
55006
|
deps.startTrial(args.deployId);
|
|
@@ -54986,7 +55053,7 @@ function buildDeployHandlers(deps) {
|
|
|
54986
55053
|
|
|
54987
55054
|
// src/deploy/receipt-store.ts
|
|
54988
55055
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
54989
|
-
var
|
|
55056
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
54990
55057
|
init_protocol();
|
|
54991
55058
|
function createReceiptStore(deps) {
|
|
54992
55059
|
let receipts = [];
|
|
@@ -55012,7 +55079,7 @@ function createReceiptStore(deps) {
|
|
|
55012
55079
|
flushTimer = null;
|
|
55013
55080
|
}
|
|
55014
55081
|
const content = { version: 1, receipts };
|
|
55015
|
-
await import_promises4.default.mkdir(
|
|
55082
|
+
await import_promises4.default.mkdir(import_node_path31.default.dirname(deps.filePath), { recursive: true });
|
|
55016
55083
|
const tmp = `${deps.filePath}.tmp-${process.pid}-${deps.now()}`;
|
|
55017
55084
|
await import_promises4.default.writeFile(tmp, JSON.stringify(content, null, 2), { encoding: "utf8", mode: 384 });
|
|
55018
55085
|
await import_promises4.default.rename(tmp, deps.filePath);
|
|
@@ -55070,7 +55137,7 @@ function createReceiptStore(deps) {
|
|
|
55070
55137
|
|
|
55071
55138
|
// src/deploy/secret-store.ts
|
|
55072
55139
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
55073
|
-
var
|
|
55140
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
55074
55141
|
function createSecretStore(deps) {
|
|
55075
55142
|
let entries = [];
|
|
55076
55143
|
let flushTimer = null;
|
|
@@ -55096,7 +55163,7 @@ function createSecretStore(deps) {
|
|
|
55096
55163
|
flushTimer = null;
|
|
55097
55164
|
}
|
|
55098
55165
|
const content = { version: 1, entries };
|
|
55099
|
-
await import_promises5.default.mkdir(
|
|
55166
|
+
await import_promises5.default.mkdir(import_node_path32.default.dirname(deps.filePath), { recursive: true });
|
|
55100
55167
|
const tmp = `${deps.filePath}.tmp-${process.pid}-${deps.now()}`;
|
|
55101
55168
|
await import_promises5.default.writeFile(tmp, JSON.stringify(content, null, 2), { encoding: "utf8", mode: 384 });
|
|
55102
55169
|
await import_promises5.default.rename(tmp, deps.filePath);
|
|
@@ -55167,9 +55234,10 @@ function createSecretStore(deps) {
|
|
|
55167
55234
|
|
|
55168
55235
|
// src/deploy/cloud-host-config.ts
|
|
55169
55236
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
55170
|
-
var
|
|
55237
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
55171
55238
|
var CLOUD_HOST_CONFIG_FILE = "cloud-host.json";
|
|
55172
|
-
var REQUIRED = ["
|
|
55239
|
+
var REQUIRED = ["gatewayUrl", "gatewayAdminKey", "gatewayApiKey"];
|
|
55240
|
+
var LOCAL_REQUIRED = ["provisionDir", "k3sHost", "k3sKeyPath"];
|
|
55173
55241
|
var CloudHostConfigError = class extends Error {
|
|
55174
55242
|
};
|
|
55175
55243
|
var looksLikeRegistryRef = (s) => {
|
|
@@ -55251,7 +55319,7 @@ function formatGaps(file, gaps, hasLocalCoords) {
|
|
|
55251
55319
|
return lines.join("\n");
|
|
55252
55320
|
}
|
|
55253
55321
|
async function loadCloudHostConfig(dataDir) {
|
|
55254
|
-
const file =
|
|
55322
|
+
const file = import_node_path33.default.join(dataDir, CLOUD_HOST_CONFIG_FILE);
|
|
55255
55323
|
let raw;
|
|
55256
55324
|
try {
|
|
55257
55325
|
raw = await import_promises6.default.readFile(file, "utf8");
|
|
@@ -55276,9 +55344,11 @@ async function loadCloudHostConfig(dataDir) {
|
|
|
55276
55344
|
const buildHost = parsed.buildHost === "local" ? "local" : "gha";
|
|
55277
55345
|
const imageRepo = parsed.imageRepo ?? "clawd-persona-cloud";
|
|
55278
55346
|
if (buildHost === "local") {
|
|
55279
|
-
const need =
|
|
55347
|
+
const need = LOCAL_REQUIRED.filter((k2) => !parsed[k2]);
|
|
55280
55348
|
if (need.length > 0) {
|
|
55281
|
-
throw new CloudHostConfigError(
|
|
55349
|
+
throw new CloudHostConfigError(
|
|
55350
|
+
`${file} \u7684 buildHost \u662F local\uFF0C\u8FD8\u7F3A\uFF1A${need.join(" / ")}\u3002` + (need.includes("provisionDir") ? '\uFF08provisionDir \u662F clawos checkout \u91CC\u7684 cloud-host/provision \u7EDD\u5BF9\u8DEF\u5F84\u2014\u2014local \u8FD9\u6761\u8DEF\u8981\u5728\u672C\u673A\u8DD1\u6784\u5EFA\u5668\u3001\u8FD8\u8981\u4ECE\u4ED3\u5E93\u53D6\u968F\u884C\u8D44\u4EA7\uFF0C\u6240\u4EE5\u5B83\u5FC5\u987B\u6307\u5411\u4E00\u4EFD checkout\u3002\u4E0D\u60F3\u8981\u8FD9\u4E2A\u524D\u63D0\u7684\u8BDD\uFF0C\u6539\u6210\u9ED8\u8BA4\u7684 "buildHost": "gha"\uFF0C\u90A3\u6761\u8DEF\u4E0D\u78B0\u4ED3\u5E93\u3002\uFF09' : "")
|
|
55351
|
+
);
|
|
55282
55352
|
}
|
|
55283
55353
|
} else {
|
|
55284
55354
|
const gaps = ghaGaps(parsed, imageRepo);
|
|
@@ -55289,7 +55359,7 @@ async function loadCloudHostConfig(dataDir) {
|
|
|
55289
55359
|
}
|
|
55290
55360
|
}
|
|
55291
55361
|
return {
|
|
55292
|
-
provisionDir: parsed.provisionDir,
|
|
55362
|
+
...parsed.provisionDir ? { provisionDir: parsed.provisionDir } : {},
|
|
55293
55363
|
gatewayUrl: parsed.gatewayUrl.replace(/\/+$/, ""),
|
|
55294
55364
|
gatewayAdminKey: parsed.gatewayAdminKey,
|
|
55295
55365
|
gatewayApiKey: parsed.gatewayApiKey,
|
|
@@ -55322,34 +55392,34 @@ async function loadCloudHostConfig(dataDir) {
|
|
|
55322
55392
|
// src/deploy/trial-runner.ts
|
|
55323
55393
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
55324
55394
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
55325
|
-
var
|
|
55395
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
55326
55396
|
|
|
55327
55397
|
// src/deploy/bundle-store.ts
|
|
55328
55398
|
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
55329
55399
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
55330
55400
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
55331
|
-
var
|
|
55401
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
55332
55402
|
var import_node_child_process8 = require("child_process");
|
|
55333
55403
|
var BUNDLE_URL_TTL_SEC = 30 * 60;
|
|
55334
55404
|
var RUNTIME_STATE = /* @__PURE__ */ new Set(["projects", ".attachments", ".clawd/sessions"]);
|
|
55335
55405
|
var NEVER_PERSONA = /* @__PURE__ */ new Set(["node_modules", ".git"]);
|
|
55336
55406
|
async function stagePersonaDir(personaDir) {
|
|
55337
|
-
const stage = await import_promises7.default.mkdtemp(
|
|
55338
|
-
const root =
|
|
55339
|
-
await import_promises7.default.cp(root,
|
|
55407
|
+
const stage = await import_promises7.default.mkdtemp(import_node_path34.default.join(import_node_os8.default.tmpdir(), "clawd-bundle-"));
|
|
55408
|
+
const root = import_node_path34.default.resolve(personaDir);
|
|
55409
|
+
await import_promises7.default.cp(root, import_node_path34.default.join(stage, "persona"), {
|
|
55340
55410
|
recursive: true,
|
|
55341
55411
|
dereference: true,
|
|
55342
55412
|
filter: (src) => {
|
|
55343
|
-
const rel =
|
|
55413
|
+
const rel = import_node_path34.default.relative(root, import_node_path34.default.resolve(src));
|
|
55344
55414
|
if (!rel) return true;
|
|
55345
|
-
return !RUNTIME_STATE.has(rel) && !NEVER_PERSONA.has(
|
|
55415
|
+
return !RUNTIME_STATE.has(rel) && !NEVER_PERSONA.has(import_node_path34.default.basename(rel));
|
|
55346
55416
|
}
|
|
55347
55417
|
});
|
|
55348
55418
|
return { dir: stage, cleanup: () => import_promises7.default.rm(stage, { recursive: true, force: true }) };
|
|
55349
55419
|
}
|
|
55350
55420
|
async function packPersonaBundle(personaDir) {
|
|
55351
55421
|
const { dir: stage, cleanup } = await stagePersonaDir(personaDir);
|
|
55352
|
-
const file =
|
|
55422
|
+
const file = import_node_path34.default.join(stage, "bundle.tgz");
|
|
55353
55423
|
await new Promise((resolve9, reject) => {
|
|
55354
55424
|
const child = (0, import_node_child_process8.spawn)("tar", ["-czf", file, "-C", stage, "persona"], { stdio: ["ignore", "ignore", "pipe"] });
|
|
55355
55425
|
let err = "";
|
|
@@ -55614,12 +55684,24 @@ var gap = (errorText, raw, suggest) => ({
|
|
|
55614
55684
|
...raw ? { raw: redactSecretValues(raw.slice(-RAW_TAIL_CHARS)) } : {},
|
|
55615
55685
|
...suggest ? { suggest } : {}
|
|
55616
55686
|
});
|
|
55687
|
+
var CLI_NAME = /^(@[a-z0-9][a-z0-9._+-]*\/)?[a-z0-9][a-z0-9._+-]*$/i;
|
|
55688
|
+
var CLI_NAME_MAX = 40;
|
|
55689
|
+
var stripCliPrefix = (s) => s.replace(/^cli:/i, "");
|
|
55617
55690
|
function missingFromAgentText(text) {
|
|
55691
|
+
const empty = { clis: [], notes: [] };
|
|
55618
55692
|
const idx = text.lastIndexOf(MISSING_MARKER);
|
|
55619
|
-
if (idx === -1) return
|
|
55693
|
+
if (idx === -1) return empty;
|
|
55620
55694
|
const line = text.slice(idx + MISSING_MARKER.length).split("\n")[0].trim();
|
|
55621
|
-
if (!line || /^(none|无|没有)[.。]?$/i.test(line)) return
|
|
55622
|
-
|
|
55695
|
+
if (!line || /^(none|无|没有)[.。]?$/i.test(line)) return empty;
|
|
55696
|
+
const out = { clis: [], notes: [] };
|
|
55697
|
+
for (const raw of line.replace(/[`*]/g, "").split(/[,,、]/)) {
|
|
55698
|
+
const item = raw.trim();
|
|
55699
|
+
if (!item) continue;
|
|
55700
|
+
const name = stripCliPrefix(item);
|
|
55701
|
+
if (name.length <= CLI_NAME_MAX && CLI_NAME.test(name)) out.clis.push(name);
|
|
55702
|
+
else out.notes.push(item);
|
|
55703
|
+
}
|
|
55704
|
+
return out;
|
|
55623
55705
|
}
|
|
55624
55706
|
function gapsFromBuildOutput(r) {
|
|
55625
55707
|
try {
|
|
@@ -55641,6 +55723,8 @@ async function chat(deps, args) {
|
|
|
55641
55723
|
const timer = setTimeout(() => ctl.abort(), args.timeoutMs);
|
|
55642
55724
|
const notes = [];
|
|
55643
55725
|
let text = "";
|
|
55726
|
+
let meta;
|
|
55727
|
+
let delivered = false;
|
|
55644
55728
|
try {
|
|
55645
55729
|
const res = await deps.fetchImpl(`${cloudHost.gatewayUrl}/v1/chat/completions`, {
|
|
55646
55730
|
method: "POST",
|
|
@@ -55658,8 +55742,14 @@ async function chat(deps, args) {
|
|
|
55658
55742
|
});
|
|
55659
55743
|
if (!res.ok) {
|
|
55660
55744
|
const body = await res.text().catch(() => "");
|
|
55661
|
-
return {
|
|
55745
|
+
return {
|
|
55746
|
+
ok: false,
|
|
55747
|
+
notes,
|
|
55748
|
+
text: `gateway \u62D2\u4E86\u8FD9\u6B21\u6295\u5582\uFF08HTTP ${res.status}\uFF09\uFF1A${body.slice(0, 500)}`,
|
|
55749
|
+
infra: { stage: "schedule", reason: `HTTP ${res.status}` }
|
|
55750
|
+
};
|
|
55662
55751
|
}
|
|
55752
|
+
delivered = true;
|
|
55663
55753
|
for await (const line of sseLines(res)) {
|
|
55664
55754
|
if (line.startsWith(":")) {
|
|
55665
55755
|
const note = line.slice(1).trim();
|
|
@@ -55675,6 +55765,7 @@ async function chat(deps, args) {
|
|
|
55675
55765
|
try {
|
|
55676
55766
|
const frame = JSON.parse(payload);
|
|
55677
55767
|
text += frame.choices?.[0]?.delta?.content ?? "";
|
|
55768
|
+
if (frame.clawd) meta = frame.clawd;
|
|
55678
55769
|
} catch {
|
|
55679
55770
|
}
|
|
55680
55771
|
}
|
|
@@ -55683,13 +55774,22 @@ async function chat(deps, args) {
|
|
|
55683
55774
|
return {
|
|
55684
55775
|
ok: false,
|
|
55685
55776
|
notes,
|
|
55686
|
-
text: aborted ? `\u7B49\u4E86 ${Math.round(args.timeoutMs / 6e4)} \u5206\u949F\uFF0C\u5BB9\u5668\u90A3\u8FB9\u8FD8\u6CA1\u8DD1\u5B8C` : `\u8DDF gateway \u8BF4\u4E0D\u4E0A\u8BDD\uFF1A${String(err)}
|
|
55777
|
+
text: aborted ? `\u7B49\u4E86 ${Math.round(args.timeoutMs / 6e4)} \u5206\u949F\uFF0C\u5BB9\u5668\u90A3\u8FB9\u8FD8\u6CA1\u8DD1\u5B8C` : `\u8DDF gateway \u8BF4\u4E0D\u4E0A\u8BDD\uFF1A${String(err)}`,
|
|
55778
|
+
// 连响应都没拿到 = 这次投喂没落地;**流中途才断**的另说:任务还在云上跑,
|
|
55779
|
+
// 判不出是清单的错还是网络的错,从严算数
|
|
55780
|
+
...delivered ? {} : { infra: { stage: "schedule", reason: String(err) } }
|
|
55687
55781
|
};
|
|
55688
55782
|
} finally {
|
|
55689
55783
|
clearTimeout(timer);
|
|
55690
55784
|
}
|
|
55691
|
-
|
|
55692
|
-
|
|
55785
|
+
if (!meta?.outcome) {
|
|
55786
|
+
deps.logger?.warn("deploy.trial.no-final-frame", {
|
|
55787
|
+
note: "gateway \u6CA1\u7ED9\u672B\u5E27\u7684 clawd.outcome\uFF0C\u56DE\u843D\u5230\u6B63\u6587\u5224\u5B9A\uFF08\u8001 gateway\uFF0C\u6216\u8005\u8FD9\u6761\u6D41\u88AB\u622A\u65AD\u4E86\uFF09"
|
|
55788
|
+
});
|
|
55789
|
+
}
|
|
55790
|
+
const failed = meta?.outcome ? meta.outcome.kind !== "success" : /\[gateway\]/.test(text);
|
|
55791
|
+
const infra = meta?.outcome?.infra;
|
|
55792
|
+
return { ok: !failed, text, notes, ...failed && infra ? { infra } : {} };
|
|
55693
55793
|
}
|
|
55694
55794
|
async function* sseLines(res) {
|
|
55695
55795
|
const reader = res.body?.getReader();
|
|
@@ -55709,8 +55809,8 @@ async function* sseLines(res) {
|
|
|
55709
55809
|
}
|
|
55710
55810
|
if (buf.trim()) yield buf.trim();
|
|
55711
55811
|
}
|
|
55712
|
-
async function gatewayAdmin(deps,
|
|
55713
|
-
const res = await deps.fetchImpl(`${deps.cloudHost.gatewayUrl}${
|
|
55812
|
+
async function gatewayAdmin(deps, path100, body) {
|
|
55813
|
+
const res = await deps.fetchImpl(`${deps.cloudHost.gatewayUrl}${path100}`, {
|
|
55714
55814
|
method: "POST",
|
|
55715
55815
|
headers: {
|
|
55716
55816
|
"content-type": "application/json",
|
|
@@ -55723,11 +55823,11 @@ async function gatewayAdmin(deps, path99, body) {
|
|
|
55723
55823
|
signal: AbortSignal.timeout(GATEWAY_ADMIN_TIMEOUT_MS)
|
|
55724
55824
|
});
|
|
55725
55825
|
const text = await res.text();
|
|
55726
|
-
if (!res.ok) throw new Error(`gateway ${
|
|
55826
|
+
if (!res.ok) throw new Error(`gateway ${path100} \u56DE\u4E86 HTTP ${res.status}\uFF1A${text.slice(0, 300)}`);
|
|
55727
55827
|
try {
|
|
55728
55828
|
return JSON.parse(text);
|
|
55729
55829
|
} catch {
|
|
55730
|
-
throw new Error(`gateway ${
|
|
55830
|
+
throw new Error(`gateway ${path100} \u56DE\u7684\u4E0D\u662F JSON\uFF1A${text.slice(0, 300)}`);
|
|
55731
55831
|
}
|
|
55732
55832
|
}
|
|
55733
55833
|
async function registerOfficialDeployment(deps, receipt, deployerSecrets) {
|
|
@@ -55826,28 +55926,37 @@ async function buildViaGha(deps, args) {
|
|
|
55826
55926
|
}
|
|
55827
55927
|
async function buildLocally(deps, args) {
|
|
55828
55928
|
const { cloudHost } = deps;
|
|
55929
|
+
const needed = [
|
|
55930
|
+
["provisionDir", cloudHost.provisionDir],
|
|
55931
|
+
["k3sHost", cloudHost.k3sHost],
|
|
55932
|
+
["k3sKeyPath", cloudHost.k3sKeyPath]
|
|
55933
|
+
].filter(([, v2]) => !v2).map(([k2]) => k2);
|
|
55934
|
+
if (needed.length > 0) {
|
|
55935
|
+
return { ok: false, gaps: [gap(`cloud-host.json \u7684 buildHost \u662F local\uFF0C\u4F46\u7F3A ${needed.join(" / ")}\u3002`)] };
|
|
55936
|
+
}
|
|
55937
|
+
const provisionDir = cloudHost.provisionDir;
|
|
55829
55938
|
const baseTag = `${cloudHost.imageRepo}:base-local`;
|
|
55830
55939
|
const deadline = deps.now() + args.timeoutMs;
|
|
55831
55940
|
const left = () => Math.max(3e4, deadline - deps.now());
|
|
55832
55941
|
deps.onStage("\u5728\u672C\u673A\u6784\u5E95\u5EA7");
|
|
55833
55942
|
const base = await deps.runNode(
|
|
55834
|
-
`${
|
|
55943
|
+
`${provisionDir}/build-image.mjs`,
|
|
55835
55944
|
[
|
|
55836
55945
|
"--base",
|
|
55837
55946
|
"--manifest",
|
|
55838
|
-
`${
|
|
55947
|
+
`${provisionDir}/manifests/base.json`,
|
|
55839
55948
|
"--tag",
|
|
55840
55949
|
baseTag,
|
|
55841
55950
|
"--platform",
|
|
55842
55951
|
"linux/amd64",
|
|
55843
55952
|
"--context",
|
|
55844
|
-
`${
|
|
55953
|
+
`${provisionDir}/build-context-base`
|
|
55845
55954
|
],
|
|
55846
55955
|
{ timeoutMs: left() }
|
|
55847
55956
|
);
|
|
55848
55957
|
if (base.code !== 0) return { ok: false, gaps: gapsFromBuildOutput(base) };
|
|
55849
55958
|
deps.onStage("\u5728\u6309\u6E05\u5355\u6784 persona \u5C42");
|
|
55850
|
-
const manifestFile =
|
|
55959
|
+
const manifestFile = import_node_path35.default.join(import_node_os9.default.tmpdir(), `clawd-trial-${args.tmpKey}.json`);
|
|
55851
55960
|
let built;
|
|
55852
55961
|
let staged;
|
|
55853
55962
|
try {
|
|
@@ -55858,14 +55967,14 @@ async function buildLocally(deps, args) {
|
|
|
55858
55967
|
try {
|
|
55859
55968
|
await import_promises8.default.writeFile(manifestFile, JSON.stringify({ manifest: args.manifest }, null, 2), { mode: 384 });
|
|
55860
55969
|
built = await deps.runNode(
|
|
55861
|
-
`${
|
|
55970
|
+
`${provisionDir}/build-image.mjs`,
|
|
55862
55971
|
[
|
|
55863
55972
|
"--manifest",
|
|
55864
55973
|
manifestFile,
|
|
55865
55974
|
"--from",
|
|
55866
55975
|
baseTag,
|
|
55867
55976
|
"--persona-dir",
|
|
55868
|
-
|
|
55977
|
+
import_node_path35.default.join(staged.dir, "persona"),
|
|
55869
55978
|
"--tag",
|
|
55870
55979
|
args.image,
|
|
55871
55980
|
"--platform",
|
|
@@ -55882,11 +55991,8 @@ async function buildLocally(deps, args) {
|
|
|
55882
55991
|
}
|
|
55883
55992
|
if (built.code !== 0) return { ok: false, gaps: gapsFromBuildOutput(built) };
|
|
55884
55993
|
deps.onStage("\u628A\u955C\u50CF\u63A8\u5230\u4E91\u4E0A\u90A3\u53F0\u673A\u5668");
|
|
55885
|
-
if (!cloudHost.k3sHost || !cloudHost.k3sKeyPath) {
|
|
55886
|
-
return { ok: false, gaps: [gap("cloud-host.json \u7684 buildHost \u662F local\uFF0C\u4F46\u7F3A k3sHost / k3sKeyPath\u3002")] };
|
|
55887
|
-
}
|
|
55888
55994
|
const pushed = await deps.runNode(
|
|
55889
|
-
`${
|
|
55995
|
+
`${provisionDir}/push-to-k3s.mjs`,
|
|
55890
55996
|
["--host", cloudHost.k3sHost, "--key", cloudHost.k3sKeyPath, "--image", args.image],
|
|
55891
55997
|
{ timeoutMs: left() }
|
|
55892
55998
|
);
|
|
@@ -55906,6 +56012,12 @@ async function runTrial(deps, args) {
|
|
|
55906
56012
|
const appName = trialAppName(receipt.deployId);
|
|
55907
56013
|
const deadline = deps.now() + cloudHost.trialTimeoutMs;
|
|
55908
56014
|
const left = () => Math.max(3e4, deadline - deps.now());
|
|
56015
|
+
if (cloudHost.buildHost !== "local" && cloudHost.provisionDir) {
|
|
56016
|
+
deps.logger?.info("deploy.trial.provision-dir-unused", {
|
|
56017
|
+
provisionDir: cloudHost.provisionDir,
|
|
56018
|
+
note: "buildHost=gha \u4E0D\u8BFB provisionDir\uFF08\u6784\u5EFA\u6574\u4E2A\u53D1\u751F\u5728 GitHub runner \u4E0A\uFF09\uFF0C\u8FD9\u4E00\u884C\u53EF\u4EE5\u4ECE cloud-host.json \u5220\u6389"
|
|
56019
|
+
});
|
|
56020
|
+
}
|
|
55909
56021
|
const buildOutcome = cloudHost.buildHost === "local" ? await buildLocally(deps, {
|
|
55910
56022
|
manifest,
|
|
55911
56023
|
personaDir: args.personaDir,
|
|
@@ -55942,10 +56054,15 @@ async function runTrial(deps, args) {
|
|
|
55942
56054
|
prompt: buildTeardownPrompt(appName),
|
|
55943
56055
|
timeoutMs: Math.min(left(), 15 * 6e4)
|
|
55944
56056
|
});
|
|
56057
|
+
const infra = smoke.infra ?? (smoke.ok ? teardown.infra : void 0);
|
|
56058
|
+
if (infra) {
|
|
56059
|
+
deps.logger?.warn("deploy.trial.infra-failure", { deployId: receipt.deployId, round, stage: infra.stage });
|
|
56060
|
+
}
|
|
56061
|
+
const spent = !infra;
|
|
55945
56062
|
if (!smoke.ok) {
|
|
55946
56063
|
return {
|
|
55947
56064
|
ok: false,
|
|
55948
|
-
spent
|
|
56065
|
+
spent,
|
|
55949
56066
|
gaps: [
|
|
55950
56067
|
gap(smoke.text.trim() || "\u5BB9\u5668\u91CC\u90A3\u4E2A persona \u6CA1\u8BF4\u6E05\u695A\u4E3A\u4EC0\u4E48\u6CA1\u8DD1\u5B8C", smoke.notes.slice(-20).join("\n")),
|
|
55951
56068
|
...teardown.ok ? [] : [gap(`\u987A\u5E26\uFF1A\u8BD5\u88C5\u4EA7\u7269\u6CA1\u62C6\u5E72\u51C0\u2014\u2014${teardown.text.trim()}`)]
|
|
@@ -55953,14 +56070,21 @@ async function runTrial(deps, args) {
|
|
|
55953
56070
|
};
|
|
55954
56071
|
}
|
|
55955
56072
|
if (!teardown.ok) {
|
|
55956
|
-
return { ok: false, spent
|
|
56073
|
+
return { ok: false, spent, gaps: [gap(`\u5E94\u7528\u5EFA\u51FA\u6765\u5E76\u53D1\u5E03\u6210\u529F\u4E86\uFF0C\u4F46\u62C6\u4E0D\u5E72\u51C0\uFF1A${teardown.text.trim()}`, teardown.notes.slice(-20).join("\n"))] };
|
|
55957
56074
|
}
|
|
55958
56075
|
const missing = missingFromAgentText(smoke.text);
|
|
55959
|
-
if (missing.length > 0) {
|
|
56076
|
+
if (missing.notes.length > 0) {
|
|
56077
|
+
deps.logger?.warn("deploy.trial.missing-not-a-dependency", {
|
|
56078
|
+
deployId: receipt.deployId,
|
|
56079
|
+
round,
|
|
56080
|
+
items: missing.notes
|
|
56081
|
+
});
|
|
56082
|
+
}
|
|
56083
|
+
if (missing.clis.length > 0) {
|
|
55960
56084
|
return {
|
|
55961
56085
|
ok: false,
|
|
55962
56086
|
spent: true,
|
|
55963
|
-
gaps: missing.map((name) => gap(
|
|
56087
|
+
gaps: missing.clis.map((name) => gap(
|
|
55964
56088
|
`\u5BB9\u5668\u91CC\u6CA1\u6709 \`${name}\`\uFF0C\u662F\u5B83\u81EA\u5DF1\u52A8\u624B\u8865\u4E0A\u624D\u8DD1\u4E0B\u53BB\u7684\u2014\u2014\u6E05\u5355\u91CC\u6F0F\u4E86\u8FD9\u6761\uFF0C\u4E0B\u4E00\u4E2A\u5BB9\u5668\u7167\u6837\u7F3A\u3002`,
|
|
55965
56089
|
smoke.text.slice(-RAW_TAIL_CHARS),
|
|
55966
56090
|
`cli:${name}`
|
|
@@ -56008,35 +56132,6 @@ async function runNodeScript(script, args, timeoutMs) {
|
|
|
56008
56132
|
});
|
|
56009
56133
|
}
|
|
56010
56134
|
|
|
56011
|
-
// src/deploy/scan-task.ts
|
|
56012
|
-
var BUTLER_PERSONA_ID = "persona-clawd-butler";
|
|
56013
|
-
var SCANNABLE_ASSETS = ["deploy-kit"];
|
|
56014
|
-
function settleEndedScan(outcome, current) {
|
|
56015
|
-
if (current?.status !== "scanning") return void 0;
|
|
56016
|
-
return {
|
|
56017
|
-
status: "scanFailed",
|
|
56018
|
-
error: "error" in outcome ? outcome.error : "butler \u4F1A\u8BDD\u7ED3\u675F\u4E86\u4F46\u6CA1\u6709\u8C03 finishScan"
|
|
56019
|
-
};
|
|
56020
|
-
}
|
|
56021
|
-
function reconcileInterruptedScans(deps) {
|
|
56022
|
-
const stale = deps.list().filter((r) => r.status === "scanning");
|
|
56023
|
-
for (const r of stale) {
|
|
56024
|
-
deps.update(r.deployId, { status: "scanFailed", error: "daemon \u91CD\u542F\uFF0C\u626B\u63CF\u4F1A\u8BDD\u5DF2\u4E2D\u65AD\u2014\u2014\u8BF7\u91CD\u65B0\u626B\u63CF" });
|
|
56025
|
-
}
|
|
56026
|
-
return stale.map((r) => r.deployId);
|
|
56027
|
-
}
|
|
56028
|
-
function reconcileInterruptedTrials(deps) {
|
|
56029
|
-
const stale = deps.list().filter((r) => r.status === "trialing");
|
|
56030
|
-
for (const r of stale) {
|
|
56031
|
-
deps.update(r.deployId, {
|
|
56032
|
-
status: "failed",
|
|
56033
|
-
trialStage: void 0,
|
|
56034
|
-
gaps: [{ errorText: "daemon \u91CD\u542F\uFF0C\u8FD9\u4E00\u8F6E\u8BD5\u88C5\u88AB\u6253\u65AD\u4E86\u2014\u2014\u6CA1\u7ED3\u8BBA\uFF0C\u91CD\u8DD1\u4E00\u6B21\u5373\u53EF\u3002" }]
|
|
56035
|
-
});
|
|
56036
|
-
}
|
|
56037
|
-
return stale.map((r) => r.deployId);
|
|
56038
|
-
}
|
|
56039
|
-
|
|
56040
56135
|
// src/handlers/lark-bot.ts
|
|
56041
56136
|
init_protocol();
|
|
56042
56137
|
var PROVISION_ERROR_SET = new Set(LARK_BOT_PROVISION_ERROR_REASONS);
|
|
@@ -56425,9 +56520,9 @@ async function refreshTunnelUrlOnStartup(deps) {
|
|
|
56425
56520
|
|
|
56426
56521
|
// src/lark-bot-connector/binding-store.ts
|
|
56427
56522
|
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
56428
|
-
var
|
|
56523
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
56429
56524
|
function createLarkBotBindingStore(personaRoot) {
|
|
56430
|
-
const filePath = (personaId2) =>
|
|
56525
|
+
const filePath = (personaId2) => import_node_path36.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
|
|
56431
56526
|
const read = (personaId2) => {
|
|
56432
56527
|
const file = filePath(personaId2);
|
|
56433
56528
|
if (!import_node_fs28.default.existsSync(file)) return null;
|
|
@@ -56441,7 +56536,7 @@ function createLarkBotBindingStore(personaRoot) {
|
|
|
56441
56536
|
};
|
|
56442
56537
|
const write = (personaId2, meta) => {
|
|
56443
56538
|
const file = filePath(personaId2);
|
|
56444
|
-
import_node_fs28.default.mkdirSync(
|
|
56539
|
+
import_node_fs28.default.mkdirSync(import_node_path36.default.dirname(file), { recursive: true });
|
|
56445
56540
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
56446
56541
|
import_node_fs28.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
56447
56542
|
import_node_fs28.default.renameSync(tmp, file);
|
|
@@ -56609,7 +56704,7 @@ function createLarkBotCloudClient(opts) {
|
|
|
56609
56704
|
|
|
56610
56705
|
// src/lark-bot-connector/chat-router.ts
|
|
56611
56706
|
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
56612
|
-
var
|
|
56707
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
56613
56708
|
init_protocol();
|
|
56614
56709
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
56615
56710
|
var LOCAL_TURN_RETRIES = 2;
|
|
@@ -56676,7 +56771,7 @@ function createLarkChatRouter(deps) {
|
|
|
56676
56771
|
}
|
|
56677
56772
|
const dir = deps.mediaRootFor(env.chatId);
|
|
56678
56773
|
import_node_fs29.default.mkdirSync(dir, { recursive: true });
|
|
56679
|
-
const p2 =
|
|
56774
|
+
const p2 = import_node_path37.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
|
|
56680
56775
|
import_node_fs29.default.writeFileSync(p2, r.data);
|
|
56681
56776
|
lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
56682
56777
|
} catch (err) {
|
|
@@ -56699,7 +56794,7 @@ function createLarkChatRouter(deps) {
|
|
|
56699
56794
|
}
|
|
56700
56795
|
const dir = deps.mediaRootFor(env.chatId);
|
|
56701
56796
|
import_node_fs29.default.mkdirSync(dir, { recursive: true });
|
|
56702
|
-
const p2 =
|
|
56797
|
+
const p2 = import_node_path37.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
|
|
56703
56798
|
import_node_fs29.default.writeFileSync(p2, r.data);
|
|
56704
56799
|
lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
56705
56800
|
} catch (err) {
|
|
@@ -57789,7 +57884,7 @@ var CodexHistoryReader = class {
|
|
|
57789
57884
|
};
|
|
57790
57885
|
|
|
57791
57886
|
// src/tools/codex-skills.ts
|
|
57792
|
-
var
|
|
57887
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
57793
57888
|
function str3(v2) {
|
|
57794
57889
|
return typeof v2 === "string" ? v2 : void 0;
|
|
57795
57890
|
}
|
|
@@ -57804,13 +57899,13 @@ function mapSkillsListResponse(res) {
|
|
|
57804
57899
|
const r = s ?? {};
|
|
57805
57900
|
const name = str3(r.name);
|
|
57806
57901
|
if (!name) continue;
|
|
57807
|
-
const
|
|
57902
|
+
const path100 = str3(r.path);
|
|
57808
57903
|
const description = str3(r.description);
|
|
57809
57904
|
const isPlugin = name.includes(":");
|
|
57810
57905
|
out.push({
|
|
57811
57906
|
name,
|
|
57812
57907
|
source: isPlugin ? "plugin" : "project",
|
|
57813
|
-
...
|
|
57908
|
+
...path100 ? { path: path100 } : {},
|
|
57814
57909
|
...description ? { description } : {},
|
|
57815
57910
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
57816
57911
|
});
|
|
@@ -57826,7 +57921,7 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
57826
57921
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
57827
57922
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
57828
57923
|
beforeRequest: (client) => {
|
|
57829
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
57924
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path38.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
57830
57925
|
}
|
|
57831
57926
|
});
|
|
57832
57927
|
return mapSkillsListResponse(res);
|
|
@@ -57913,14 +58008,14 @@ function str4(v2) {
|
|
|
57913
58008
|
// src/workspace/browser.ts
|
|
57914
58009
|
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
57915
58010
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
57916
|
-
var
|
|
58011
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
57917
58012
|
init_protocol();
|
|
57918
58013
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
57919
58014
|
function resolveInsideCwd(cwd, subpath) {
|
|
57920
|
-
const absCwd =
|
|
57921
|
-
const joined =
|
|
57922
|
-
const rel =
|
|
57923
|
-
if (rel.startsWith("..") ||
|
|
58015
|
+
const absCwd = import_node_path39.default.resolve(cwd);
|
|
58016
|
+
const joined = import_node_path39.default.resolve(absCwd, subpath ?? ".");
|
|
58017
|
+
const rel = import_node_path39.default.relative(absCwd, joined);
|
|
58018
|
+
if (rel.startsWith("..") || import_node_path39.default.isAbsolute(rel)) {
|
|
57924
58019
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
57925
58020
|
}
|
|
57926
58021
|
return joined;
|
|
@@ -57951,7 +58046,7 @@ var WorkspaceBrowser = class {
|
|
|
57951
58046
|
mtime: ""
|
|
57952
58047
|
};
|
|
57953
58048
|
try {
|
|
57954
|
-
const st = import_node_fs30.default.statSync(
|
|
58049
|
+
const st = import_node_fs30.default.statSync(import_node_path39.default.join(full, d.name));
|
|
57955
58050
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
57956
58051
|
if (d.isFile()) entry.size = st.size;
|
|
57957
58052
|
} catch {
|
|
@@ -57998,7 +58093,7 @@ var WorkspaceBrowser = class {
|
|
|
57998
58093
|
// src/skills/agents-scanner.ts
|
|
57999
58094
|
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
58000
58095
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
58001
|
-
var
|
|
58096
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
58002
58097
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
58003
58098
|
function isDirLikeSync2(p2) {
|
|
58004
58099
|
try {
|
|
@@ -58036,10 +58131,10 @@ function scanAgentsDir(dir, source, seen, out) {
|
|
|
58036
58131
|
}
|
|
58037
58132
|
for (const ent of entries) {
|
|
58038
58133
|
if (!ent.name.endsWith(".md")) continue;
|
|
58039
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
58134
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path40.default.join(dir, ent.name)))) {
|
|
58040
58135
|
continue;
|
|
58041
58136
|
}
|
|
58042
|
-
const filePath =
|
|
58137
|
+
const filePath = import_node_path40.default.join(dir, ent.name);
|
|
58043
58138
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
58044
58139
|
if (seen.has(baseName)) continue;
|
|
58045
58140
|
seen.add(baseName);
|
|
@@ -58062,7 +58157,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
58062
58157
|
return;
|
|
58063
58158
|
}
|
|
58064
58159
|
for (const ent of entries) {
|
|
58065
|
-
const childPath =
|
|
58160
|
+
const childPath = import_node_path40.default.join(dir, ent.name);
|
|
58066
58161
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
58067
58162
|
walk2(childPath, [...namespaces, ent.name]);
|
|
58068
58163
|
continue;
|
|
@@ -58087,9 +58182,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
58087
58182
|
walk2(root, []);
|
|
58088
58183
|
}
|
|
58089
58184
|
function readInstalledPlugins2(home) {
|
|
58090
|
-
const pluginsDir =
|
|
58091
|
-
const v2 =
|
|
58092
|
-
const v1 =
|
|
58185
|
+
const pluginsDir = import_node_path40.default.join(home, ".claude", "plugins");
|
|
58186
|
+
const v2 = import_node_path40.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
58187
|
+
const v1 = import_node_path40.default.join(pluginsDir, "installed_plugins.json");
|
|
58093
58188
|
let raw = null;
|
|
58094
58189
|
for (const candidate of [v2, v1]) {
|
|
58095
58190
|
try {
|
|
@@ -58118,19 +58213,19 @@ function readInstalledPlugins2(home) {
|
|
|
58118
58213
|
return out;
|
|
58119
58214
|
}
|
|
58120
58215
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
58121
|
-
let cur =
|
|
58122
|
-
const fsRoot =
|
|
58216
|
+
let cur = import_node_path40.default.resolve(startCwd);
|
|
58217
|
+
const fsRoot = import_node_path40.default.parse(cur).root;
|
|
58123
58218
|
while (true) {
|
|
58124
|
-
scanAgentsDir(
|
|
58219
|
+
scanAgentsDir(import_node_path40.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
58125
58220
|
let hasGit = false;
|
|
58126
58221
|
try {
|
|
58127
|
-
hasGit = import_node_fs31.default.existsSync(
|
|
58222
|
+
hasGit = import_node_fs31.default.existsSync(import_node_path40.default.join(cur, ".git"));
|
|
58128
58223
|
} catch {
|
|
58129
58224
|
}
|
|
58130
58225
|
if (hasGit) return;
|
|
58131
58226
|
if (cur === home) return;
|
|
58132
58227
|
if (cur === fsRoot) return;
|
|
58133
|
-
const parent =
|
|
58228
|
+
const parent = import_node_path40.default.dirname(cur);
|
|
58134
58229
|
if (parent === cur) return;
|
|
58135
58230
|
cur = parent;
|
|
58136
58231
|
}
|
|
@@ -58165,7 +58260,7 @@ var AgentsScanner = class {
|
|
|
58165
58260
|
}
|
|
58166
58261
|
const fsBlock = [];
|
|
58167
58262
|
scanAgentsDir(
|
|
58168
|
-
|
|
58263
|
+
import_node_path40.default.join(this.home, ".claude", "agents"),
|
|
58169
58264
|
"global",
|
|
58170
58265
|
seen,
|
|
58171
58266
|
fsBlock
|
|
@@ -58179,7 +58274,7 @@ var AgentsScanner = class {
|
|
|
58179
58274
|
...this.extraPluginRoots
|
|
58180
58275
|
];
|
|
58181
58276
|
for (const { name, root } of plugins) {
|
|
58182
|
-
const agentsRoot =
|
|
58277
|
+
const agentsRoot = import_node_path40.default.join(root, "agents");
|
|
58183
58278
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
58184
58279
|
}
|
|
58185
58280
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -58189,13 +58284,13 @@ var AgentsScanner = class {
|
|
|
58189
58284
|
// src/observer/session-observer.ts
|
|
58190
58285
|
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
58191
58286
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
58192
|
-
var
|
|
58287
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
58193
58288
|
init_claude_history();
|
|
58194
58289
|
|
|
58195
58290
|
// src/observer/subagent-meta-observer.ts
|
|
58196
58291
|
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
58197
58292
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
58198
|
-
var
|
|
58293
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
58199
58294
|
init_claude_history();
|
|
58200
58295
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
58201
58296
|
var SubagentMetaObserver = class {
|
|
@@ -58208,7 +58303,7 @@ var SubagentMetaObserver = class {
|
|
|
58208
58303
|
watches = /* @__PURE__ */ new Map();
|
|
58209
58304
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
58210
58305
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
58211
|
-
return
|
|
58306
|
+
return import_node_path41.default.join(
|
|
58212
58307
|
this.home,
|
|
58213
58308
|
".claude",
|
|
58214
58309
|
"projects",
|
|
@@ -58264,7 +58359,7 @@ var SubagentMetaObserver = class {
|
|
|
58264
58359
|
if (!m2) return;
|
|
58265
58360
|
const agentId = m2[1];
|
|
58266
58361
|
if (w2.emitted.has(agentId)) return;
|
|
58267
|
-
const file =
|
|
58362
|
+
const file = import_node_path41.default.join(w2.dirPath, name);
|
|
58268
58363
|
let raw;
|
|
58269
58364
|
try {
|
|
58270
58365
|
raw = import_node_fs32.default.readFileSync(file, "utf8");
|
|
@@ -58324,7 +58419,7 @@ var SessionObserver = class {
|
|
|
58324
58419
|
metaObserver;
|
|
58325
58420
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
58326
58421
|
if (override) return override;
|
|
58327
|
-
return
|
|
58422
|
+
return import_node_path42.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
58328
58423
|
}
|
|
58329
58424
|
start(args) {
|
|
58330
58425
|
this.stop(args.sessionId);
|
|
@@ -58350,10 +58445,10 @@ var SessionObserver = class {
|
|
|
58350
58445
|
lastDeriveMs: 0
|
|
58351
58446
|
};
|
|
58352
58447
|
try {
|
|
58353
|
-
import_node_fs33.default.mkdirSync(
|
|
58448
|
+
import_node_fs33.default.mkdirSync(import_node_path42.default.dirname(filePath), { recursive: true });
|
|
58354
58449
|
} catch {
|
|
58355
58450
|
}
|
|
58356
|
-
w2.watcher = import_node_fs33.default.watch(
|
|
58451
|
+
w2.watcher = import_node_fs33.default.watch(import_node_path42.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
58357
58452
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
58358
58453
|
this.poll(w2);
|
|
58359
58454
|
});
|
|
@@ -58450,7 +58545,7 @@ var SessionObserver = class {
|
|
|
58450
58545
|
const now = Date.now();
|
|
58451
58546
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
58452
58547
|
w2.lastRelocateScanMs = now;
|
|
58453
|
-
const projectsRoot =
|
|
58548
|
+
const projectsRoot = import_node_path42.default.join(this.home, ".claude", "projects");
|
|
58454
58549
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
58455
58550
|
if (!found || found === w2.filePath) return;
|
|
58456
58551
|
try {
|
|
@@ -58459,7 +58554,7 @@ var SessionObserver = class {
|
|
|
58459
58554
|
}
|
|
58460
58555
|
w2.filePath = found;
|
|
58461
58556
|
try {
|
|
58462
|
-
w2.watcher = import_node_fs33.default.watch(
|
|
58557
|
+
w2.watcher = import_node_fs33.default.watch(import_node_path42.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
58463
58558
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
58464
58559
|
this.poll(w2);
|
|
58465
58560
|
});
|
|
@@ -58582,7 +58677,7 @@ function listRegistered() {
|
|
|
58582
58677
|
var import_node_child_process10 = require("child_process");
|
|
58583
58678
|
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
58584
58679
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
58585
|
-
var
|
|
58680
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
58586
58681
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
58587
58682
|
var TITLE_MODEL_BY_TOOL = {
|
|
58588
58683
|
claude: "haiku",
|
|
@@ -58653,7 +58748,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
58653
58748
|
if (!text) return null;
|
|
58654
58749
|
let workDir;
|
|
58655
58750
|
try {
|
|
58656
|
-
workDir = import_node_fs34.default.mkdtempSync(
|
|
58751
|
+
workDir = import_node_fs34.default.mkdtempSync(import_node_path43.default.join(import_node_os14.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
58657
58752
|
} catch {
|
|
58658
58753
|
return null;
|
|
58659
58754
|
}
|
|
@@ -58663,8 +58758,8 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
58663
58758
|
} catch {
|
|
58664
58759
|
}
|
|
58665
58760
|
};
|
|
58666
|
-
const outFile =
|
|
58667
|
-
const schemaFile =
|
|
58761
|
+
const outFile = import_node_path43.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
58762
|
+
const schemaFile = import_node_path43.default.join(workDir, "title-schema.json");
|
|
58668
58763
|
if (tool === "codex") {
|
|
58669
58764
|
try {
|
|
58670
58765
|
import_node_fs34.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
@@ -59428,7 +59523,7 @@ async function authenticate(token, deps) {
|
|
|
59428
59523
|
|
|
59429
59524
|
// src/legacy-cleanup.ts
|
|
59430
59525
|
var fs48 = __toESM(require("fs/promises"), 1);
|
|
59431
|
-
var
|
|
59526
|
+
var path51 = __toESM(require("path"), 1);
|
|
59432
59527
|
var LEGACY_FILES = [
|
|
59433
59528
|
"personal-capability.json",
|
|
59434
59529
|
"received-capabilities.json",
|
|
@@ -59437,7 +59532,7 @@ var LEGACY_FILES = [
|
|
|
59437
59532
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
59438
59533
|
const removed = [];
|
|
59439
59534
|
for (const name of LEGACY_FILES) {
|
|
59440
|
-
const p2 =
|
|
59535
|
+
const p2 = path51.join(dataDir, name);
|
|
59441
59536
|
try {
|
|
59442
59537
|
await fs48.unlink(p2);
|
|
59443
59538
|
removed.push(name);
|
|
@@ -59452,7 +59547,7 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
59452
59547
|
|
|
59453
59548
|
// src/inbox/inbox-store.ts
|
|
59454
59549
|
var fs49 = __toESM(require("fs"), 1);
|
|
59455
|
-
var
|
|
59550
|
+
var path52 = __toESM(require("path"), 1);
|
|
59456
59551
|
var INBOX_SUBDIR = "inbox";
|
|
59457
59552
|
var InboxStore = class {
|
|
59458
59553
|
constructor(dataDir) {
|
|
@@ -59550,10 +59645,10 @@ var InboxStore = class {
|
|
|
59550
59645
|
}
|
|
59551
59646
|
}
|
|
59552
59647
|
dirPath() {
|
|
59553
|
-
return
|
|
59648
|
+
return path52.join(this.dataDir, INBOX_SUBDIR);
|
|
59554
59649
|
}
|
|
59555
59650
|
filePath(peerDeviceId) {
|
|
59556
|
-
return
|
|
59651
|
+
return path52.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
59557
59652
|
}
|
|
59558
59653
|
};
|
|
59559
59654
|
function parseAllLines(raw) {
|
|
@@ -59642,7 +59737,7 @@ var InboxManager = class {
|
|
|
59642
59737
|
|
|
59643
59738
|
// src/state/contact-store.ts
|
|
59644
59739
|
var fs50 = __toESM(require("fs"), 1);
|
|
59645
|
-
var
|
|
59740
|
+
var path53 = __toESM(require("path"), 1);
|
|
59646
59741
|
var FILE_NAME = "contacts.json";
|
|
59647
59742
|
var ContactStore = class {
|
|
59648
59743
|
constructor(dataDir) {
|
|
@@ -59652,7 +59747,7 @@ var ContactStore = class {
|
|
|
59652
59747
|
contacts = /* @__PURE__ */ new Map();
|
|
59653
59748
|
load() {
|
|
59654
59749
|
this.contacts.clear();
|
|
59655
|
-
const file =
|
|
59750
|
+
const file = path53.join(this.dataDir, FILE_NAME);
|
|
59656
59751
|
let raw;
|
|
59657
59752
|
try {
|
|
59658
59753
|
raw = fs50.readFileSync(file, "utf8");
|
|
@@ -59736,7 +59831,7 @@ var ContactStore = class {
|
|
|
59736
59831
|
return true;
|
|
59737
59832
|
}
|
|
59738
59833
|
flush() {
|
|
59739
|
-
const file =
|
|
59834
|
+
const file = path53.join(this.dataDir, FILE_NAME);
|
|
59740
59835
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
59741
59836
|
const content = JSON.stringify(
|
|
59742
59837
|
{ contacts: Array.from(this.contacts.values()) },
|
|
@@ -59858,52 +59953,52 @@ async function connectRemote(args) {
|
|
|
59858
59953
|
|
|
59859
59954
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
59860
59955
|
var fs51 = __toESM(require("fs"), 1);
|
|
59861
|
-
var
|
|
59956
|
+
var path54 = __toESM(require("path"), 1);
|
|
59862
59957
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
59863
59958
|
function migrateFlattenSessions(opts) {
|
|
59864
59959
|
const dataDir = opts.dataDir;
|
|
59865
59960
|
const now = opts.now ?? Date.now;
|
|
59866
|
-
const sessionsDir =
|
|
59867
|
-
const flagPath =
|
|
59961
|
+
const sessionsDir = path54.join(dataDir, "sessions");
|
|
59962
|
+
const flagPath = path54.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
59868
59963
|
if (existsSync3(flagPath)) {
|
|
59869
59964
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
59870
59965
|
}
|
|
59871
59966
|
let movedBare = 0;
|
|
59872
59967
|
let movedVmOwner = 0;
|
|
59873
59968
|
let archivedListener = 0;
|
|
59874
|
-
const defaultDir =
|
|
59969
|
+
const defaultDir = path54.join(sessionsDir, "default");
|
|
59875
59970
|
if (existsSync3(defaultDir)) {
|
|
59876
59971
|
for (const entry of readdirSafe(defaultDir)) {
|
|
59877
59972
|
if (!entry.endsWith(".json")) continue;
|
|
59878
|
-
const src =
|
|
59879
|
-
const dst =
|
|
59973
|
+
const src = path54.join(defaultDir, entry);
|
|
59974
|
+
const dst = path54.join(sessionsDir, entry);
|
|
59880
59975
|
fs51.renameSync(src, dst);
|
|
59881
59976
|
movedBare += 1;
|
|
59882
59977
|
}
|
|
59883
59978
|
rmdirIfEmpty(defaultDir);
|
|
59884
59979
|
}
|
|
59885
59980
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
59886
|
-
const personaDir =
|
|
59981
|
+
const personaDir = path54.join(sessionsDir, pid);
|
|
59887
59982
|
if (!isDir(personaDir)) continue;
|
|
59888
59983
|
if (pid === "default") continue;
|
|
59889
|
-
const ownerSrc =
|
|
59984
|
+
const ownerSrc = path54.join(personaDir, "owner");
|
|
59890
59985
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
59891
|
-
const ownerDst =
|
|
59986
|
+
const ownerDst = path54.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
59892
59987
|
fs51.mkdirSync(ownerDst, { recursive: true });
|
|
59893
59988
|
for (const file of readdirSafe(ownerSrc)) {
|
|
59894
59989
|
if (!file.endsWith(".json")) continue;
|
|
59895
|
-
fs51.renameSync(
|
|
59990
|
+
fs51.renameSync(path54.join(ownerSrc, file), path54.join(ownerDst, file));
|
|
59896
59991
|
movedVmOwner += 1;
|
|
59897
59992
|
}
|
|
59898
59993
|
rmdirIfEmpty(ownerSrc);
|
|
59899
59994
|
}
|
|
59900
|
-
const listenerSrc =
|
|
59995
|
+
const listenerSrc = path54.join(personaDir, "listener");
|
|
59901
59996
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
59902
|
-
const archiveDst =
|
|
59997
|
+
const archiveDst = path54.join(dataDir, ".legacy", `listener-${pid}`);
|
|
59903
59998
|
fs51.mkdirSync(archiveDst, { recursive: true });
|
|
59904
59999
|
for (const file of readdirSafe(listenerSrc)) {
|
|
59905
60000
|
if (!file.endsWith(".json")) continue;
|
|
59906
|
-
fs51.renameSync(
|
|
60001
|
+
fs51.renameSync(path54.join(listenerSrc, file), path54.join(archiveDst, file));
|
|
59907
60002
|
archivedListener += 1;
|
|
59908
60003
|
}
|
|
59909
60004
|
rmdirIfEmpty(listenerSrc);
|
|
@@ -59951,13 +60046,13 @@ function rmdirIfEmpty(p2) {
|
|
|
59951
60046
|
|
|
59952
60047
|
// src/migrations/2026-08-18-drop-seeded-projects.ts
|
|
59953
60048
|
var fs52 = __toESM(require("fs"), 1);
|
|
59954
|
-
var
|
|
60049
|
+
var path55 = __toESM(require("path"), 1);
|
|
59955
60050
|
var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
|
|
59956
60051
|
function dropSeededProjects(opts) {
|
|
59957
60052
|
fs52.mkdirSync(opts.dataDir, { recursive: true });
|
|
59958
|
-
const flag =
|
|
60053
|
+
const flag = path55.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
|
|
59959
60054
|
if (fs52.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
|
|
59960
|
-
const file =
|
|
60055
|
+
const file = path55.join(opts.dataDir, "projects.json");
|
|
59961
60056
|
let raw = null;
|
|
59962
60057
|
let dropped = 0;
|
|
59963
60058
|
try {
|
|
@@ -59967,9 +60062,9 @@ function dropSeededProjects(opts) {
|
|
|
59967
60062
|
}
|
|
59968
60063
|
let backup = null;
|
|
59969
60064
|
if (raw != null && dropped > 0) {
|
|
59970
|
-
const dir =
|
|
60065
|
+
const dir = path55.join(opts.dataDir, "backups");
|
|
59971
60066
|
fs52.mkdirSync(dir, { recursive: true });
|
|
59972
|
-
backup =
|
|
60067
|
+
backup = path55.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
|
|
59973
60068
|
fs52.writeFileSync(backup, raw);
|
|
59974
60069
|
}
|
|
59975
60070
|
if (raw != null || dropped > 0) {
|
|
@@ -59981,10 +60076,10 @@ function dropSeededProjects(opts) {
|
|
|
59981
60076
|
|
|
59982
60077
|
// src/transport/http-router.ts
|
|
59983
60078
|
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
59984
|
-
var
|
|
60079
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
59985
60080
|
|
|
59986
60081
|
// src/attachment/mime.ts
|
|
59987
|
-
var
|
|
60082
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
59988
60083
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
59989
60084
|
var EXT_TO_NATIVE_MIME = {
|
|
59990
60085
|
// 图片
|
|
@@ -60091,7 +60186,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
60091
60186
|
".mk"
|
|
60092
60187
|
]);
|
|
60093
60188
|
function lookupMime(filePathOrName) {
|
|
60094
|
-
const ext =
|
|
60189
|
+
const ext = import_node_path44.default.extname(filePathOrName).toLowerCase();
|
|
60095
60190
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
60096
60191
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
60097
60192
|
return "application/octet-stream";
|
|
@@ -60162,7 +60257,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
60162
60257
|
|
|
60163
60258
|
// src/attachment/upload.ts
|
|
60164
60259
|
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
60165
|
-
var
|
|
60260
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
60166
60261
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
60167
60262
|
var import_promises10 = require("stream/promises");
|
|
60168
60263
|
var UploadError = class extends Error {
|
|
@@ -60174,14 +60269,14 @@ var UploadError = class extends Error {
|
|
|
60174
60269
|
code;
|
|
60175
60270
|
};
|
|
60176
60271
|
function assertValidFileName(fileName) {
|
|
60177
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
60272
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path45.default.basename(fileName)) {
|
|
60178
60273
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
60179
60274
|
}
|
|
60180
60275
|
}
|
|
60181
60276
|
var HASH_PREFIX_LEN = 16;
|
|
60182
60277
|
async function writeUploadedAttachment(args) {
|
|
60183
60278
|
assertValidFileName(args.fileName);
|
|
60184
|
-
const attachmentsRoot =
|
|
60279
|
+
const attachmentsRoot = import_node_path45.default.join(args.baseDir, ".attachments");
|
|
60185
60280
|
try {
|
|
60186
60281
|
import_node_fs35.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
60187
60282
|
} catch (err) {
|
|
@@ -60189,7 +60284,7 @@ async function writeUploadedAttachment(args) {
|
|
|
60189
60284
|
}
|
|
60190
60285
|
const hasher = import_node_crypto11.default.createHash("sha256");
|
|
60191
60286
|
let actualSize = 0;
|
|
60192
|
-
const tmpPath =
|
|
60287
|
+
const tmpPath = import_node_path45.default.join(
|
|
60193
60288
|
attachmentsRoot,
|
|
60194
60289
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto11.default.randomBytes(4).toString("hex")}`
|
|
60195
60290
|
);
|
|
@@ -60224,7 +60319,7 @@ async function writeUploadedAttachment(args) {
|
|
|
60224
60319
|
);
|
|
60225
60320
|
}
|
|
60226
60321
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
60227
|
-
const hashDir =
|
|
60322
|
+
const hashDir = import_node_path45.default.join(attachmentsRoot, attachmentId);
|
|
60228
60323
|
let finalFileName;
|
|
60229
60324
|
let hashDirExists = false;
|
|
60230
60325
|
try {
|
|
@@ -60242,7 +60337,7 @@ async function writeUploadedAttachment(args) {
|
|
|
60242
60337
|
try {
|
|
60243
60338
|
import_node_fs35.default.mkdirSync(hashDir, { recursive: true });
|
|
60244
60339
|
finalFileName = args.fileName;
|
|
60245
|
-
import_node_fs35.default.renameSync(tmpPath,
|
|
60340
|
+
import_node_fs35.default.renameSync(tmpPath, import_node_path45.default.join(hashDir, finalFileName));
|
|
60246
60341
|
} catch (err) {
|
|
60247
60342
|
try {
|
|
60248
60343
|
import_node_fs35.default.unlinkSync(tmpPath);
|
|
@@ -60251,7 +60346,7 @@ async function writeUploadedAttachment(args) {
|
|
|
60251
60346
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
60252
60347
|
}
|
|
60253
60348
|
}
|
|
60254
|
-
const absPath =
|
|
60349
|
+
const absPath = import_node_path45.default.join(hashDir, finalFileName);
|
|
60255
60350
|
const relPath = absPath;
|
|
60256
60351
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
60257
60352
|
relPath: absPath,
|
|
@@ -60266,7 +60361,7 @@ async function writeUploadedAttachment(args) {
|
|
|
60266
60361
|
|
|
60267
60362
|
// src/extension/import.ts
|
|
60268
60363
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
60269
|
-
var
|
|
60364
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
60270
60365
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
60271
60366
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
60272
60367
|
var ImportError = class extends Error {
|
|
@@ -60284,7 +60379,7 @@ async function importZip(buf, root) {
|
|
|
60284
60379
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
60285
60380
|
}
|
|
60286
60381
|
for (const name of Object.keys(zip.files)) {
|
|
60287
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
60382
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path46.default.isAbsolute(name)) {
|
|
60288
60383
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
60289
60384
|
}
|
|
60290
60385
|
}
|
|
@@ -60317,7 +60412,7 @@ async function importZip(buf, root) {
|
|
|
60317
60412
|
);
|
|
60318
60413
|
}
|
|
60319
60414
|
}
|
|
60320
|
-
const destDir =
|
|
60415
|
+
const destDir = import_node_path46.default.join(root, manifest.id);
|
|
60321
60416
|
let destExists = false;
|
|
60322
60417
|
try {
|
|
60323
60418
|
await import_promises11.default.access(destDir);
|
|
@@ -60327,15 +60422,15 @@ async function importZip(buf, root) {
|
|
|
60327
60422
|
if (destExists) {
|
|
60328
60423
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
60329
60424
|
}
|
|
60330
|
-
const stage = await import_promises11.default.mkdtemp(
|
|
60425
|
+
const stage = await import_promises11.default.mkdtemp(import_node_path46.default.join(import_node_os15.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
60331
60426
|
try {
|
|
60332
60427
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
60333
|
-
const dest =
|
|
60428
|
+
const dest = import_node_path46.default.join(stage, name);
|
|
60334
60429
|
if (entry.dir) {
|
|
60335
60430
|
await import_promises11.default.mkdir(dest, { recursive: true });
|
|
60336
60431
|
continue;
|
|
60337
60432
|
}
|
|
60338
|
-
await import_promises11.default.mkdir(
|
|
60433
|
+
await import_promises11.default.mkdir(import_node_path46.default.dirname(dest), { recursive: true });
|
|
60339
60434
|
const content = await entry.async("nodebuffer");
|
|
60340
60435
|
await import_promises11.default.writeFile(dest, content);
|
|
60341
60436
|
}
|
|
@@ -60365,7 +60460,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
60365
60460
|
".wasm": "application/wasm"
|
|
60366
60461
|
};
|
|
60367
60462
|
function shareUiAssetMime(filePath) {
|
|
60368
|
-
const ext =
|
|
60463
|
+
const ext = import_node_path47.default.extname(filePath).toLowerCase();
|
|
60369
60464
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
60370
60465
|
}
|
|
60371
60466
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -60464,7 +60559,7 @@ function isValidUploadFileName(fileName) {
|
|
|
60464
60559
|
if (fileName === "." || fileName === "..") return false;
|
|
60465
60560
|
if (fileName.startsWith(".")) return false;
|
|
60466
60561
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
60467
|
-
return fileName ===
|
|
60562
|
+
return fileName === import_node_path47.default.basename(fileName);
|
|
60468
60563
|
}
|
|
60469
60564
|
function createHttpRouter(deps) {
|
|
60470
60565
|
return async (req, res) => {
|
|
@@ -60700,7 +60795,7 @@ function createHttpRouter(deps) {
|
|
|
60700
60795
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
60701
60796
|
return true;
|
|
60702
60797
|
}
|
|
60703
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
60798
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path47.default.basename(r.absPath)));
|
|
60704
60799
|
return true;
|
|
60705
60800
|
}
|
|
60706
60801
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -60821,7 +60916,7 @@ function createHttpRouter(deps) {
|
|
|
60821
60916
|
return true;
|
|
60822
60917
|
}
|
|
60823
60918
|
let absPath;
|
|
60824
|
-
if (
|
|
60919
|
+
if (import_node_path47.default.isAbsolute(pathParam)) {
|
|
60825
60920
|
absPath = pathParam;
|
|
60826
60921
|
} else if (deps.sessionStore) {
|
|
60827
60922
|
const file = deps.sessionStore.read(sid);
|
|
@@ -60829,7 +60924,7 @@ function createHttpRouter(deps) {
|
|
|
60829
60924
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
60830
60925
|
return true;
|
|
60831
60926
|
}
|
|
60832
|
-
absPath =
|
|
60927
|
+
absPath = import_node_path47.default.join(file.cwd, pathParam);
|
|
60833
60928
|
} else {
|
|
60834
60929
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
60835
60930
|
return true;
|
|
@@ -60931,7 +61026,7 @@ function streamFile(res, absPath, logger) {
|
|
|
60931
61026
|
return;
|
|
60932
61027
|
}
|
|
60933
61028
|
const mime = lookupMime(absPath);
|
|
60934
|
-
const basename2 =
|
|
61029
|
+
const basename2 = import_node_path47.default.basename(absPath);
|
|
60935
61030
|
res.writeHead(200, {
|
|
60936
61031
|
"Content-Type": mime,
|
|
60937
61032
|
"Content-Length": String(stat.size),
|
|
@@ -60949,7 +61044,7 @@ function streamFile(res, absPath, logger) {
|
|
|
60949
61044
|
|
|
60950
61045
|
// src/attachment/gc.ts
|
|
60951
61046
|
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
60952
|
-
var
|
|
61047
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
60953
61048
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
60954
61049
|
function runAttachmentGc(args) {
|
|
60955
61050
|
const now = (args.now ?? Date.now)();
|
|
@@ -60958,12 +61053,12 @@ function runAttachmentGc(args) {
|
|
|
60958
61053
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
60959
61054
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
60960
61055
|
if (entry.stale) continue;
|
|
60961
|
-
if (
|
|
61056
|
+
if (import_node_path48.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
60962
61057
|
}
|
|
60963
61058
|
}
|
|
60964
61059
|
const visited = /* @__PURE__ */ new Set();
|
|
60965
61060
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
60966
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
61061
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path48.default.join(
|
|
60967
61062
|
args.dataDir,
|
|
60968
61063
|
"sessions",
|
|
60969
61064
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -60976,7 +61071,7 @@ function runAttachmentGc(args) {
|
|
|
60976
61071
|
return true;
|
|
60977
61072
|
});
|
|
60978
61073
|
for (const rootDir of roots) {
|
|
60979
|
-
const attRoot =
|
|
61074
|
+
const attRoot = import_node_path48.default.join(rootDir, ".attachments");
|
|
60980
61075
|
let hashDirs;
|
|
60981
61076
|
try {
|
|
60982
61077
|
hashDirs = import_node_fs37.default.readdirSync(attRoot);
|
|
@@ -60986,7 +61081,7 @@ function runAttachmentGc(args) {
|
|
|
60986
61081
|
continue;
|
|
60987
61082
|
}
|
|
60988
61083
|
for (const hashDir of hashDirs) {
|
|
60989
|
-
const hashDirAbs =
|
|
61084
|
+
const hashDirAbs = import_node_path48.default.join(attRoot, hashDir);
|
|
60990
61085
|
let files;
|
|
60991
61086
|
try {
|
|
60992
61087
|
files = import_node_fs37.default.readdirSync(hashDirAbs);
|
|
@@ -60994,7 +61089,7 @@ function runAttachmentGc(args) {
|
|
|
60994
61089
|
continue;
|
|
60995
61090
|
}
|
|
60996
61091
|
for (const name of files) {
|
|
60997
|
-
const file =
|
|
61092
|
+
const file = import_node_path48.default.join(hashDirAbs, name);
|
|
60998
61093
|
let stat;
|
|
60999
61094
|
try {
|
|
61000
61095
|
stat = import_node_fs37.default.statSync(file);
|
|
@@ -61026,7 +61121,7 @@ function runAttachmentGc(args) {
|
|
|
61026
61121
|
|
|
61027
61122
|
// src/attachment/group.ts
|
|
61028
61123
|
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
61029
|
-
var
|
|
61124
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
61030
61125
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
61031
61126
|
init_protocol();
|
|
61032
61127
|
var GroupFileStore = class {
|
|
@@ -61038,11 +61133,11 @@ var GroupFileStore = class {
|
|
|
61038
61133
|
this.logger = opts.logger;
|
|
61039
61134
|
}
|
|
61040
61135
|
rootForScope(scope) {
|
|
61041
|
-
return
|
|
61136
|
+
return import_node_path49.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
61042
61137
|
}
|
|
61043
61138
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
61044
61139
|
filePath(scope, sessionId) {
|
|
61045
|
-
return
|
|
61140
|
+
return import_node_path49.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
61046
61141
|
}
|
|
61047
61142
|
cacheKey(scope, sessionId) {
|
|
61048
61143
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -61077,7 +61172,7 @@ var GroupFileStore = class {
|
|
|
61077
61172
|
}
|
|
61078
61173
|
writeFile(scope, sessionId, entries) {
|
|
61079
61174
|
const file = this.filePath(scope, sessionId);
|
|
61080
|
-
import_node_fs38.default.mkdirSync(
|
|
61175
|
+
import_node_fs38.default.mkdirSync(import_node_path49.default.dirname(file), { recursive: true });
|
|
61081
61176
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
61082
61177
|
import_node_fs38.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
61083
61178
|
import_node_fs38.default.renameSync(tmp, file);
|
|
@@ -61167,9 +61262,9 @@ var GroupFileStore = class {
|
|
|
61167
61262
|
|
|
61168
61263
|
// src/discovery/state-file.ts
|
|
61169
61264
|
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
61170
|
-
var
|
|
61265
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
61171
61266
|
function defaultStateFilePath(dataDir) {
|
|
61172
|
-
return
|
|
61267
|
+
return import_node_path50.default.join(dataDir, "state.json");
|
|
61173
61268
|
}
|
|
61174
61269
|
function isPidAlive(pid) {
|
|
61175
61270
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -61205,7 +61300,7 @@ var StateFileManager = class {
|
|
|
61205
61300
|
return { status: "stale", existing };
|
|
61206
61301
|
}
|
|
61207
61302
|
write(state) {
|
|
61208
|
-
import_node_fs39.default.mkdirSync(
|
|
61303
|
+
import_node_fs39.default.mkdirSync(import_node_path50.default.dirname(this.file), { recursive: true });
|
|
61209
61304
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
61210
61305
|
import_node_fs39.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
61211
61306
|
import_node_fs39.default.renameSync(tmp, this.file);
|
|
@@ -61233,13 +61328,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
61233
61328
|
|
|
61234
61329
|
// src/tunnel/tunnel-manager.ts
|
|
61235
61330
|
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
61236
|
-
var
|
|
61331
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
61237
61332
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
61238
61333
|
var import_node_child_process13 = require("child_process");
|
|
61239
61334
|
|
|
61240
61335
|
// src/tunnel/tunnel-store.ts
|
|
61241
61336
|
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
61242
|
-
var
|
|
61337
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
61243
61338
|
var TunnelStore = class {
|
|
61244
61339
|
constructor(filePath) {
|
|
61245
61340
|
this.filePath = filePath;
|
|
@@ -61258,7 +61353,7 @@ var TunnelStore = class {
|
|
|
61258
61353
|
}
|
|
61259
61354
|
}
|
|
61260
61355
|
async set(v2) {
|
|
61261
|
-
const dir =
|
|
61356
|
+
const dir = import_node_path51.default.dirname(this.filePath);
|
|
61262
61357
|
await import_node_fs40.default.promises.mkdir(dir, { recursive: true });
|
|
61263
61358
|
const data = JSON.stringify(v2, null, 2);
|
|
61264
61359
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
@@ -61370,7 +61465,7 @@ function escape(v2) {
|
|
|
61370
61465
|
// src/tunnel/frpc-binary.ts
|
|
61371
61466
|
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
61372
61467
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
61373
|
-
var
|
|
61468
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
61374
61469
|
var import_node_child_process11 = require("child_process");
|
|
61375
61470
|
var import_node_stream3 = require("stream");
|
|
61376
61471
|
var import_promises12 = require("stream/promises");
|
|
@@ -61409,13 +61504,13 @@ async function ensureFrpcBinary(opts) {
|
|
|
61409
61504
|
}
|
|
61410
61505
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
61411
61506
|
const platform = opts.platform ?? detectPlatform();
|
|
61412
|
-
const binDir =
|
|
61507
|
+
const binDir = import_node_path52.default.join(opts.dataDir, "bin");
|
|
61413
61508
|
import_node_fs41.default.mkdirSync(binDir, { recursive: true });
|
|
61414
61509
|
cleanupStaleArtifacts(binDir);
|
|
61415
|
-
const stableBin =
|
|
61510
|
+
const stableBin = import_node_path52.default.join(binDir, "frpc");
|
|
61416
61511
|
if (import_node_fs41.default.existsSync(stableBin)) return stableBin;
|
|
61417
61512
|
const partialBin = `${stableBin}.partial`;
|
|
61418
|
-
const tarballPath =
|
|
61513
|
+
const tarballPath = import_node_path52.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
61419
61514
|
try {
|
|
61420
61515
|
const url = frpcDownloadUrl(version2, platform);
|
|
61421
61516
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -61441,7 +61536,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
61441
61536
|
}
|
|
61442
61537
|
for (const name of entries) {
|
|
61443
61538
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
61444
|
-
const full =
|
|
61539
|
+
const full = import_node_path52.default.join(binDir, name);
|
|
61445
61540
|
try {
|
|
61446
61541
|
import_node_fs41.default.rmSync(full, { recursive: true, force: true });
|
|
61447
61542
|
} catch {
|
|
@@ -61467,7 +61562,7 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
61467
61562
|
await (0, import_promises12.pipeline)(nodeStream, out);
|
|
61468
61563
|
}
|
|
61469
61564
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
61470
|
-
const work =
|
|
61565
|
+
const work = import_node_path52.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
61471
61566
|
import_node_fs41.default.mkdirSync(work, { recursive: true });
|
|
61472
61567
|
try {
|
|
61473
61568
|
await new Promise((resolve9, reject) => {
|
|
@@ -61476,7 +61571,7 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
61476
61571
|
proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
|
|
61477
61572
|
});
|
|
61478
61573
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
61479
|
-
const src =
|
|
61574
|
+
const src = import_node_path52.default.join(work, dirName, "frpc");
|
|
61480
61575
|
if (!import_node_fs41.default.existsSync(src)) {
|
|
61481
61576
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
61482
61577
|
}
|
|
@@ -61488,10 +61583,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
61488
61583
|
|
|
61489
61584
|
// src/tunnel/frpc-process.ts
|
|
61490
61585
|
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
61491
|
-
var
|
|
61586
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
61492
61587
|
var import_node_child_process12 = require("child_process");
|
|
61493
61588
|
function frpcPidFilePath(dataDir) {
|
|
61494
|
-
return
|
|
61589
|
+
return import_node_path53.default.join(dataDir, "frpc.pid");
|
|
61495
61590
|
}
|
|
61496
61591
|
function writeFrpcPid(dataDir, pid) {
|
|
61497
61592
|
try {
|
|
@@ -61533,7 +61628,7 @@ function defaultSleep2(ms) {
|
|
|
61533
61628
|
}
|
|
61534
61629
|
async function killStaleFrpc(deps) {
|
|
61535
61630
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
61536
|
-
const tomlPath =
|
|
61631
|
+
const tomlPath = import_node_path53.default.join(deps.dataDir, "frpc.toml");
|
|
61537
61632
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
61538
61633
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
61539
61634
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -61605,7 +61700,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
61605
61700
|
var TunnelManager = class {
|
|
61606
61701
|
constructor(deps) {
|
|
61607
61702
|
this.deps = deps;
|
|
61608
|
-
this.store = deps.store ?? new TunnelStore(
|
|
61703
|
+
this.store = deps.store ?? new TunnelStore(import_node_path54.default.join(deps.dataDir, "tunnel.json"));
|
|
61609
61704
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
61610
61705
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
61611
61706
|
}
|
|
@@ -61732,7 +61827,7 @@ var TunnelManager = class {
|
|
|
61732
61827
|
dataDir: this.deps.dataDir,
|
|
61733
61828
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
61734
61829
|
});
|
|
61735
|
-
const tomlPath =
|
|
61830
|
+
const tomlPath = import_node_path54.default.join(this.deps.dataDir, "frpc.toml");
|
|
61736
61831
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto13.default.randomBytes(3).toString("hex")}`;
|
|
61737
61832
|
const toml = buildFrpcToml({
|
|
61738
61833
|
serverAddr: t.frpsHost,
|
|
@@ -61747,9 +61842,9 @@ var TunnelManager = class {
|
|
|
61747
61842
|
const proc = (this.deps.spawnImpl ?? import_node_child_process13.spawn)(frpcBin, ["-c", tomlPath], {
|
|
61748
61843
|
stdio: ["ignore", "pipe", "pipe"]
|
|
61749
61844
|
});
|
|
61750
|
-
const logDir =
|
|
61845
|
+
const logDir = import_node_path54.default.join(this.deps.dataDir, "log");
|
|
61751
61846
|
import_node_fs43.default.mkdirSync(logDir, { recursive: true });
|
|
61752
|
-
const logFilePath =
|
|
61847
|
+
const logFilePath = import_node_path54.default.join(logDir, "frpc.log");
|
|
61753
61848
|
const logStream = import_node_fs43.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
61754
61849
|
logStream.on("error", () => {
|
|
61755
61850
|
});
|
|
@@ -61833,15 +61928,15 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
61833
61928
|
|
|
61834
61929
|
// src/tunnel/device-key.ts
|
|
61835
61930
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
61836
|
-
var
|
|
61931
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
61837
61932
|
var import_node_crypto14 = __toESM(require("crypto"), 1);
|
|
61838
61933
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
61839
61934
|
function deriveStableDeviceKey(opts = {}) {
|
|
61840
61935
|
const hostname = opts.hostname ?? import_node_os17.default.hostname();
|
|
61841
61936
|
const uid = opts.uid ?? (typeof import_node_os17.default.userInfo === "function" ? import_node_os17.default.userInfo().uid : 0);
|
|
61842
61937
|
const home = opts.home ?? import_node_os17.default.homedir();
|
|
61843
|
-
const defaultDataDir =
|
|
61844
|
-
const normalizedDataDir = opts.dataDir ?
|
|
61938
|
+
const defaultDataDir = import_node_path55.default.resolve(import_node_path55.default.join(home, ".clawd"));
|
|
61939
|
+
const normalizedDataDir = opts.dataDir ? import_node_path55.default.resolve(opts.dataDir) : null;
|
|
61845
61940
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
61846
61941
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
61847
61942
|
return import_node_crypto14.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
@@ -61849,11 +61944,11 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
61849
61944
|
|
|
61850
61945
|
// src/auth-store.ts
|
|
61851
61946
|
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
61852
|
-
var
|
|
61947
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
61853
61948
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
61854
61949
|
var AUTH_FILE_NAME = "auth.json";
|
|
61855
61950
|
function authFilePath(dataDir) {
|
|
61856
|
-
return
|
|
61951
|
+
return import_node_path56.default.join(dataDir, AUTH_FILE_NAME);
|
|
61857
61952
|
}
|
|
61858
61953
|
function loadOrCreateAuthFile(opts) {
|
|
61859
61954
|
const file = authFilePath(opts.dataDir);
|
|
@@ -61905,7 +62000,7 @@ function readAuthFile(file) {
|
|
|
61905
62000
|
}
|
|
61906
62001
|
}
|
|
61907
62002
|
function writeAuthFile(file, content) {
|
|
61908
|
-
import_node_fs44.default.mkdirSync(
|
|
62003
|
+
import_node_fs44.default.mkdirSync(import_node_path56.default.dirname(file), { recursive: true });
|
|
61909
62004
|
import_node_fs44.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
61910
62005
|
try {
|
|
61911
62006
|
import_node_fs44.default.chmodSync(file, 384);
|
|
@@ -61916,10 +62011,10 @@ function writeAuthFile(file, content) {
|
|
|
61916
62011
|
// src/owner-profile.ts
|
|
61917
62012
|
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
61918
62013
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
61919
|
-
var
|
|
62014
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
61920
62015
|
var PROFILE_FILENAME = "profile.json";
|
|
61921
62016
|
function profilePath(dataDir) {
|
|
61922
|
-
return
|
|
62017
|
+
return import_node_path57.default.join(dataDir, PROFILE_FILENAME);
|
|
61923
62018
|
}
|
|
61924
62019
|
function loadOwnerProfile(dataDir) {
|
|
61925
62020
|
let raw;
|
|
@@ -61957,12 +62052,12 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
61957
62052
|
|
|
61958
62053
|
// src/feishu-auth/owner-identity-store.ts
|
|
61959
62054
|
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
61960
|
-
var
|
|
62055
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
61961
62056
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
61962
62057
|
var OwnerIdentityStore = class {
|
|
61963
62058
|
file;
|
|
61964
62059
|
constructor(dataDir) {
|
|
61965
|
-
this.file =
|
|
62060
|
+
this.file = import_node_path58.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
61966
62061
|
}
|
|
61967
62062
|
read() {
|
|
61968
62063
|
let raw;
|
|
@@ -61995,7 +62090,7 @@ var OwnerIdentityStore = class {
|
|
|
61995
62090
|
};
|
|
61996
62091
|
}
|
|
61997
62092
|
write(record3) {
|
|
61998
|
-
import_node_fs46.default.mkdirSync(
|
|
62093
|
+
import_node_fs46.default.mkdirSync(import_node_path58.default.dirname(this.file), { recursive: true });
|
|
61999
62094
|
import_node_fs46.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
|
|
62000
62095
|
try {
|
|
62001
62096
|
import_node_fs46.default.chmodSync(this.file, 384);
|
|
@@ -62141,9 +62236,9 @@ var CentralClientError = class extends Error {
|
|
|
62141
62236
|
code;
|
|
62142
62237
|
cause;
|
|
62143
62238
|
};
|
|
62144
|
-
async function centralRequest(opts,
|
|
62239
|
+
async function centralRequest(opts, path100, init) {
|
|
62145
62240
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
62146
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
62241
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path100}`;
|
|
62147
62242
|
const ctrl = new AbortController();
|
|
62148
62243
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
62149
62244
|
let res;
|
|
@@ -62581,7 +62676,7 @@ function verifyConnectToken(args) {
|
|
|
62581
62676
|
|
|
62582
62677
|
// src/feishu-auth/server-key.ts
|
|
62583
62678
|
var fs66 = __toESM(require("fs"), 1);
|
|
62584
|
-
var
|
|
62679
|
+
var path71 = __toESM(require("path"), 1);
|
|
62585
62680
|
var FILE_NAME2 = "server-signing-key.json";
|
|
62586
62681
|
var ServerKeyStore = class {
|
|
62587
62682
|
constructor(dataDir) {
|
|
@@ -62589,7 +62684,7 @@ var ServerKeyStore = class {
|
|
|
62589
62684
|
}
|
|
62590
62685
|
dataDir;
|
|
62591
62686
|
filePath() {
|
|
62592
|
-
return
|
|
62687
|
+
return path71.join(this.dataDir, FILE_NAME2);
|
|
62593
62688
|
}
|
|
62594
62689
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
62595
62690
|
read() {
|
|
@@ -62624,7 +62719,7 @@ var ServerKeyStore = class {
|
|
|
62624
62719
|
init_protocol();
|
|
62625
62720
|
|
|
62626
62721
|
// src/handlers/index.ts
|
|
62627
|
-
var
|
|
62722
|
+
var import_node_path74 = __toESM(require("path"), 1);
|
|
62628
62723
|
|
|
62629
62724
|
// src/handlers/session.ts
|
|
62630
62725
|
init_protocol();
|
|
@@ -62632,7 +62727,7 @@ init_protocol();
|
|
|
62632
62727
|
// src/session/fork.ts
|
|
62633
62728
|
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
62634
62729
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
62635
|
-
var
|
|
62730
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
62636
62731
|
var import_node_crypto17 = require("crypto");
|
|
62637
62732
|
init_claude_history();
|
|
62638
62733
|
function readJsonlEntries(file) {
|
|
@@ -62649,19 +62744,19 @@ function readJsonlEntries(file) {
|
|
|
62649
62744
|
return out;
|
|
62650
62745
|
}
|
|
62651
62746
|
function forkSession(input) {
|
|
62652
|
-
const baseDir = input.baseDir ??
|
|
62653
|
-
let projectDir =
|
|
62654
|
-
let sourceFile =
|
|
62747
|
+
const baseDir = input.baseDir ?? import_node_path59.default.join(import_node_os19.default.homedir(), ".claude");
|
|
62748
|
+
let projectDir = import_node_path59.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
62749
|
+
let sourceFile = import_node_path59.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
62655
62750
|
if (!import_node_fs47.default.existsSync(sourceFile)) {
|
|
62656
62751
|
const found = findTranscriptByToolSessionId(
|
|
62657
|
-
|
|
62752
|
+
import_node_path59.default.join(baseDir, "projects"),
|
|
62658
62753
|
input.toolSessionId
|
|
62659
62754
|
);
|
|
62660
62755
|
if (!found) {
|
|
62661
62756
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
62662
62757
|
}
|
|
62663
62758
|
sourceFile = found;
|
|
62664
|
-
projectDir =
|
|
62759
|
+
projectDir = import_node_path59.default.dirname(found);
|
|
62665
62760
|
}
|
|
62666
62761
|
const entries = readJsonlEntries(sourceFile);
|
|
62667
62762
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -62690,8 +62785,8 @@ function forkSession(input) {
|
|
|
62690
62785
|
}
|
|
62691
62786
|
forkedLines.push(JSON.stringify(forked));
|
|
62692
62787
|
}
|
|
62693
|
-
const outDir = input.targetCwd ?
|
|
62694
|
-
const forkedFilePath =
|
|
62788
|
+
const outDir = input.targetCwd ? import_node_path59.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
62789
|
+
const forkedFilePath = import_node_path59.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
62695
62790
|
import_node_fs47.default.mkdirSync(outDir, { recursive: true });
|
|
62696
62791
|
import_node_fs47.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
62697
62792
|
return { forkedToolSessionId, forkedFilePath };
|
|
@@ -62701,16 +62796,16 @@ function forkSession(input) {
|
|
|
62701
62796
|
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
62702
62797
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
62703
62798
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
62704
|
-
var
|
|
62799
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
62705
62800
|
var import_node_module = require("module");
|
|
62706
62801
|
var import_node_child_process14 = require("child_process");
|
|
62707
62802
|
var import_meta5 = {};
|
|
62708
62803
|
function defaultRoots() {
|
|
62709
62804
|
const home = import_node_os20.default.homedir();
|
|
62710
62805
|
return {
|
|
62711
|
-
claudeProjectsDir:
|
|
62712
|
-
codexDir:
|
|
62713
|
-
clawdDir:
|
|
62806
|
+
claudeProjectsDir: import_node_path60.default.join(home, ".claude", "projects"),
|
|
62807
|
+
codexDir: import_node_path60.default.join(home, ".codex"),
|
|
62808
|
+
clawdDir: import_node_path60.default.join(home, ".clawd")
|
|
62714
62809
|
};
|
|
62715
62810
|
}
|
|
62716
62811
|
function width(s) {
|
|
@@ -62778,13 +62873,13 @@ async function scanClaude(roots) {
|
|
|
62778
62873
|
if (!d.isDirectory()) continue;
|
|
62779
62874
|
let files;
|
|
62780
62875
|
try {
|
|
62781
|
-
files = import_node_fs48.default.readdirSync(
|
|
62876
|
+
files = import_node_fs48.default.readdirSync(import_node_path60.default.join(roots.claudeProjectsDir, d.name));
|
|
62782
62877
|
} catch {
|
|
62783
62878
|
continue;
|
|
62784
62879
|
}
|
|
62785
62880
|
for (const name of files) {
|
|
62786
62881
|
if (!name.endsWith(".jsonl")) continue;
|
|
62787
|
-
const file =
|
|
62882
|
+
const file = import_node_path60.default.join(roots.claudeProjectsDir, d.name, name);
|
|
62788
62883
|
let st;
|
|
62789
62884
|
try {
|
|
62790
62885
|
st = import_node_fs48.default.statSync(file);
|
|
@@ -62914,7 +63009,7 @@ async function codexFromRows(rows) {
|
|
|
62914
63009
|
async function scanCodex(roots) {
|
|
62915
63010
|
let dbs = [];
|
|
62916
63011
|
try {
|
|
62917
|
-
dbs = import_node_fs48.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) =>
|
|
63012
|
+
dbs = import_node_fs48.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path60.default.join(roots.codexDir, n));
|
|
62918
63013
|
} catch {
|
|
62919
63014
|
}
|
|
62920
63015
|
if (!dbs.length) return [];
|
|
@@ -62923,14 +63018,14 @@ async function scanCodex(roots) {
|
|
|
62923
63018
|
}
|
|
62924
63019
|
async function scanExternalSessions(rootsIn) {
|
|
62925
63020
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
62926
|
-
const personaRoot =
|
|
63021
|
+
const personaRoot = import_node_path60.default.join(roots.clawdDir, "personas");
|
|
62927
63022
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
62928
63023
|
const out = [];
|
|
62929
63024
|
for (const c of all) {
|
|
62930
63025
|
if (c.skip) continue;
|
|
62931
63026
|
if (c.turns < 1) continue;
|
|
62932
63027
|
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
62933
|
-
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot +
|
|
63028
|
+
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path60.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path60.default.sep)) {
|
|
62934
63029
|
continue;
|
|
62935
63030
|
}
|
|
62936
63031
|
out.push({
|
|
@@ -62948,12 +63043,12 @@ async function scanExternalSessions(rootsIn) {
|
|
|
62948
63043
|
|
|
62949
63044
|
// src/session/import-ledger.ts
|
|
62950
63045
|
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
62951
|
-
var
|
|
63046
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
62952
63047
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
62953
63048
|
function readImportLedger(dataDir) {
|
|
62954
63049
|
try {
|
|
62955
63050
|
const parsed = JSON.parse(
|
|
62956
|
-
import_node_fs49.default.readFileSync(
|
|
63051
|
+
import_node_fs49.default.readFileSync(import_node_path61.default.join(dataDir, LEDGER_FILENAME), "utf8")
|
|
62957
63052
|
);
|
|
62958
63053
|
return Array.isArray(parsed) ? parsed : [];
|
|
62959
63054
|
} catch {
|
|
@@ -62961,7 +63056,7 @@ function readImportLedger(dataDir) {
|
|
|
62961
63056
|
}
|
|
62962
63057
|
}
|
|
62963
63058
|
function appendImportLedger(dataDir, entry) {
|
|
62964
|
-
const file =
|
|
63059
|
+
const file = import_node_path61.default.join(dataDir, LEDGER_FILENAME);
|
|
62965
63060
|
const entries = readImportLedger(dataDir);
|
|
62966
63061
|
entries.push(entry);
|
|
62967
63062
|
import_node_fs49.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
@@ -62969,7 +63064,7 @@ function appendImportLedger(dataDir, entry) {
|
|
|
62969
63064
|
|
|
62970
63065
|
// src/tools/transcript-search.ts
|
|
62971
63066
|
var import_node_fs50 = __toESM(require("fs"), 1);
|
|
62972
|
-
var
|
|
63067
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
62973
63068
|
var SNIPPET_PAD = 60;
|
|
62974
63069
|
var INJECTED_ENVELOPE_RE = /^<(system-reminder|command-name|command-message|command-args|local-command-stdout|local-command-stderr|task-notification|user-prompt-submit-hook|environment_context|user_instructions)\b/;
|
|
62975
63070
|
var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
|
|
@@ -63062,7 +63157,7 @@ function createCodexRolloutLocator(roots) {
|
|
|
63062
63157
|
return;
|
|
63063
63158
|
}
|
|
63064
63159
|
for (const entry of entries) {
|
|
63065
|
-
const full =
|
|
63160
|
+
const full = import_node_path62.default.join(dir, entry.name);
|
|
63066
63161
|
if (entry.isDirectory()) {
|
|
63067
63162
|
walk2(full, into);
|
|
63068
63163
|
continue;
|
|
@@ -63083,15 +63178,15 @@ function createCodexRolloutLocator(roots) {
|
|
|
63083
63178
|
// src/handlers/session.ts
|
|
63084
63179
|
init_protocol();
|
|
63085
63180
|
var import_node_os21 = __toESM(require("os"), 1);
|
|
63086
|
-
var
|
|
63181
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
63087
63182
|
function canReadSearchHit(ctx, file) {
|
|
63088
63183
|
if (!ctx || ctx.principal.kind === "owner") return true;
|
|
63089
63184
|
return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
|
|
63090
63185
|
}
|
|
63091
63186
|
var DEFAULT_SEARCH_LIMIT = 9;
|
|
63092
63187
|
function codexRolloutRoots(dataDir) {
|
|
63093
|
-
const roots = [
|
|
63094
|
-
if (dataDir) roots.push(
|
|
63188
|
+
const roots = [import_node_path63.default.join(import_node_os21.default.homedir(), ".codex", "sessions")];
|
|
63189
|
+
if (dataDir) roots.push(import_node_path63.default.join(dataDir, "codex-home", "sessions"));
|
|
63095
63190
|
return roots;
|
|
63096
63191
|
}
|
|
63097
63192
|
function buildSessionHandlers(deps) {
|
|
@@ -63640,7 +63735,7 @@ function buildPermissionHandlers(deps) {
|
|
|
63640
63735
|
}
|
|
63641
63736
|
|
|
63642
63737
|
// src/handlers/history.ts
|
|
63643
|
-
var
|
|
63738
|
+
var path78 = __toESM(require("path"), 1);
|
|
63644
63739
|
init_protocol();
|
|
63645
63740
|
|
|
63646
63741
|
// src/session/recent-dirs.ts
|
|
@@ -63658,7 +63753,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
63658
63753
|
}
|
|
63659
63754
|
|
|
63660
63755
|
// src/permission/persona-paths.ts
|
|
63661
|
-
var
|
|
63756
|
+
var path77 = __toESM(require("path"), 1);
|
|
63662
63757
|
function getAllowedPersonaIds(grants, action) {
|
|
63663
63758
|
const ids = /* @__PURE__ */ new Set();
|
|
63664
63759
|
for (const g2 of grants) {
|
|
@@ -63671,42 +63766,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
63671
63766
|
return ids;
|
|
63672
63767
|
}
|
|
63673
63768
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
63674
|
-
const target =
|
|
63769
|
+
const target = path77.resolve(absPath);
|
|
63675
63770
|
if (userWorkDir) {
|
|
63676
|
-
const u =
|
|
63677
|
-
const usep = u.endsWith(
|
|
63771
|
+
const u = path77.resolve(userWorkDir);
|
|
63772
|
+
const usep = u.endsWith(path77.sep) ? "" : path77.sep;
|
|
63678
63773
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
63679
63774
|
}
|
|
63680
|
-
const root =
|
|
63681
|
-
const sep4 = root.endsWith(
|
|
63775
|
+
const root = path77.resolve(personaRoot);
|
|
63776
|
+
const sep4 = root.endsWith(path77.sep) ? "" : path77.sep;
|
|
63682
63777
|
if (!target.startsWith(root + sep4)) return false;
|
|
63683
|
-
const rel =
|
|
63778
|
+
const rel = path77.relative(root, target);
|
|
63684
63779
|
if (!rel || rel.startsWith("..")) return false;
|
|
63685
|
-
const personaId2 = rel.split(
|
|
63780
|
+
const personaId2 = rel.split(path77.sep)[0];
|
|
63686
63781
|
if (!personaId2) return false;
|
|
63687
63782
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
63688
63783
|
if (allowed === "*") return true;
|
|
63689
63784
|
return allowed.has(personaId2);
|
|
63690
63785
|
}
|
|
63691
63786
|
function personaIdFromPath(absPath, personaRoot) {
|
|
63692
|
-
const root =
|
|
63693
|
-
const target =
|
|
63694
|
-
const sep4 = root.endsWith(
|
|
63787
|
+
const root = path77.resolve(personaRoot);
|
|
63788
|
+
const target = path77.resolve(absPath);
|
|
63789
|
+
const sep4 = root.endsWith(path77.sep) ? "" : path77.sep;
|
|
63695
63790
|
if (!target.startsWith(root + sep4)) return null;
|
|
63696
|
-
const rel =
|
|
63791
|
+
const rel = path77.relative(root, target);
|
|
63697
63792
|
if (!rel || rel.startsWith("..")) return null;
|
|
63698
|
-
const id = rel.split(
|
|
63793
|
+
const id = rel.split(path77.sep)[0];
|
|
63699
63794
|
return id || null;
|
|
63700
63795
|
}
|
|
63701
63796
|
function isPathWithin(dir, absPath) {
|
|
63702
|
-
const d =
|
|
63703
|
-
const t =
|
|
63704
|
-
const sep4 = d.endsWith(
|
|
63797
|
+
const d = path77.resolve(dir);
|
|
63798
|
+
const t = path77.resolve(absPath);
|
|
63799
|
+
const sep4 = d.endsWith(path77.sep) ? "" : path77.sep;
|
|
63705
63800
|
return t === d || t.startsWith(d + sep4);
|
|
63706
63801
|
}
|
|
63707
63802
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
63708
63803
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
63709
|
-
return personaIdFromPath(
|
|
63804
|
+
return personaIdFromPath(path77.resolve(absPath), personaRoot) === personaId2;
|
|
63710
63805
|
}
|
|
63711
63806
|
|
|
63712
63807
|
// src/handlers/history.ts
|
|
@@ -63759,7 +63854,7 @@ function buildHistoryHandlers(deps) {
|
|
|
63759
63854
|
if (!pid) return false;
|
|
63760
63855
|
return isGuestPathAllowed(
|
|
63761
63856
|
ctx.grants,
|
|
63762
|
-
|
|
63857
|
+
path78.join(personaRoot, pid),
|
|
63763
63858
|
personaRoot,
|
|
63764
63859
|
"read",
|
|
63765
63860
|
userWorkDir
|
|
@@ -63771,7 +63866,7 @@ function buildHistoryHandlers(deps) {
|
|
|
63771
63866
|
};
|
|
63772
63867
|
const list = async (frame, _client, ctx) => {
|
|
63773
63868
|
const args = HistoryListArgs.parse(frame);
|
|
63774
|
-
assertGuestPath(ctx,
|
|
63869
|
+
assertGuestPath(ctx, path78.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
63775
63870
|
const sessions = await history.listSessions(args);
|
|
63776
63871
|
return { response: { type: "history:list", sessions } };
|
|
63777
63872
|
};
|
|
@@ -63819,14 +63914,14 @@ function buildHistoryHandlers(deps) {
|
|
|
63819
63914
|
};
|
|
63820
63915
|
const subagents = async (frame, _client, ctx) => {
|
|
63821
63916
|
const args = HistorySubagentsArgs.parse(frame);
|
|
63822
|
-
assertGuestPath(ctx,
|
|
63917
|
+
assertGuestPath(ctx, path78.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
63823
63918
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
63824
63919
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
63825
63920
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
63826
63921
|
};
|
|
63827
63922
|
const subagentRead = async (frame, _client, ctx) => {
|
|
63828
63923
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
63829
|
-
assertGuestPath(ctx,
|
|
63924
|
+
assertGuestPath(ctx, path78.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
63830
63925
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
63831
63926
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
63832
63927
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -63836,7 +63931,7 @@ function buildHistoryHandlers(deps) {
|
|
|
63836
63931
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
63837
63932
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
63838
63933
|
const filtered = dirs.filter(
|
|
63839
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
63934
|
+
(d) => isGuestPathAllowed(ctx.grants, path78.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
63840
63935
|
);
|
|
63841
63936
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
63842
63937
|
}
|
|
@@ -63855,15 +63950,15 @@ function buildHistoryHandlers(deps) {
|
|
|
63855
63950
|
// src/handlers/projects.ts
|
|
63856
63951
|
var fs71 = __toESM(require("fs"), 1);
|
|
63857
63952
|
var os23 = __toESM(require("os"), 1);
|
|
63858
|
-
var
|
|
63953
|
+
var path79 = __toESM(require("path"), 1);
|
|
63859
63954
|
var import_node_child_process15 = require("child_process");
|
|
63860
63955
|
init_protocol();
|
|
63861
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
63956
|
+
var DEFAULT_PROJECTS_ROOT = path79.join(os23.homedir(), "Documents", "ChatGPT");
|
|
63862
63957
|
function allocateDir(root, name) {
|
|
63863
|
-
let candidate =
|
|
63958
|
+
let candidate = path79.join(root, name);
|
|
63864
63959
|
let n = 2;
|
|
63865
63960
|
while (fs71.existsSync(candidate)) {
|
|
63866
|
-
candidate =
|
|
63961
|
+
candidate = path79.join(root, `${name} ${n}`);
|
|
63867
63962
|
n += 1;
|
|
63868
63963
|
}
|
|
63869
63964
|
return candidate;
|
|
@@ -63948,7 +64043,7 @@ function buildProjectHandlers(deps) {
|
|
|
63948
64043
|
}
|
|
63949
64044
|
|
|
63950
64045
|
// src/handlers/workspace.ts
|
|
63951
|
-
var
|
|
64046
|
+
var path80 = __toESM(require("path"), 1);
|
|
63952
64047
|
var os24 = __toESM(require("os"), 1);
|
|
63953
64048
|
init_protocol();
|
|
63954
64049
|
init_protocol();
|
|
@@ -63990,22 +64085,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
63990
64085
|
const args = WorkspaceListArgs.parse(frame);
|
|
63991
64086
|
const isGuest = ctx?.principal.kind === "guest";
|
|
63992
64087
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os24.homedir();
|
|
63993
|
-
const resolvedCwd =
|
|
63994
|
-
const target = args.path ?
|
|
64088
|
+
const resolvedCwd = path80.resolve(args.cwd ?? fallbackCwd);
|
|
64089
|
+
const target = args.path ? path80.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
63995
64090
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
63996
64091
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
63997
64092
|
return { response: { type: "workspace:list", ...res } };
|
|
63998
64093
|
};
|
|
63999
64094
|
const read = async (frame, _client, ctx) => {
|
|
64000
64095
|
const args = WorkspaceReadArgs.parse(frame);
|
|
64001
|
-
const target =
|
|
64096
|
+
const target = path80.isAbsolute(args.path) ? path80.resolve(args.path) : path80.resolve(args.cwd, args.path);
|
|
64002
64097
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
64003
64098
|
const res = workspace.read(args);
|
|
64004
64099
|
return { response: { type: "workspace:read", ...res } };
|
|
64005
64100
|
};
|
|
64006
64101
|
const skillsList = async (frame, _client, ctx) => {
|
|
64007
64102
|
const args = SkillsListArgs.parse(frame);
|
|
64008
|
-
const cwdAbs =
|
|
64103
|
+
const cwdAbs = path80.resolve(args.cwd);
|
|
64009
64104
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
64010
64105
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
64011
64106
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -64017,7 +64112,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
64017
64112
|
};
|
|
64018
64113
|
const agentsList = async (frame, _client, ctx) => {
|
|
64019
64114
|
const args = AgentsListArgs.parse(frame);
|
|
64020
|
-
const cwdAbs =
|
|
64115
|
+
const cwdAbs = path80.resolve(args.cwd);
|
|
64021
64116
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
64022
64117
|
if (args.tool === "codex") {
|
|
64023
64118
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -64039,18 +64134,18 @@ function buildWorkspaceHandlers(deps) {
|
|
|
64039
64134
|
}
|
|
64040
64135
|
|
|
64041
64136
|
// src/handlers/git.ts
|
|
64042
|
-
var
|
|
64137
|
+
var path82 = __toESM(require("path"), 1);
|
|
64043
64138
|
init_protocol();
|
|
64044
64139
|
init_protocol();
|
|
64045
64140
|
|
|
64046
64141
|
// src/workspace/git.ts
|
|
64047
64142
|
var import_node_child_process16 = require("child_process");
|
|
64048
64143
|
var import_node_fs51 = __toESM(require("fs"), 1);
|
|
64049
|
-
var
|
|
64144
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
64050
64145
|
var import_node_util = require("util");
|
|
64051
64146
|
var pexec = (0, import_node_util.promisify)(import_node_child_process16.execFile);
|
|
64052
64147
|
function normalizePath(p2) {
|
|
64053
|
-
const resolved =
|
|
64148
|
+
const resolved = import_node_path64.default.resolve(p2);
|
|
64054
64149
|
try {
|
|
64055
64150
|
return import_node_fs51.default.realpathSync(resolved);
|
|
64056
64151
|
} catch {
|
|
@@ -64126,7 +64221,7 @@ async function listGitBranches(cwd) {
|
|
|
64126
64221
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
64127
64222
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
64128
64223
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
64129
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
64224
|
+
if (!isGuestPathAllowed(ctx.grants, path82.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
64130
64225
|
throw new ClawdError(
|
|
64131
64226
|
ERROR_CODES.UNAUTHORIZED,
|
|
64132
64227
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -64974,21 +65069,21 @@ function computeMethodAccess(args) {
|
|
|
64974
65069
|
}
|
|
64975
65070
|
|
|
64976
65071
|
// src/version.ts
|
|
64977
|
-
var version = "0.2.
|
|
65072
|
+
var version = "0.2.469".length > 0 ? "0.2.469" : "dev";
|
|
64978
65073
|
|
|
64979
65074
|
// src/cli-probe/probe.ts
|
|
64980
65075
|
var fs73 = __toESM(require("fs"), 1);
|
|
64981
|
-
var
|
|
65076
|
+
var path83 = __toESM(require("path"), 1);
|
|
64982
65077
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
64983
65078
|
var BIN_NAME = "clawd";
|
|
64984
65079
|
var MAX_PARENT_HOPS = 5;
|
|
64985
65080
|
function probeGlobalCli(pathEnv) {
|
|
64986
65081
|
if (!pathEnv) return null;
|
|
64987
|
-
for (const dir of pathEnv.split(
|
|
65082
|
+
for (const dir of pathEnv.split(path83.delimiter)) {
|
|
64988
65083
|
if (!dir) continue;
|
|
64989
65084
|
let real;
|
|
64990
65085
|
try {
|
|
64991
|
-
real = fs73.realpathSync(
|
|
65086
|
+
real = fs73.realpathSync(path83.join(dir, BIN_NAME));
|
|
64992
65087
|
} catch {
|
|
64993
65088
|
continue;
|
|
64994
65089
|
}
|
|
@@ -64998,15 +65093,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
64998
65093
|
return null;
|
|
64999
65094
|
}
|
|
65000
65095
|
function readOwnPackageVersion(entryPath) {
|
|
65001
|
-
let dir =
|
|
65096
|
+
let dir = path83.dirname(entryPath);
|
|
65002
65097
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
65003
65098
|
try {
|
|
65004
|
-
const raw = fs73.readFileSync(
|
|
65099
|
+
const raw = fs73.readFileSync(path83.join(dir, "package.json"), "utf8");
|
|
65005
65100
|
const pkg = JSON.parse(raw);
|
|
65006
65101
|
if (pkg.name !== PKG_NAME) return null;
|
|
65007
65102
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
65008
65103
|
} catch {
|
|
65009
|
-
const parent =
|
|
65104
|
+
const parent = path83.dirname(dir);
|
|
65010
65105
|
if (parent === dir) return null;
|
|
65011
65106
|
dir = parent;
|
|
65012
65107
|
}
|
|
@@ -65178,7 +65273,7 @@ function buildPersonaHandlers(deps) {
|
|
|
65178
65273
|
}
|
|
65179
65274
|
|
|
65180
65275
|
// src/handlers/attachment.ts
|
|
65181
|
-
var
|
|
65276
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
65182
65277
|
init_protocol();
|
|
65183
65278
|
init_protocol();
|
|
65184
65279
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -65258,12 +65353,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
65258
65353
|
`session ${args.sessionId} scope unresolved`
|
|
65259
65354
|
);
|
|
65260
65355
|
}
|
|
65261
|
-
const cwdAbs =
|
|
65262
|
-
const candidateAbs =
|
|
65356
|
+
const cwdAbs = import_node_path65.default.resolve(sessionFile.cwd);
|
|
65357
|
+
const candidateAbs = import_node_path65.default.isAbsolute(args.relPath) ? import_node_path65.default.resolve(args.relPath) : import_node_path65.default.resolve(cwdAbs, args.relPath);
|
|
65263
65358
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
65264
65359
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
65265
65360
|
const entry = entries.find((e) => {
|
|
65266
|
-
const storedAbs =
|
|
65361
|
+
const storedAbs = import_node_path65.default.isAbsolute(e.relPath) ? import_node_path65.default.resolve(e.relPath) : import_node_path65.default.resolve(cwdAbs, e.relPath);
|
|
65267
65362
|
return storedAbs === candidateAbs && !e.stale;
|
|
65268
65363
|
});
|
|
65269
65364
|
if (!entry) {
|
|
@@ -65288,7 +65383,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
65288
65383
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
65289
65384
|
const f = deps.sessionStore.read(sessionId);
|
|
65290
65385
|
if (!f) return;
|
|
65291
|
-
assertGuestAttachmentPath(ctx,
|
|
65386
|
+
assertGuestAttachmentPath(ctx, import_node_path65.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
65292
65387
|
}
|
|
65293
65388
|
const groupAdd = async (frame, _client, ctx) => {
|
|
65294
65389
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -65303,8 +65398,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
65303
65398
|
if (!scope) {
|
|
65304
65399
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
65305
65400
|
}
|
|
65306
|
-
const cwdAbs =
|
|
65307
|
-
const candidateAbs =
|
|
65401
|
+
const cwdAbs = import_node_path65.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
65402
|
+
const candidateAbs = import_node_path65.default.isAbsolute(args.relPath) ? import_node_path65.default.resolve(args.relPath) : import_node_path65.default.resolve(cwdAbs, args.relPath);
|
|
65308
65403
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
65309
65404
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
65310
65405
|
const size = 0;
|
|
@@ -65363,19 +65458,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
65363
65458
|
|
|
65364
65459
|
// src/handlers/extension.ts
|
|
65365
65460
|
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
65366
|
-
var
|
|
65461
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
65367
65462
|
init_protocol();
|
|
65368
65463
|
|
|
65369
65464
|
// src/extension/bundle-zip.ts
|
|
65370
65465
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
65371
|
-
var
|
|
65466
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
65372
65467
|
var import_node_crypto18 = __toESM(require("crypto"), 1);
|
|
65373
65468
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
65374
65469
|
async function bundleExtensionDir(dir) {
|
|
65375
65470
|
const entries = await listFilesSorted(dir);
|
|
65376
65471
|
const zip = new import_jszip2.default();
|
|
65377
65472
|
for (const rel of entries) {
|
|
65378
|
-
const abs =
|
|
65473
|
+
const abs = import_node_path66.default.join(dir, rel);
|
|
65379
65474
|
const content = await import_promises14.default.readFile(abs);
|
|
65380
65475
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
65381
65476
|
}
|
|
@@ -65396,7 +65491,7 @@ async function listFilesSorted(rootDir) {
|
|
|
65396
65491
|
return out;
|
|
65397
65492
|
}
|
|
65398
65493
|
async function walk(absRoot, relPrefix, out) {
|
|
65399
|
-
const dirAbs =
|
|
65494
|
+
const dirAbs = import_node_path66.default.join(absRoot, relPrefix);
|
|
65400
65495
|
const entries = await import_promises14.default.readdir(dirAbs, { withFileTypes: true });
|
|
65401
65496
|
for (const e of entries) {
|
|
65402
65497
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -65450,25 +65545,25 @@ function computePublishCheck(args) {
|
|
|
65450
65545
|
|
|
65451
65546
|
// src/extension/install-flow.ts
|
|
65452
65547
|
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
65453
|
-
var
|
|
65548
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
65454
65549
|
var import_node_os24 = __toESM(require("os"), 1);
|
|
65455
65550
|
var import_node_crypto19 = __toESM(require("crypto"), 1);
|
|
65456
65551
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
65457
65552
|
|
|
65458
65553
|
// src/extension/paths.ts
|
|
65459
65554
|
var import_node_os23 = __toESM(require("os"), 1);
|
|
65460
|
-
var
|
|
65555
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
65461
65556
|
function clawdHomeRoot(override) {
|
|
65462
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
65557
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path67.default.join(import_node_os23.default.homedir(), ".clawd");
|
|
65463
65558
|
}
|
|
65464
65559
|
function extensionsRoot(override) {
|
|
65465
|
-
return
|
|
65560
|
+
return import_node_path67.default.join(clawdHomeRoot(override), "extensions");
|
|
65466
65561
|
}
|
|
65467
65562
|
function publishedChannelsFile(override) {
|
|
65468
|
-
return
|
|
65563
|
+
return import_node_path67.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
65469
65564
|
}
|
|
65470
65565
|
function bundleCacheRoot(override) {
|
|
65471
|
-
return
|
|
65566
|
+
return import_node_path67.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
65472
65567
|
}
|
|
65473
65568
|
|
|
65474
65569
|
// src/extension/install-flow.ts
|
|
@@ -65495,7 +65590,7 @@ async function installFromChannel(args, deps) {
|
|
|
65495
65590
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
65496
65591
|
}
|
|
65497
65592
|
for (const name of Object.keys(zip.files)) {
|
|
65498
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
65593
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path68.default.isAbsolute(name)) {
|
|
65499
65594
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
65500
65595
|
}
|
|
65501
65596
|
}
|
|
@@ -65527,7 +65622,7 @@ async function installFromChannel(args, deps) {
|
|
|
65527
65622
|
);
|
|
65528
65623
|
}
|
|
65529
65624
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
65530
|
-
const destDir =
|
|
65625
|
+
const destDir = import_node_path68.default.join(deps.extensionsRoot, localExtId);
|
|
65531
65626
|
let destExists = false;
|
|
65532
65627
|
try {
|
|
65533
65628
|
await import_promises15.default.access(destDir);
|
|
@@ -65541,16 +65636,16 @@ async function installFromChannel(args, deps) {
|
|
|
65541
65636
|
);
|
|
65542
65637
|
}
|
|
65543
65638
|
const stage = await import_promises15.default.mkdtemp(
|
|
65544
|
-
|
|
65639
|
+
import_node_path68.default.join(import_node_os24.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
65545
65640
|
);
|
|
65546
65641
|
try {
|
|
65547
65642
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
65548
|
-
const dest =
|
|
65643
|
+
const dest = import_node_path68.default.join(stage, name);
|
|
65549
65644
|
if (entry.dir) {
|
|
65550
65645
|
await import_promises15.default.mkdir(dest, { recursive: true });
|
|
65551
65646
|
continue;
|
|
65552
65647
|
}
|
|
65553
|
-
await import_promises15.default.mkdir(
|
|
65648
|
+
await import_promises15.default.mkdir(import_node_path68.default.dirname(dest), { recursive: true });
|
|
65554
65649
|
if (name === "manifest.json") {
|
|
65555
65650
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
65556
65651
|
await import_promises15.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -65571,7 +65666,7 @@ async function installFromChannel(args, deps) {
|
|
|
65571
65666
|
|
|
65572
65667
|
// src/extension/update-flow.ts
|
|
65573
65668
|
var import_promises16 = __toESM(require("fs/promises"), 1);
|
|
65574
|
-
var
|
|
65669
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
65575
65670
|
var import_node_os25 = __toESM(require("os"), 1);
|
|
65576
65671
|
var import_node_crypto20 = __toESM(require("crypto"), 1);
|
|
65577
65672
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -65588,11 +65683,11 @@ async function updateFromChannel(args, deps) {
|
|
|
65588
65683
|
channelRef.extId,
|
|
65589
65684
|
channelRef.ownerPrincipalId
|
|
65590
65685
|
);
|
|
65591
|
-
const liveDir =
|
|
65686
|
+
const liveDir = import_node_path69.default.join(deps.extensionsRoot, localExtId);
|
|
65592
65687
|
const prevDir = `${liveDir}.prev`;
|
|
65593
65688
|
let existingVersion;
|
|
65594
65689
|
try {
|
|
65595
|
-
const raw = await import_promises16.default.readFile(
|
|
65690
|
+
const raw = await import_promises16.default.readFile(import_node_path69.default.join(liveDir, "manifest.json"), "utf8");
|
|
65596
65691
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
65597
65692
|
if (!parsed2.success) {
|
|
65598
65693
|
throw new UpdateError(
|
|
@@ -65625,7 +65720,7 @@ async function updateFromChannel(args, deps) {
|
|
|
65625
65720
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
65626
65721
|
}
|
|
65627
65722
|
for (const name of Object.keys(zip.files)) {
|
|
65628
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
65723
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path69.default.isAbsolute(name)) {
|
|
65629
65724
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
65630
65725
|
}
|
|
65631
65726
|
}
|
|
@@ -65660,16 +65755,16 @@ async function updateFromChannel(args, deps) {
|
|
|
65660
65755
|
await import_promises16.default.rm(prevDir, { recursive: true, force: true });
|
|
65661
65756
|
await import_promises16.default.rename(liveDir, prevDir);
|
|
65662
65757
|
const stage = await import_promises16.default.mkdtemp(
|
|
65663
|
-
|
|
65758
|
+
import_node_path69.default.join(import_node_os25.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
65664
65759
|
);
|
|
65665
65760
|
try {
|
|
65666
65761
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
65667
|
-
const dest =
|
|
65762
|
+
const dest = import_node_path69.default.join(stage, name);
|
|
65668
65763
|
if (entry.dir) {
|
|
65669
65764
|
await import_promises16.default.mkdir(dest, { recursive: true });
|
|
65670
65765
|
continue;
|
|
65671
65766
|
}
|
|
65672
|
-
await import_promises16.default.mkdir(
|
|
65767
|
+
await import_promises16.default.mkdir(import_node_path69.default.dirname(dest), { recursive: true });
|
|
65673
65768
|
if (name === "manifest.json") {
|
|
65674
65769
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
65675
65770
|
await import_promises16.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -65736,7 +65831,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
65736
65831
|
);
|
|
65737
65832
|
}
|
|
65738
65833
|
}
|
|
65739
|
-
const manifestPath =
|
|
65834
|
+
const manifestPath = import_node_path70.default.join(root, extId, "manifest.json");
|
|
65740
65835
|
const manifest = await readManifest(root, extId);
|
|
65741
65836
|
const next = { ...manifest, version: newVersion };
|
|
65742
65837
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -65744,7 +65839,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
65744
65839
|
await import_promises17.default.rename(tmp, manifestPath);
|
|
65745
65840
|
}
|
|
65746
65841
|
async function readManifest(root, extId) {
|
|
65747
|
-
const file =
|
|
65842
|
+
const file = import_node_path70.default.join(root, extId, "manifest.json");
|
|
65748
65843
|
let raw;
|
|
65749
65844
|
try {
|
|
65750
65845
|
raw = await import_promises17.default.readFile(file, "utf8");
|
|
@@ -65828,7 +65923,7 @@ function buildExtensionHandlers(deps) {
|
|
|
65828
65923
|
};
|
|
65829
65924
|
async function buildSnapshotMeta(extId) {
|
|
65830
65925
|
const manifest = await readManifest(deps.root, extId);
|
|
65831
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
65926
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path70.default.join(deps.root, extId));
|
|
65832
65927
|
return { manifest, contentHash: sha256, buffer };
|
|
65833
65928
|
}
|
|
65834
65929
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -66071,7 +66166,7 @@ var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
|
66071
66166
|
|
|
66072
66167
|
// src/handlers/app-builder.ts
|
|
66073
66168
|
init_protocol();
|
|
66074
|
-
var
|
|
66169
|
+
var import_node_path71 = require("path");
|
|
66075
66170
|
var import_node_fs52 = require("fs");
|
|
66076
66171
|
var DEFAULT_TEMPLATE = "nestjs-react";
|
|
66077
66172
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
@@ -66218,13 +66313,13 @@ function buildAppBuilderHandlers(deps) {
|
|
|
66218
66313
|
const created = await deps.createProjectOnDisk({
|
|
66219
66314
|
store: userStore,
|
|
66220
66315
|
name: f.name,
|
|
66221
|
-
templateSrcDir: (0,
|
|
66222
|
-
scaffoldScript: (0,
|
|
66316
|
+
templateSrcDir: (0, import_node_path71.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE),
|
|
66317
|
+
scaffoldScript: (0, import_node_path71.join)(deps.deployKitRoot, "scripts", "new-extension.sh"),
|
|
66223
66318
|
reservedPorts,
|
|
66224
66319
|
// 凭据只进 scaffold 子进程的 env,且**只给这个 persona 的 kit 模板声明要的那几个变量**
|
|
66225
66320
|
// (M1b Step 5)。整表塞进去粒度只到「进程」——那会把 service-role key 交给一个用不到
|
|
66226
66321
|
// 它的脚本。new-extension.sh 用它把模板的 `${VAR}` 渲成项目可跑的 server/.env。
|
|
66227
|
-
extraEnv: secretsForKit(deps.readSecrets?.(), (0,
|
|
66322
|
+
extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path71.join)(personaRoot, "extension-kit")),
|
|
66228
66323
|
...deps.logger ? { logger: deps.logger } : {}
|
|
66229
66324
|
});
|
|
66230
66325
|
project = created.project;
|
|
@@ -66423,7 +66518,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
66423
66518
|
await userStore.clearPublishJob(args.name);
|
|
66424
66519
|
}
|
|
66425
66520
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
66426
|
-
const scriptPath = (0,
|
|
66521
|
+
const scriptPath = (0, import_node_path71.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
66427
66522
|
deps.logger?.info("app-builder.publish.start", {
|
|
66428
66523
|
name: args.name,
|
|
66429
66524
|
sessionId: boundSession.sessionId,
|
|
@@ -66439,7 +66534,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
66439
66534
|
// 凭据只进 publish.sh 这个子进程的 env,且只给它的 kit 模板声明要的那几个变量
|
|
66440
66535
|
// (M1b Step 5)。那个进程里跑着 `eval "$BUILD_CMD"`——项目自带的构建命令会继承这份
|
|
66441
66536
|
// env,多给一个变量就是多交一个凭据给它。personaRoot 上面已按绑定 session 的 persona 解析。
|
|
66442
|
-
extraEnv: secretsForKit(deps.readSecrets?.(), (0,
|
|
66537
|
+
extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path71.join)(personaRoot, "extension-kit")),
|
|
66443
66538
|
hooks: {
|
|
66444
66539
|
// 元数据每次写盘(publishJob 起落 / prodUrl 回填)后重推一帧:UI 渲染 PublishProgress
|
|
66445
66540
|
// 三段 checklist 依赖 project.publishJob.status==='in-flight',而 publishJob 字段只有
|
|
@@ -67175,7 +67270,7 @@ function buildVisitorHandlers(deps) {
|
|
|
67175
67270
|
|
|
67176
67271
|
// src/extension/registry.ts
|
|
67177
67272
|
var import_promises19 = __toESM(require("fs/promises"), 1);
|
|
67178
|
-
var
|
|
67273
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
67179
67274
|
async function loadAll(root) {
|
|
67180
67275
|
let entries;
|
|
67181
67276
|
try {
|
|
@@ -67188,13 +67283,13 @@ async function loadAll(root) {
|
|
|
67188
67283
|
for (const ent of entries) {
|
|
67189
67284
|
if (!ent.isDirectory()) continue;
|
|
67190
67285
|
if (ent.name.startsWith(".")) continue;
|
|
67191
|
-
records.push(await loadOne(
|
|
67286
|
+
records.push(await loadOne(import_node_path72.default.join(root, ent.name), ent.name));
|
|
67192
67287
|
}
|
|
67193
67288
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
67194
67289
|
return records;
|
|
67195
67290
|
}
|
|
67196
67291
|
async function loadOne(dir, dirName) {
|
|
67197
|
-
const manifestPath =
|
|
67292
|
+
const manifestPath = import_node_path72.default.join(dir, "manifest.json");
|
|
67198
67293
|
let raw;
|
|
67199
67294
|
try {
|
|
67200
67295
|
raw = await import_promises19.default.readFile(manifestPath, "utf8");
|
|
@@ -67239,7 +67334,7 @@ async function loadOne(dir, dirName) {
|
|
|
67239
67334
|
|
|
67240
67335
|
// src/extension/uninstall.ts
|
|
67241
67336
|
var import_promises20 = __toESM(require("fs/promises"), 1);
|
|
67242
|
-
var
|
|
67337
|
+
var import_node_path73 = __toESM(require("path"), 1);
|
|
67243
67338
|
var UninstallError = class extends Error {
|
|
67244
67339
|
constructor(code, message) {
|
|
67245
67340
|
super(message);
|
|
@@ -67248,7 +67343,7 @@ var UninstallError = class extends Error {
|
|
|
67248
67343
|
code;
|
|
67249
67344
|
};
|
|
67250
67345
|
async function uninstall(deps) {
|
|
67251
|
-
const dir =
|
|
67346
|
+
const dir = import_node_path73.default.join(deps.root, deps.extId);
|
|
67252
67347
|
try {
|
|
67253
67348
|
await import_promises20.default.access(dir);
|
|
67254
67349
|
} catch {
|
|
@@ -67484,7 +67579,7 @@ function buildMethodHandlers(deps) {
|
|
|
67484
67579
|
broadcast: deps.broadcastToOwners
|
|
67485
67580
|
}),
|
|
67486
67581
|
...buildMasterHandlers({
|
|
67487
|
-
authorityTablePath:
|
|
67582
|
+
authorityTablePath: import_node_path74.default.join(deps.masterDataDir, "master-authority.json")
|
|
67488
67583
|
}),
|
|
67489
67584
|
...buildTopicHandlers({
|
|
67490
67585
|
topicStore: deps.topicStore,
|
|
@@ -67530,8 +67625,8 @@ function refreshPathFromLoginShell() {
|
|
|
67530
67625
|
timeout: 3e3,
|
|
67531
67626
|
stdio: ["ignore", "pipe", "ignore"]
|
|
67532
67627
|
});
|
|
67533
|
-
const
|
|
67534
|
-
if (
|
|
67628
|
+
const path100 = out.trim();
|
|
67629
|
+
if (path100) process.env.PATH = path100;
|
|
67535
67630
|
} catch {
|
|
67536
67631
|
}
|
|
67537
67632
|
}
|
|
@@ -67657,7 +67752,7 @@ function buildOnboardingHandlers(deps) {
|
|
|
67657
67752
|
// src/app-builder-plugin/project-store.ts
|
|
67658
67753
|
var import_node_fs53 = require("fs");
|
|
67659
67754
|
var import_node_child_process21 = require("child_process");
|
|
67660
|
-
var
|
|
67755
|
+
var import_node_path75 = require("path");
|
|
67661
67756
|
init_protocol();
|
|
67662
67757
|
var PROJECTS_DIR = "projects";
|
|
67663
67758
|
var META_FILE = ".clawd-project.json";
|
|
@@ -67687,14 +67782,14 @@ var ProjectStore = class {
|
|
|
67687
67782
|
}
|
|
67688
67783
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
67689
67784
|
metaPath(name) {
|
|
67690
|
-
return (0,
|
|
67785
|
+
return (0, import_node_path75.join)(this.projectsRoot(), name, META_FILE);
|
|
67691
67786
|
}
|
|
67692
67787
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
67693
67788
|
projectDir(name) {
|
|
67694
|
-
return (0,
|
|
67789
|
+
return (0, import_node_path75.join)(this.projectsRoot(), name);
|
|
67695
67790
|
}
|
|
67696
67791
|
projectsRoot() {
|
|
67697
|
-
return (0,
|
|
67792
|
+
return (0, import_node_path75.join)(this.root, PROJECTS_DIR);
|
|
67698
67793
|
}
|
|
67699
67794
|
async list() {
|
|
67700
67795
|
let entries;
|
|
@@ -68200,7 +68295,7 @@ var PublishJobRegistry = class {
|
|
|
68200
68295
|
// src/app-builder-plugin/publish-job-runner.ts
|
|
68201
68296
|
var import_node_child_process23 = require("child_process");
|
|
68202
68297
|
var import_node_fs54 = require("fs");
|
|
68203
|
-
var
|
|
68298
|
+
var import_node_path76 = require("path");
|
|
68204
68299
|
|
|
68205
68300
|
// src/app-builder-plugin/publish-stage-parser.ts
|
|
68206
68301
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -68232,7 +68327,7 @@ async function startPublishJob(deps, args) {
|
|
|
68232
68327
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
68233
68328
|
}
|
|
68234
68329
|
const projDir = projectDir(args.name);
|
|
68235
|
-
const logPath = (0,
|
|
68330
|
+
const logPath = (0, import_node_path76.join)(projDir, ".publish.log");
|
|
68236
68331
|
let logStream = null;
|
|
68237
68332
|
try {
|
|
68238
68333
|
logStream = (0, import_node_fs54.createWriteStream)(logPath, { flags: "w" });
|
|
@@ -68579,9 +68674,9 @@ async function recoverInterruptedPublishJobs(store, logger) {
|
|
|
68579
68674
|
|
|
68580
68675
|
// src/app-builder-plugin/mcp-config.ts
|
|
68581
68676
|
var import_node_fs55 = __toESM(require("fs"), 1);
|
|
68582
|
-
var
|
|
68677
|
+
var import_node_path77 = __toESM(require("path"), 1);
|
|
68583
68678
|
function appBuilderMcpConfigPath(dataDir) {
|
|
68584
|
-
return
|
|
68679
|
+
return import_node_path77.default.join(dataDir, "app-builder.mcp.json");
|
|
68585
68680
|
}
|
|
68586
68681
|
function writeAppBuilderMcpConfig(args) {
|
|
68587
68682
|
const cfgPath = appBuilderMcpConfigPath(args.dataDir);
|
|
@@ -68595,8 +68690,8 @@ function writeAppBuilderMcpConfig(args) {
|
|
|
68595
68690
|
env: {
|
|
68596
68691
|
CLAWD_DAEMON_TOKEN: args.daemonToken,
|
|
68597
68692
|
CLAWD_DAEMON_URL: args.daemonUrl,
|
|
68598
|
-
CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT:
|
|
68599
|
-
CLAWD_APP_BUILDER_PUBLISH_SCRIPT:
|
|
68693
|
+
CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT: import_node_path77.default.join(args.deployKitScriptsDir, "new-extension.sh"),
|
|
68694
|
+
CLAWD_APP_BUILDER_PUBLISH_SCRIPT: import_node_path77.default.join(args.deployKitScriptsDir, "publish.sh"),
|
|
68600
68695
|
...args.logPath ? { CLAWD_APP_BUILDER_LOG: args.logPath } : {}
|
|
68601
68696
|
}
|
|
68602
68697
|
}
|
|
@@ -68644,7 +68739,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
68644
68739
|
|
|
68645
68740
|
// src/extension/runtime.ts
|
|
68646
68741
|
var import_node_child_process25 = require("child_process");
|
|
68647
|
-
var
|
|
68742
|
+
var import_node_path78 = __toESM(require("path"), 1);
|
|
68648
68743
|
var import_promises21 = require("timers/promises");
|
|
68649
68744
|
|
|
68650
68745
|
// src/extension/port-allocator.ts
|
|
@@ -68745,7 +68840,7 @@ var Runtime = class {
|
|
|
68745
68840
|
/\$CLAWOS_EXT_PORT/g,
|
|
68746
68841
|
String(port)
|
|
68747
68842
|
);
|
|
68748
|
-
const dir =
|
|
68843
|
+
const dir = import_node_path78.default.join(this.root, extId);
|
|
68749
68844
|
const env = {
|
|
68750
68845
|
...process.env,
|
|
68751
68846
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -68857,7 +68952,7 @@ ${handle.stderrTail}`
|
|
|
68857
68952
|
|
|
68858
68953
|
// src/extension/published-channels.ts
|
|
68859
68954
|
var import_promises22 = __toESM(require("fs/promises"), 1);
|
|
68860
|
-
var
|
|
68955
|
+
var import_node_path79 = __toESM(require("path"), 1);
|
|
68861
68956
|
init_zod();
|
|
68862
68957
|
var PublishedChannelsError = class extends Error {
|
|
68863
68958
|
constructor(code, message) {
|
|
@@ -68956,7 +69051,7 @@ var PublishedChannelStore = class {
|
|
|
68956
69051
|
)
|
|
68957
69052
|
};
|
|
68958
69053
|
const tmp = `${this.filePath}.tmp`;
|
|
68959
|
-
await import_promises22.default.mkdir(
|
|
69054
|
+
await import_promises22.default.mkdir(import_node_path79.default.dirname(this.filePath), { recursive: true });
|
|
68960
69055
|
await import_promises22.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
68961
69056
|
await import_promises22.default.rename(tmp, this.filePath);
|
|
68962
69057
|
}
|
|
@@ -68964,7 +69059,7 @@ var PublishedChannelStore = class {
|
|
|
68964
69059
|
|
|
68965
69060
|
// src/extension/bundle-cache.ts
|
|
68966
69061
|
var import_promises23 = __toESM(require("fs/promises"), 1);
|
|
68967
|
-
var
|
|
69062
|
+
var import_node_path80 = __toESM(require("path"), 1);
|
|
68968
69063
|
var BundleCache = class {
|
|
68969
69064
|
constructor(rootDir) {
|
|
68970
69065
|
this.rootDir = rootDir;
|
|
@@ -68973,14 +69068,14 @@ var BundleCache = class {
|
|
|
68973
69068
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
68974
69069
|
async write(snapshotHash, buffer) {
|
|
68975
69070
|
await import_promises23.default.mkdir(this.rootDir, { recursive: true });
|
|
68976
|
-
const file =
|
|
69071
|
+
const file = import_node_path80.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
68977
69072
|
const tmp = `${file}.tmp`;
|
|
68978
69073
|
await import_promises23.default.writeFile(tmp, buffer, { mode: 384 });
|
|
68979
69074
|
await import_promises23.default.rename(tmp, file);
|
|
68980
69075
|
}
|
|
68981
69076
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
68982
69077
|
async read(snapshotHash) {
|
|
68983
|
-
const file =
|
|
69078
|
+
const file = import_node_path80.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
68984
69079
|
try {
|
|
68985
69080
|
return await import_promises23.default.readFile(file);
|
|
68986
69081
|
} catch (e) {
|
|
@@ -68990,7 +69085,7 @@ var BundleCache = class {
|
|
|
68990
69085
|
}
|
|
68991
69086
|
/** Idempotent — missing file is not an error. */
|
|
68992
69087
|
async delete(snapshotHash) {
|
|
68993
|
-
const file =
|
|
69088
|
+
const file = import_node_path80.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
68994
69089
|
await import_promises23.default.rm(file, { force: true });
|
|
68995
69090
|
}
|
|
68996
69091
|
};
|
|
@@ -69013,24 +69108,24 @@ async function startDaemon(config) {
|
|
|
69013
69108
|
sampling: logShippingCfg.sampling,
|
|
69014
69109
|
homeDir: import_node_os28.default.homedir()
|
|
69015
69110
|
});
|
|
69016
|
-
const logDir =
|
|
69111
|
+
const logDir = import_node_path81.default.join(config.dataDir, "log");
|
|
69017
69112
|
import_node_fs56.default.mkdirSync(logDir, { recursive: true });
|
|
69018
69113
|
const logger = createLogger({
|
|
69019
69114
|
level: config.logLevel,
|
|
69020
|
-
file:
|
|
69115
|
+
file: import_node_path81.default.join(logDir, "clawd.log"),
|
|
69021
69116
|
logClient
|
|
69022
69117
|
});
|
|
69023
69118
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
69024
69119
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
69025
|
-
file:
|
|
69120
|
+
file: import_node_path81.default.join(logDir, "screen-idle-probe.log"),
|
|
69026
69121
|
level: "debug"
|
|
69027
69122
|
});
|
|
69028
69123
|
logger.info("screen-idle probe logger enabled", {
|
|
69029
|
-
file:
|
|
69124
|
+
file: import_node_path81.default.join(logDir, "screen-idle-probe.log")
|
|
69030
69125
|
});
|
|
69031
69126
|
const CAP_TARGETS = [
|
|
69032
|
-
|
|
69033
|
-
|
|
69127
|
+
import_node_path81.default.join(logDir, "clawd.log"),
|
|
69128
|
+
import_node_path81.default.join(logDir, "screen-idle-probe.log")
|
|
69034
69129
|
];
|
|
69035
69130
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
69036
69131
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -69152,8 +69247,8 @@ async function startDaemon(config) {
|
|
|
69152
69247
|
const agents = new AgentsScanner();
|
|
69153
69248
|
const history = new ClaudeHistoryReader();
|
|
69154
69249
|
let transport = null;
|
|
69155
|
-
const personaStore = new PersonaStore(
|
|
69156
|
-
const usersRoot =
|
|
69250
|
+
const personaStore = new PersonaStore(import_node_path81.default.join(config.dataDir, "personas"));
|
|
69251
|
+
const usersRoot = import_node_path81.default.join(config.dataDir, "users");
|
|
69157
69252
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
69158
69253
|
if (defaultsRoot) {
|
|
69159
69254
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -69177,7 +69272,7 @@ async function startDaemon(config) {
|
|
|
69177
69272
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
69178
69273
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
69179
69274
|
const dispatchStore = createDispatchStore({
|
|
69180
|
-
filePath:
|
|
69275
|
+
filePath: import_node_path81.default.join(config.dataDir, "dispatch.json"),
|
|
69181
69276
|
now: () => Date.now(),
|
|
69182
69277
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
69183
69278
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -69186,7 +69281,7 @@ async function startDaemon(config) {
|
|
|
69186
69281
|
await dispatchStore.load();
|
|
69187
69282
|
dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
|
|
69188
69283
|
const channelStore = createChannelStore({
|
|
69189
|
-
filePath:
|
|
69284
|
+
filePath: import_node_path81.default.join(config.dataDir, "channels.json"),
|
|
69190
69285
|
now: () => Date.now(),
|
|
69191
69286
|
genId: () => `ch-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
|
|
69192
69287
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
@@ -69195,7 +69290,7 @@ async function startDaemon(config) {
|
|
|
69195
69290
|
});
|
|
69196
69291
|
await channelStore.load();
|
|
69197
69292
|
const topicStore = createTopicStore({
|
|
69198
|
-
filePath:
|
|
69293
|
+
filePath: import_node_path81.default.join(config.dataDir, "topics.json"),
|
|
69199
69294
|
now: () => Date.now(),
|
|
69200
69295
|
genId: () => `tp-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
|
|
69201
69296
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
@@ -69222,28 +69317,28 @@ async function startDaemon(config) {
|
|
|
69222
69317
|
});
|
|
69223
69318
|
}
|
|
69224
69319
|
});
|
|
69225
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
69320
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path81.default.dirname((0, import_node_url5.fileURLToPath)(import_meta8.url));
|
|
69226
69321
|
const mcpConfigs = [];
|
|
69227
69322
|
const secretsBundleRoot = findSecretsBundleRoot(logger);
|
|
69228
|
-
const localSecretsDir =
|
|
69323
|
+
const localSecretsDir = import_node_path81.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
|
|
69229
69324
|
const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
|
|
69230
69325
|
const resolvePersonaMcpConfig = (personaId2) => renderPersonaMcpSecrets({
|
|
69231
69326
|
personaId: personaId2,
|
|
69232
|
-
personaDir:
|
|
69327
|
+
personaDir: import_node_path81.default.join(config.dataDir, "personas", personaId2),
|
|
69233
69328
|
secrets: readSecrets(),
|
|
69234
|
-
outDir:
|
|
69329
|
+
outDir: import_node_path81.default.join(config.dataDir, "persona-mcp"),
|
|
69235
69330
|
logger
|
|
69236
69331
|
});
|
|
69237
69332
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
69238
69333
|
const dispatchServerCandidates = [
|
|
69239
|
-
|
|
69334
|
+
import_node_path81.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
69240
69335
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
69241
|
-
|
|
69336
|
+
import_node_path81.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
69242
69337
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
69243
69338
|
];
|
|
69244
69339
|
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
69245
69340
|
if (dispatchServerScriptPath) {
|
|
69246
|
-
const dispatchLogPath =
|
|
69341
|
+
const dispatchLogPath = import_node_path81.default.join(logDir, "dispatch-mcp-server.log");
|
|
69247
69342
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
69248
69343
|
dataDir: config.dataDir,
|
|
69249
69344
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -69263,12 +69358,12 @@ async function startDaemon(config) {
|
|
|
69263
69358
|
});
|
|
69264
69359
|
}
|
|
69265
69360
|
const ticketServerCandidates = [
|
|
69266
|
-
|
|
69267
|
-
|
|
69361
|
+
import_node_path81.default.join(here, "ticket", "mcp-server.cjs"),
|
|
69362
|
+
import_node_path81.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
69268
69363
|
];
|
|
69269
69364
|
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
69270
69365
|
if (ticketServerScriptPath) {
|
|
69271
|
-
const ticketLogPath =
|
|
69366
|
+
const ticketLogPath = import_node_path81.default.join(logDir, "ticket-mcp-server.log");
|
|
69272
69367
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
69273
69368
|
dataDir: config.dataDir,
|
|
69274
69369
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -69290,12 +69385,12 @@ async function startDaemon(config) {
|
|
|
69290
69385
|
});
|
|
69291
69386
|
}
|
|
69292
69387
|
const shiftServerCandidates = [
|
|
69293
|
-
|
|
69294
|
-
|
|
69388
|
+
import_node_path81.default.join(here, "shift", "mcp-server.cjs"),
|
|
69389
|
+
import_node_path81.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
69295
69390
|
];
|
|
69296
69391
|
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
69297
69392
|
if (shiftServerScriptPath) {
|
|
69298
|
-
const shiftLogPath =
|
|
69393
|
+
const shiftLogPath = import_node_path81.default.join(logDir, "shift-mcp-server.log");
|
|
69299
69394
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
69300
69395
|
dataDir: config.dataDir,
|
|
69301
69396
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -69316,12 +69411,12 @@ async function startDaemon(config) {
|
|
|
69316
69411
|
);
|
|
69317
69412
|
}
|
|
69318
69413
|
const inboxServerCandidates = [
|
|
69319
|
-
|
|
69320
|
-
|
|
69414
|
+
import_node_path81.default.join(here, "inbox", "mcp-server.cjs"),
|
|
69415
|
+
import_node_path81.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
69321
69416
|
];
|
|
69322
69417
|
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
69323
69418
|
if (inboxServerScriptPath) {
|
|
69324
|
-
const inboxLogPath =
|
|
69419
|
+
const inboxLogPath = import_node_path81.default.join(logDir, "inbox-mcp-server.log");
|
|
69325
69420
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
69326
69421
|
dataDir: config.dataDir,
|
|
69327
69422
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -69342,8 +69437,8 @@ async function startDaemon(config) {
|
|
|
69342
69437
|
);
|
|
69343
69438
|
}
|
|
69344
69439
|
const peerOpsServerCandidates = [
|
|
69345
|
-
|
|
69346
|
-
|
|
69440
|
+
import_node_path81.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
69441
|
+
import_node_path81.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
69347
69442
|
];
|
|
69348
69443
|
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
69349
69444
|
if (peerOpsServerScriptPath) {
|
|
@@ -69365,12 +69460,12 @@ async function startDaemon(config) {
|
|
|
69365
69460
|
);
|
|
69366
69461
|
}
|
|
69367
69462
|
const rpcToolServerCandidates = [
|
|
69368
|
-
|
|
69369
|
-
|
|
69463
|
+
import_node_path81.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
69464
|
+
import_node_path81.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
69370
69465
|
];
|
|
69371
69466
|
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
69372
69467
|
if (rpcToolServerScriptPath) {
|
|
69373
|
-
const rpcToolLogPath =
|
|
69468
|
+
const rpcToolLogPath = import_node_path81.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
69374
69469
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
69375
69470
|
dataDir: config.dataDir,
|
|
69376
69471
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -69391,18 +69486,18 @@ async function startDaemon(config) {
|
|
|
69391
69486
|
);
|
|
69392
69487
|
}
|
|
69393
69488
|
const appBuilderServerCandidates = [
|
|
69394
|
-
|
|
69395
|
-
|
|
69489
|
+
import_node_path81.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
|
|
69490
|
+
import_node_path81.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
|
|
69396
69491
|
];
|
|
69397
69492
|
const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
69398
69493
|
if (appBuilderServerScriptPath) {
|
|
69399
|
-
const appBuilderLogPath =
|
|
69494
|
+
const appBuilderLogPath = import_node_path81.default.join(logDir, "app-builder-mcp-server.log");
|
|
69400
69495
|
const appBuilderCfgPath = writeAppBuilderMcpConfig({
|
|
69401
69496
|
dataDir: config.dataDir,
|
|
69402
69497
|
serverScriptPath: appBuilderServerScriptPath,
|
|
69403
69498
|
daemonToken: resolvedAuthToken,
|
|
69404
69499
|
daemonUrl: mcpDaemonUrl,
|
|
69405
|
-
deployKitScriptsDir:
|
|
69500
|
+
deployKitScriptsDir: import_node_path81.default.join(config.dataDir, "deploy-kit", "scripts"),
|
|
69406
69501
|
logPath: appBuilderLogPath
|
|
69407
69502
|
});
|
|
69408
69503
|
mcpConfigs.push({ id: "app-builder", path: appBuilderCfgPath, personas: APP_BUILDER_PERSONAS });
|
|
@@ -69418,7 +69513,7 @@ async function startDaemon(config) {
|
|
|
69418
69513
|
);
|
|
69419
69514
|
}
|
|
69420
69515
|
const shiftStore = createShiftStore({
|
|
69421
|
-
filePath:
|
|
69516
|
+
filePath: import_node_path81.default.join(config.dataDir, "shift.json"),
|
|
69422
69517
|
ownerIdProvider: () => ownerPrincipalId,
|
|
69423
69518
|
now: () => Date.now()
|
|
69424
69519
|
});
|
|
@@ -69440,7 +69535,7 @@ async function startDaemon(config) {
|
|
|
69440
69535
|
getAdapter,
|
|
69441
69536
|
historyReader: history,
|
|
69442
69537
|
dataDir: config.dataDir,
|
|
69443
|
-
personaRoot:
|
|
69538
|
+
personaRoot: import_node_path81.default.join(config.dataDir, "personas"),
|
|
69444
69539
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
69445
69540
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
69446
69541
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -69497,7 +69592,7 @@ async function startDaemon(config) {
|
|
|
69497
69592
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
69498
69593
|
attachmentGroup: {
|
|
69499
69594
|
onFileEdit: (input) => {
|
|
69500
|
-
const absPath =
|
|
69595
|
+
const absPath = import_node_path81.default.isAbsolute(input.relPath) ? input.relPath : import_node_path81.default.join(input.cwd, input.relPath);
|
|
69501
69596
|
let size = 0;
|
|
69502
69597
|
try {
|
|
69503
69598
|
size = import_node_fs56.default.statSync(absPath).size;
|
|
@@ -69530,9 +69625,9 @@ async function startDaemon(config) {
|
|
|
69530
69625
|
logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
|
|
69531
69626
|
}
|
|
69532
69627
|
const projectsStore = new ProjectsStore({
|
|
69533
|
-
file:
|
|
69628
|
+
file: import_node_path81.default.join(config.dataDir, "projects.json"),
|
|
69534
69629
|
clawdDir: config.dataDir,
|
|
69535
|
-
codexStateFile:
|
|
69630
|
+
codexStateFile: import_node_path81.default.join(import_node_os28.default.homedir(), ".codex", ".codex-global-state.json"),
|
|
69536
69631
|
logger
|
|
69537
69632
|
});
|
|
69538
69633
|
const observer = new SessionObserver({
|
|
@@ -69592,12 +69687,12 @@ async function startDaemon(config) {
|
|
|
69592
69687
|
screenIdleProbeLogger
|
|
69593
69688
|
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
69594
69689
|
registerAdapter("claude", claudeAdapter);
|
|
69595
|
-
const codexIsolatedHome =
|
|
69690
|
+
const codexIsolatedHome = import_node_path81.default.join(config.dataDir, "codex-home");
|
|
69596
69691
|
try {
|
|
69597
69692
|
import_node_fs56.default.mkdirSync(codexIsolatedHome, { recursive: true });
|
|
69598
69693
|
for (const f of ["auth.json", "config.toml"]) {
|
|
69599
|
-
const link =
|
|
69600
|
-
const target =
|
|
69694
|
+
const link = import_node_path81.default.join(codexIsolatedHome, f);
|
|
69695
|
+
const target = import_node_path81.default.join(import_node_os28.default.homedir(), ".codex", f);
|
|
69601
69696
|
if (!import_node_fs56.default.existsSync(link) && import_node_fs56.default.existsSync(target)) import_node_fs56.default.symlinkSync(target, link);
|
|
69602
69697
|
}
|
|
69603
69698
|
} catch (err) {
|
|
@@ -69611,11 +69706,11 @@ async function startDaemon(config) {
|
|
|
69611
69706
|
// projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
|
|
69612
69707
|
codexHomeFor: (cwd) => resolveCodexHome({
|
|
69613
69708
|
cwd,
|
|
69614
|
-
personaRoot:
|
|
69709
|
+
personaRoot: import_node_path81.default.join(config.dataDir, "personas"),
|
|
69615
69710
|
// 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
|
|
69616
69711
|
// Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
|
|
69617
69712
|
projectPaths: projectsStore.listMerged().map((x) => x.path),
|
|
69618
|
-
sharedHome:
|
|
69713
|
+
sharedHome: import_node_path81.default.join(import_node_os28.default.homedir(), ".codex"),
|
|
69619
69714
|
isolatedHome: codexIsolatedHome
|
|
69620
69715
|
})
|
|
69621
69716
|
})
|
|
@@ -69900,11 +69995,11 @@ async function startDaemon(config) {
|
|
|
69900
69995
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
69901
69996
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
69902
69997
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
69903
|
-
personaRoot:
|
|
69998
|
+
personaRoot: import_node_path81.default.join(config.dataDir, "personas"),
|
|
69904
69999
|
usersRoot
|
|
69905
70000
|
},
|
|
69906
70001
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
69907
|
-
personaRoot:
|
|
70002
|
+
personaRoot: import_node_path81.default.join(config.dataDir, "personas"),
|
|
69908
70003
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
69909
70004
|
usersRoot,
|
|
69910
70005
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -70005,11 +70100,11 @@ async function startDaemon(config) {
|
|
|
70005
70100
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
70006
70101
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
70007
70102
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
70008
|
-
appBuilderPersonaRoot:
|
|
70103
|
+
appBuilderPersonaRoot: import_node_path81.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
70009
70104
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
70010
|
-
deployKitRoot:
|
|
70105
|
+
deployKitRoot: import_node_path81.default.join(config.dataDir, "deploy-kit"),
|
|
70011
70106
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
70012
|
-
resolvePersonaRoot: (personaId2) =>
|
|
70107
|
+
resolvePersonaRoot: (personaId2) => import_node_path81.default.join(config.dataDir, "personas", personaId2),
|
|
70013
70108
|
// 凭据表(M1b Step 5):与 MCP 那条同一张表、同一个来源,只是交付给另一个子进程。
|
|
70014
70109
|
readSecrets,
|
|
70015
70110
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
@@ -70124,12 +70219,12 @@ async function startDaemon(config) {
|
|
|
70124
70219
|
});
|
|
70125
70220
|
Object.assign(handlers, shiftHandlers);
|
|
70126
70221
|
const deployReceipts = createReceiptStore({
|
|
70127
|
-
filePath:
|
|
70222
|
+
filePath: import_node_path81.default.join(config.dataDir, "deploy.json"),
|
|
70128
70223
|
now: () => Date.now(),
|
|
70129
70224
|
onFlushError: (err) => logger.error("deploy receipts flush failed", { error: String(err) })
|
|
70130
70225
|
});
|
|
70131
70226
|
const deploySecrets = createSecretStore({
|
|
70132
|
-
filePath:
|
|
70227
|
+
filePath: import_node_path81.default.join(config.dataDir, "deploy-secrets.json"),
|
|
70133
70228
|
now: () => Date.now(),
|
|
70134
70229
|
onFlushError: (err) => logger.error("deploy secrets flush failed", { error: String(err) })
|
|
70135
70230
|
});
|
|
@@ -70205,13 +70300,13 @@ async function startDaemon(config) {
|
|
|
70205
70300
|
hasPersona: (personaId2) => personaStore.has(personaId2),
|
|
70206
70301
|
startScan: (deployId, personaId2) => {
|
|
70207
70302
|
const assetLines = SCANNABLE_ASSETS.map(
|
|
70208
|
-
(
|
|
70303
|
+
(a) => ` - ${a.name}${a.path ? `\uFF08${a.path(config.dataDir)}\uFF09` : ""}\uFF1A${a.what}`
|
|
70209
70304
|
).join("\n");
|
|
70210
70305
|
const prompt = [
|
|
70211
70306
|
`\u626B\u63CF persona\u300C${personaId2}\u300D\u7684\u90E8\u7F72\u73AF\u5883\uFF0CdeployId=${deployId}\u3002`,
|
|
70212
70307
|
"",
|
|
70213
70308
|
`persona \u76EE\u5F55\uFF1A${personaStore.personaDirPath(personaId2)}`,
|
|
70214
|
-
"\u53EF\u4EE5\
|
|
70309
|
+
"\u53EF\u4EE5\u58F0\u660E\u7684 persona \u76EE\u5F55\u4E4B\u5916\u7684\u5171\u4EAB\u8D44\u4EA7\uFF08\u7528\u5230\u54EA\u6761\u5C31\u62A5\u54EA\u6761\uFF09\uFF1A",
|
|
70215
70310
|
assetLines || " \uFF08\u65E0\uFF09",
|
|
70216
70311
|
"",
|
|
70217
70312
|
"\u6309 scan-persona-for-deploy skill \u5E72\u6D3B\uFF1A\u8FB9\u67E5\u8FB9\u7528 deploy:reportFinding \u4E0A\u62A5\uFF0C",
|
|
@@ -70270,7 +70365,7 @@ async function startDaemon(config) {
|
|
|
70270
70365
|
});
|
|
70271
70366
|
shiftScheduler.start();
|
|
70272
70367
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
70273
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
70368
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path81.default.join(config.dataDir, "personas"));
|
|
70274
70369
|
const larkBotCloud = createLarkBotCloudClient({
|
|
70275
70370
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
70276
70371
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -70284,7 +70379,7 @@ async function startDaemon(config) {
|
|
|
70284
70379
|
store: larkBotStore,
|
|
70285
70380
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
70286
70381
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
70287
|
-
mediaRootFor: (chatId) =>
|
|
70382
|
+
mediaRootFor: (chatId) => import_node_path81.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
70288
70383
|
isShuttingDown: () => larkDraining,
|
|
70289
70384
|
logger: {
|
|
70290
70385
|
warn: (msg) => logger.warn(msg),
|
|
@@ -70589,8 +70684,8 @@ async function startDaemon(config) {
|
|
|
70589
70684
|
const lines = [
|
|
70590
70685
|
`Tunnel: ${r.url}`,
|
|
70591
70686
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
70592
|
-
`Frpc config: ${
|
|
70593
|
-
`Frpc log: ${
|
|
70687
|
+
`Frpc config: ${import_node_path81.default.join(config.dataDir, "frpc.toml")}`,
|
|
70688
|
+
`Frpc log: ${import_node_path81.default.join(logDir, "frpc.log")}`
|
|
70594
70689
|
];
|
|
70595
70690
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
70596
70691
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -70603,7 +70698,7 @@ ${bar}
|
|
|
70603
70698
|
|
|
70604
70699
|
`);
|
|
70605
70700
|
try {
|
|
70606
|
-
const connectPath =
|
|
70701
|
+
const connectPath = import_node_path81.default.join(config.dataDir, "connect.txt");
|
|
70607
70702
|
import_node_fs56.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
70608
70703
|
} catch {
|
|
70609
70704
|
}
|
|
@@ -70693,7 +70788,7 @@ ${bar}
|
|
|
70693
70788
|
};
|
|
70694
70789
|
}
|
|
70695
70790
|
function migrateDropPersonsDir(dataDir) {
|
|
70696
|
-
const dir =
|
|
70791
|
+
const dir = import_node_path81.default.join(dataDir, "persons");
|
|
70697
70792
|
try {
|
|
70698
70793
|
import_node_fs56.default.rmSync(dir, { recursive: true, force: true });
|
|
70699
70794
|
} catch {
|