@clawos-dev/clawd 0.2.136-beta.286.f41a8a0 → 0.2.136-beta.287.97b0d33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +315 -367
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -720,8 +720,8 @@ var init_parseUtil = __esm({
|
|
|
720
720
|
init_errors2();
|
|
721
721
|
init_en();
|
|
722
722
|
makeIssue = (params) => {
|
|
723
|
-
const { data, path:
|
|
724
|
-
const fullPath = [...
|
|
723
|
+
const { data, path: path58, errorMaps, issueData } = params;
|
|
724
|
+
const fullPath = [...path58, ...issueData.path || []];
|
|
725
725
|
const fullIssue = {
|
|
726
726
|
...issueData,
|
|
727
727
|
path: fullPath
|
|
@@ -1032,11 +1032,11 @@ var init_types = __esm({
|
|
|
1032
1032
|
init_parseUtil();
|
|
1033
1033
|
init_util();
|
|
1034
1034
|
ParseInputLazyPath = class {
|
|
1035
|
-
constructor(parent, value,
|
|
1035
|
+
constructor(parent, value, path58, key) {
|
|
1036
1036
|
this._cachedPath = [];
|
|
1037
1037
|
this.parent = parent;
|
|
1038
1038
|
this.data = value;
|
|
1039
|
-
this._path =
|
|
1039
|
+
this._path = path58;
|
|
1040
1040
|
this._key = key;
|
|
1041
1041
|
}
|
|
1042
1042
|
get path() {
|
|
@@ -6218,8 +6218,8 @@ var require_req = __commonJS({
|
|
|
6218
6218
|
if (req.originalUrl) {
|
|
6219
6219
|
_req.url = req.originalUrl;
|
|
6220
6220
|
} else {
|
|
6221
|
-
const
|
|
6222
|
-
_req.url = typeof
|
|
6221
|
+
const path58 = req.path;
|
|
6222
|
+
_req.url = typeof path58 === "string" ? path58 : req.url ? req.url.path || req.url : void 0;
|
|
6223
6223
|
}
|
|
6224
6224
|
if (req.query) {
|
|
6225
6225
|
_req.query = req.query;
|
|
@@ -6384,14 +6384,14 @@ var require_redact = __commonJS({
|
|
|
6384
6384
|
}
|
|
6385
6385
|
return obj;
|
|
6386
6386
|
}
|
|
6387
|
-
function parsePath(
|
|
6387
|
+
function parsePath(path58) {
|
|
6388
6388
|
const parts = [];
|
|
6389
6389
|
let current = "";
|
|
6390
6390
|
let inBrackets = false;
|
|
6391
6391
|
let inQuotes = false;
|
|
6392
6392
|
let quoteChar = "";
|
|
6393
|
-
for (let i = 0; i <
|
|
6394
|
-
const char =
|
|
6393
|
+
for (let i = 0; i < path58.length; i++) {
|
|
6394
|
+
const char = path58[i];
|
|
6395
6395
|
if (!inBrackets && char === ".") {
|
|
6396
6396
|
if (current) {
|
|
6397
6397
|
parts.push(current);
|
|
@@ -6522,10 +6522,10 @@ var require_redact = __commonJS({
|
|
|
6522
6522
|
return current;
|
|
6523
6523
|
}
|
|
6524
6524
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
6525
|
-
for (const
|
|
6526
|
-
const parts = parsePath(
|
|
6525
|
+
for (const path58 of paths) {
|
|
6526
|
+
const parts = parsePath(path58);
|
|
6527
6527
|
if (parts.includes("*")) {
|
|
6528
|
-
redactWildcardPath(obj, parts, censor,
|
|
6528
|
+
redactWildcardPath(obj, parts, censor, path58, remove);
|
|
6529
6529
|
} else {
|
|
6530
6530
|
if (remove) {
|
|
6531
6531
|
removeKey(obj, parts);
|
|
@@ -6610,8 +6610,8 @@ var require_redact = __commonJS({
|
|
|
6610
6610
|
}
|
|
6611
6611
|
} else {
|
|
6612
6612
|
if (afterWildcard.includes("*")) {
|
|
6613
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6614
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
6613
|
+
const wrappedCensor = typeof censor === "function" ? (value, path58) => {
|
|
6614
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path58];
|
|
6615
6615
|
return censor(value, fullPath);
|
|
6616
6616
|
} : censor;
|
|
6617
6617
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -6646,8 +6646,8 @@ var require_redact = __commonJS({
|
|
|
6646
6646
|
return null;
|
|
6647
6647
|
}
|
|
6648
6648
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
6649
|
-
for (const
|
|
6650
|
-
const parts = parsePath(
|
|
6649
|
+
for (const path58 of pathsToClone) {
|
|
6650
|
+
const parts = parsePath(path58);
|
|
6651
6651
|
let current = pathStructure;
|
|
6652
6652
|
for (let i = 0; i < parts.length; i++) {
|
|
6653
6653
|
const part = parts[i];
|
|
@@ -6699,24 +6699,24 @@ var require_redact = __commonJS({
|
|
|
6699
6699
|
}
|
|
6700
6700
|
return cloneSelectively(obj, pathStructure);
|
|
6701
6701
|
}
|
|
6702
|
-
function validatePath(
|
|
6703
|
-
if (typeof
|
|
6702
|
+
function validatePath(path58) {
|
|
6703
|
+
if (typeof path58 !== "string") {
|
|
6704
6704
|
throw new Error("Paths must be (non-empty) strings");
|
|
6705
6705
|
}
|
|
6706
|
-
if (
|
|
6706
|
+
if (path58 === "") {
|
|
6707
6707
|
throw new Error("Invalid redaction path ()");
|
|
6708
6708
|
}
|
|
6709
|
-
if (
|
|
6710
|
-
throw new Error(`Invalid redaction path (${
|
|
6709
|
+
if (path58.includes("..")) {
|
|
6710
|
+
throw new Error(`Invalid redaction path (${path58})`);
|
|
6711
6711
|
}
|
|
6712
|
-
if (
|
|
6713
|
-
throw new Error(`Invalid redaction path (${
|
|
6712
|
+
if (path58.includes(",")) {
|
|
6713
|
+
throw new Error(`Invalid redaction path (${path58})`);
|
|
6714
6714
|
}
|
|
6715
6715
|
let bracketCount = 0;
|
|
6716
6716
|
let inQuotes = false;
|
|
6717
6717
|
let quoteChar = "";
|
|
6718
|
-
for (let i = 0; i <
|
|
6719
|
-
const char =
|
|
6718
|
+
for (let i = 0; i < path58.length; i++) {
|
|
6719
|
+
const char = path58[i];
|
|
6720
6720
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
6721
6721
|
if (!inQuotes) {
|
|
6722
6722
|
inQuotes = true;
|
|
@@ -6730,20 +6730,20 @@ var require_redact = __commonJS({
|
|
|
6730
6730
|
} else if (char === "]" && !inQuotes) {
|
|
6731
6731
|
bracketCount--;
|
|
6732
6732
|
if (bracketCount < 0) {
|
|
6733
|
-
throw new Error(`Invalid redaction path (${
|
|
6733
|
+
throw new Error(`Invalid redaction path (${path58})`);
|
|
6734
6734
|
}
|
|
6735
6735
|
}
|
|
6736
6736
|
}
|
|
6737
6737
|
if (bracketCount !== 0) {
|
|
6738
|
-
throw new Error(`Invalid redaction path (${
|
|
6738
|
+
throw new Error(`Invalid redaction path (${path58})`);
|
|
6739
6739
|
}
|
|
6740
6740
|
}
|
|
6741
6741
|
function validatePaths(paths) {
|
|
6742
6742
|
if (!Array.isArray(paths)) {
|
|
6743
6743
|
throw new TypeError("paths must be an array");
|
|
6744
6744
|
}
|
|
6745
|
-
for (const
|
|
6746
|
-
validatePath(
|
|
6745
|
+
for (const path58 of paths) {
|
|
6746
|
+
validatePath(path58);
|
|
6747
6747
|
}
|
|
6748
6748
|
}
|
|
6749
6749
|
function slowRedact(options = {}) {
|
|
@@ -6911,8 +6911,8 @@ var require_redaction = __commonJS({
|
|
|
6911
6911
|
if (shape[k2] === null) {
|
|
6912
6912
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
6913
6913
|
} else {
|
|
6914
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6915
|
-
return censor(value, [k2, ...
|
|
6914
|
+
const wrappedCensor = typeof censor === "function" ? (value, path58) => {
|
|
6915
|
+
return censor(value, [k2, ...path58]);
|
|
6916
6916
|
} : censor;
|
|
6917
6917
|
o[k2] = Redact({
|
|
6918
6918
|
paths: shape[k2],
|
|
@@ -7133,7 +7133,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7133
7133
|
var fs51 = require("fs");
|
|
7134
7134
|
var EventEmitter3 = require("events");
|
|
7135
7135
|
var inherits = require("util").inherits;
|
|
7136
|
-
var
|
|
7136
|
+
var path58 = require("path");
|
|
7137
7137
|
var sleep = require_atomic_sleep();
|
|
7138
7138
|
var assert = require("assert");
|
|
7139
7139
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -7187,7 +7187,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7187
7187
|
const mode = sonic.mode;
|
|
7188
7188
|
if (sonic.sync) {
|
|
7189
7189
|
try {
|
|
7190
|
-
if (sonic.mkdir) fs51.mkdirSync(
|
|
7190
|
+
if (sonic.mkdir) fs51.mkdirSync(path58.dirname(file), { recursive: true });
|
|
7191
7191
|
const fd = fs51.openSync(file, flags, mode);
|
|
7192
7192
|
fileOpened(null, fd);
|
|
7193
7193
|
} catch (err) {
|
|
@@ -7195,7 +7195,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7195
7195
|
throw err;
|
|
7196
7196
|
}
|
|
7197
7197
|
} else if (sonic.mkdir) {
|
|
7198
|
-
fs51.mkdir(
|
|
7198
|
+
fs51.mkdir(path58.dirname(file), { recursive: true }, (err) => {
|
|
7199
7199
|
if (err) return fileOpened(err);
|
|
7200
7200
|
fs51.open(file, flags, mode, fileOpened);
|
|
7201
7201
|
});
|
|
@@ -10055,7 +10055,7 @@ var require_multistream = __commonJS({
|
|
|
10055
10055
|
var require_pino = __commonJS({
|
|
10056
10056
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
10057
10057
|
"use strict";
|
|
10058
|
-
var
|
|
10058
|
+
var os21 = require("os");
|
|
10059
10059
|
var stdSerializers = require_pino_std_serializers();
|
|
10060
10060
|
var caller = require_caller();
|
|
10061
10061
|
var redaction = require_redaction();
|
|
@@ -10102,7 +10102,7 @@ var require_pino = __commonJS({
|
|
|
10102
10102
|
} = symbols;
|
|
10103
10103
|
var { epochTime, nullTime } = time;
|
|
10104
10104
|
var { pid } = process;
|
|
10105
|
-
var hostname =
|
|
10105
|
+
var hostname = os21.hostname();
|
|
10106
10106
|
var defaultErrorSerializer = stdSerializers.err;
|
|
10107
10107
|
var defaultOptions = {
|
|
10108
10108
|
level: "info",
|
|
@@ -10826,11 +10826,11 @@ var init_lib = __esm({
|
|
|
10826
10826
|
}
|
|
10827
10827
|
}
|
|
10828
10828
|
},
|
|
10829
|
-
addToPath: function addToPath(
|
|
10830
|
-
var last =
|
|
10829
|
+
addToPath: function addToPath(path58, added, removed, oldPosInc, options) {
|
|
10830
|
+
var last = path58.lastComponent;
|
|
10831
10831
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
10832
10832
|
return {
|
|
10833
|
-
oldPos:
|
|
10833
|
+
oldPos: path58.oldPos + oldPosInc,
|
|
10834
10834
|
lastComponent: {
|
|
10835
10835
|
count: last.count + 1,
|
|
10836
10836
|
added,
|
|
@@ -10840,7 +10840,7 @@ var init_lib = __esm({
|
|
|
10840
10840
|
};
|
|
10841
10841
|
} else {
|
|
10842
10842
|
return {
|
|
10843
|
-
oldPos:
|
|
10843
|
+
oldPos: path58.oldPos + oldPosInc,
|
|
10844
10844
|
lastComponent: {
|
|
10845
10845
|
count: 1,
|
|
10846
10846
|
added,
|
|
@@ -11286,10 +11286,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
11286
11286
|
const memories = raw.map((m2) => {
|
|
11287
11287
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11288
11288
|
const rec3 = m2;
|
|
11289
|
-
const
|
|
11289
|
+
const path58 = typeof rec3.path === "string" ? rec3.path : null;
|
|
11290
11290
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
11291
|
-
if (!
|
|
11292
|
-
const entry = { path:
|
|
11291
|
+
if (!path58 || content == null) return null;
|
|
11292
|
+
const entry = { path: path58, content };
|
|
11293
11293
|
if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
|
|
11294
11294
|
return entry;
|
|
11295
11295
|
}).filter((m2) => m2 !== null);
|
|
@@ -11754,12 +11754,6 @@ var init_claude_history = __esm({
|
|
|
11754
11754
|
});
|
|
11755
11755
|
|
|
11756
11756
|
// src/tools/claude.ts
|
|
11757
|
-
function macOSDesktopCandidates(home) {
|
|
11758
|
-
return [
|
|
11759
|
-
import_node_path9.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
|
|
11760
|
-
"/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
11761
|
-
];
|
|
11762
|
-
}
|
|
11763
11757
|
function probeViaWhich() {
|
|
11764
11758
|
try {
|
|
11765
11759
|
const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
@@ -11768,19 +11762,12 @@ function probeViaWhich() {
|
|
|
11768
11762
|
}
|
|
11769
11763
|
return null;
|
|
11770
11764
|
}
|
|
11771
|
-
async function probeClaude(env = process.env
|
|
11765
|
+
async function probeClaude(env = process.env) {
|
|
11772
11766
|
if (env.CLAUDE_BIN && import_node_fs9.default.existsSync(env.CLAUDE_BIN)) {
|
|
11773
11767
|
return { available: true, path: env.CLAUDE_BIN };
|
|
11774
11768
|
}
|
|
11775
11769
|
const w2 = probeViaWhich();
|
|
11776
11770
|
if (w2) return { available: true, path: w2 };
|
|
11777
|
-
if (process.platform === "darwin") {
|
|
11778
|
-
for (const candidate of macOSDesktopCandidates(home)) {
|
|
11779
|
-
if (import_node_fs9.default.existsSync(candidate)) {
|
|
11780
|
-
return { available: true, path: candidate };
|
|
11781
|
-
}
|
|
11782
|
-
}
|
|
11783
|
-
}
|
|
11784
11771
|
return { available: false };
|
|
11785
11772
|
}
|
|
11786
11773
|
function buildSpawnArgs(ctx) {
|
|
@@ -12101,10 +12088,10 @@ function parseAttachment(obj) {
|
|
|
12101
12088
|
const memories = raw.map((m2) => {
|
|
12102
12089
|
if (!m2 || typeof m2 !== "object") return null;
|
|
12103
12090
|
const rec3 = m2;
|
|
12104
|
-
const
|
|
12091
|
+
const path58 = typeof rec3.path === "string" ? rec3.path : null;
|
|
12105
12092
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
12106
|
-
if (!
|
|
12107
|
-
const out = { path:
|
|
12093
|
+
if (!path58 || content == null) return null;
|
|
12094
|
+
const out = { path: path58, content };
|
|
12108
12095
|
if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
|
|
12109
12096
|
return out;
|
|
12110
12097
|
}).filter((m2) => m2 !== null);
|
|
@@ -12208,15 +12195,13 @@ function encodeClaudeStdin(text) {
|
|
|
12208
12195
|
};
|
|
12209
12196
|
return JSON.stringify(frame) + "\n";
|
|
12210
12197
|
}
|
|
12211
|
-
var import_node_child_process, import_node_child_process2, import_node_fs9,
|
|
12198
|
+
var import_node_child_process, import_node_child_process2, import_node_fs9, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
|
|
12212
12199
|
var init_claude = __esm({
|
|
12213
12200
|
"src/tools/claude.ts"() {
|
|
12214
12201
|
"use strict";
|
|
12215
12202
|
import_node_child_process = require("child_process");
|
|
12216
12203
|
import_node_child_process2 = require("child_process");
|
|
12217
12204
|
import_node_fs9 = __toESM(require("fs"), 1);
|
|
12218
|
-
import_node_os5 = __toESM(require("os"), 1);
|
|
12219
|
-
import_node_path9 = __toESM(require("path"), 1);
|
|
12220
12205
|
init_protocol();
|
|
12221
12206
|
init_claude_history();
|
|
12222
12207
|
init_tool_result_extra();
|
|
@@ -23893,8 +23878,8 @@ var require_utils = __commonJS({
|
|
|
23893
23878
|
var result = transform[inputType][outputType](input);
|
|
23894
23879
|
return result;
|
|
23895
23880
|
};
|
|
23896
|
-
exports2.resolve = function(
|
|
23897
|
-
var parts =
|
|
23881
|
+
exports2.resolve = function(path58) {
|
|
23882
|
+
var parts = path58.split("/");
|
|
23898
23883
|
var result = [];
|
|
23899
23884
|
for (var index = 0; index < parts.length; index++) {
|
|
23900
23885
|
var part = parts[index];
|
|
@@ -29747,18 +29732,18 @@ var require_object = __commonJS({
|
|
|
29747
29732
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
29748
29733
|
this.files[name] = object;
|
|
29749
29734
|
};
|
|
29750
|
-
var parentFolder = function(
|
|
29751
|
-
if (
|
|
29752
|
-
|
|
29735
|
+
var parentFolder = function(path58) {
|
|
29736
|
+
if (path58.slice(-1) === "/") {
|
|
29737
|
+
path58 = path58.substring(0, path58.length - 1);
|
|
29753
29738
|
}
|
|
29754
|
-
var lastSlash =
|
|
29755
|
-
return lastSlash > 0 ?
|
|
29739
|
+
var lastSlash = path58.lastIndexOf("/");
|
|
29740
|
+
return lastSlash > 0 ? path58.substring(0, lastSlash) : "";
|
|
29756
29741
|
};
|
|
29757
|
-
var forceTrailingSlash = function(
|
|
29758
|
-
if (
|
|
29759
|
-
|
|
29742
|
+
var forceTrailingSlash = function(path58) {
|
|
29743
|
+
if (path58.slice(-1) !== "/") {
|
|
29744
|
+
path58 += "/";
|
|
29760
29745
|
}
|
|
29761
|
-
return
|
|
29746
|
+
return path58;
|
|
29762
29747
|
};
|
|
29763
29748
|
var folderAdd = function(name, createFolders) {
|
|
29764
29749
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -30760,7 +30745,7 @@ var require_lib3 = __commonJS({
|
|
|
30760
30745
|
// src/run-case/recorder.ts
|
|
30761
30746
|
function startRunCaseRecorder(opts) {
|
|
30762
30747
|
const now = opts.now ?? Date.now;
|
|
30763
|
-
const dir =
|
|
30748
|
+
const dir = import_node_path46.default.dirname(opts.recordPath);
|
|
30764
30749
|
let stream = null;
|
|
30765
30750
|
let closing = false;
|
|
30766
30751
|
let closedSettled = false;
|
|
@@ -30800,12 +30785,12 @@ function startRunCaseRecorder(opts) {
|
|
|
30800
30785
|
};
|
|
30801
30786
|
return { tap, close, closed };
|
|
30802
30787
|
}
|
|
30803
|
-
var import_node_fs34,
|
|
30788
|
+
var import_node_fs34, import_node_path46;
|
|
30804
30789
|
var init_recorder = __esm({
|
|
30805
30790
|
"src/run-case/recorder.ts"() {
|
|
30806
30791
|
"use strict";
|
|
30807
30792
|
import_node_fs34 = __toESM(require("fs"), 1);
|
|
30808
|
-
|
|
30793
|
+
import_node_path46 = __toESM(require("path"), 1);
|
|
30809
30794
|
}
|
|
30810
30795
|
});
|
|
30811
30796
|
|
|
@@ -30848,7 +30833,7 @@ var init_wire = __esm({
|
|
|
30848
30833
|
// src/run-case/controller.ts
|
|
30849
30834
|
async function runController(opts) {
|
|
30850
30835
|
const now = opts.now ?? Date.now;
|
|
30851
|
-
const cwd = opts.cwd ?? (0, import_node_fs35.mkdtempSync)(
|
|
30836
|
+
const cwd = opts.cwd ?? (0, import_node_fs35.mkdtempSync)(import_node_path47.default.join(import_node_os19.default.tmpdir(), "clawd-runcase-"));
|
|
30852
30837
|
const ownsCwd = opts.cwd === void 0;
|
|
30853
30838
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
30854
30839
|
const spawnCtx = { cwd };
|
|
@@ -31015,13 +31000,13 @@ async function runController(opts) {
|
|
|
31015
31000
|
}
|
|
31016
31001
|
return exitCode ?? 0;
|
|
31017
31002
|
}
|
|
31018
|
-
var import_node_fs35,
|
|
31003
|
+
var import_node_fs35, import_node_os19, import_node_path47;
|
|
31019
31004
|
var init_controller = __esm({
|
|
31020
31005
|
"src/run-case/controller.ts"() {
|
|
31021
31006
|
"use strict";
|
|
31022
31007
|
import_node_fs35 = require("fs");
|
|
31023
|
-
|
|
31024
|
-
|
|
31008
|
+
import_node_os19 = __toESM(require("os"), 1);
|
|
31009
|
+
import_node_path47 = __toESM(require("path"), 1);
|
|
31025
31010
|
init_claude();
|
|
31026
31011
|
init_stdout_splitter();
|
|
31027
31012
|
init_permission_stdio();
|
|
@@ -31256,7 +31241,7 @@ Env (advanced):
|
|
|
31256
31241
|
`;
|
|
31257
31242
|
|
|
31258
31243
|
// src/index.ts
|
|
31259
|
-
var
|
|
31244
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
31260
31245
|
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
31261
31246
|
|
|
31262
31247
|
// src/logger.ts
|
|
@@ -32601,7 +32586,7 @@ var SessionRunner = class {
|
|
|
32601
32586
|
this.input({ kind: "inject-events", events });
|
|
32602
32587
|
}
|
|
32603
32588
|
// session:interrupt 的 SDK 通道分流:codex → AgentSession.interrupt();claude → control_request('interrupt')。
|
|
32604
|
-
// TUI(pty) 路径在 manager.
|
|
32589
|
+
// TUI(pty) 路径在 manager.interrupt() 里先走 stop() SIGKILL,不进这里。
|
|
32605
32590
|
async interrupt() {
|
|
32606
32591
|
if (this.session) {
|
|
32607
32592
|
this.session.interrupt();
|
|
@@ -33672,50 +33657,12 @@ var SessionManager = class {
|
|
|
33672
33657
|
return this.stop({ sessionId: args.sessionId });
|
|
33673
33658
|
}
|
|
33674
33659
|
try {
|
|
33675
|
-
await
|
|
33660
|
+
await runner.interrupt();
|
|
33676
33661
|
} catch (err) {
|
|
33677
33662
|
throw new ClawdError(ERROR_CODES.INTERNAL, err.message);
|
|
33678
33663
|
}
|
|
33679
33664
|
return { response: { ok: true }, broadcast: [] };
|
|
33680
33665
|
}
|
|
33681
|
-
// 同时被 interrupt / cancelQuestion 调用:按模式选 interrupt 通道。TUI 优先 pty,
|
|
33682
|
-
// 否则 fallback 到 SDK 的 control_request(包括 mode='tui' 但 pty 未 register 的边角场景)。
|
|
33683
|
-
async dispatchInterrupt(runner) {
|
|
33684
|
-
const sid = runner.getState().file.sessionId;
|
|
33685
|
-
const tsid = runner.getState().file.toolSessionId;
|
|
33686
|
-
const pty = tsid ? this.ptyTransports.get(tsid) : void 0;
|
|
33687
|
-
const stateBefore = runner.getState();
|
|
33688
|
-
this.deps.logger?.info("[BUG-HUNT-INTERRUPT] dispatchInterrupt enter", {
|
|
33689
|
-
sessionId: sid,
|
|
33690
|
-
tsid,
|
|
33691
|
-
ptyHit: Boolean(pty),
|
|
33692
|
-
mode: this.deps.mode,
|
|
33693
|
-
turnOpenBefore: stateBefore.turnOpen,
|
|
33694
|
-
procAlive: stateBefore.procAlive,
|
|
33695
|
-
bufferLen: stateBefore.buffer.length
|
|
33696
|
-
});
|
|
33697
|
-
if (pty) {
|
|
33698
|
-
pty.write("\x1B");
|
|
33699
|
-
this.deps.logger?.info("[BUG-HUNT-INTERRUPT] pty.write ESC done", { sessionId: sid });
|
|
33700
|
-
runner.input({ kind: "inject-events", events: [{ kind: "turn_end" }] });
|
|
33701
|
-
const stateAfter = runner.getState();
|
|
33702
|
-
const lastEvent = stateAfter.buffer[stateAfter.buffer.length - 1];
|
|
33703
|
-
this.deps.logger?.info("[BUG-HUNT-INTERRUPT] after inject turn_end", {
|
|
33704
|
-
sessionId: sid,
|
|
33705
|
-
turnOpenAfter: stateAfter.turnOpen,
|
|
33706
|
-
bufferLen: stateAfter.buffer.length,
|
|
33707
|
-
lastEventKind: lastEvent?.event?.kind,
|
|
33708
|
-
lastEventSeq: lastEvent?.seq
|
|
33709
|
-
});
|
|
33710
|
-
return;
|
|
33711
|
-
}
|
|
33712
|
-
this.deps.logger?.warn("[BUG-HUNT-INTERRUPT] SDK fallback path (pty not registered)", {
|
|
33713
|
-
sessionId: sid,
|
|
33714
|
-
tsid,
|
|
33715
|
-
mode: this.deps.mode
|
|
33716
|
-
});
|
|
33717
|
-
await runner.interrupt();
|
|
33718
|
-
}
|
|
33719
33666
|
// 批量版本:UI 打开 session 时一次性拿到"磁盘和快照有差异"的 user message id 集合,
|
|
33720
33667
|
// 用来在消息流里精准控制 rewind 按钮的显示。session 没 toolSessionId 时返回空
|
|
33721
33668
|
rewindableMessageIds(args) {
|
|
@@ -34260,7 +34207,7 @@ var SessionManager = class {
|
|
|
34260
34207
|
runner.input({ kind: "cancel-question", toolUseId: args.toolUseId });
|
|
34261
34208
|
});
|
|
34262
34209
|
if (runner.getState().procAlive) {
|
|
34263
|
-
void
|
|
34210
|
+
void runner.interrupt().catch(() => {
|
|
34264
34211
|
});
|
|
34265
34212
|
}
|
|
34266
34213
|
return { response: { ok: true }, broadcast };
|
|
@@ -35569,8 +35516,8 @@ function turnStartInput(text) {
|
|
|
35569
35516
|
const items = [];
|
|
35570
35517
|
let leftover = text;
|
|
35571
35518
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
35572
|
-
const [marker, name,
|
|
35573
|
-
items.push({ type: "skill", name, path:
|
|
35519
|
+
const [marker, name, path58] = m2;
|
|
35520
|
+
items.push({ type: "skill", name, path: path58 });
|
|
35574
35521
|
leftover = leftover.replace(marker, "");
|
|
35575
35522
|
}
|
|
35576
35523
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -35629,6 +35576,7 @@ function createCodexSession(ctx, sink, deps = {}) {
|
|
|
35629
35576
|
]);
|
|
35630
35577
|
return;
|
|
35631
35578
|
}
|
|
35579
|
+
deps.logger?.warn("codex unknown server-request auto-cancelled", { method });
|
|
35632
35580
|
client.respond(id, "cancel");
|
|
35633
35581
|
},
|
|
35634
35582
|
onClose: () => finish(proc.exitCode)
|
|
@@ -35802,8 +35750,8 @@ var CodexAdapter = class {
|
|
|
35802
35750
|
|
|
35803
35751
|
// src/tools/claude-tui.ts
|
|
35804
35752
|
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
35805
|
-
var
|
|
35806
|
-
var
|
|
35753
|
+
var import_node_os5 = __toESM(require("os"), 1);
|
|
35754
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
35807
35755
|
var import_headless = __toESM(require_xterm_headless(), 1);
|
|
35808
35756
|
|
|
35809
35757
|
// ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
|
|
@@ -36775,15 +36723,15 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
36775
36723
|
args.push(isResume ? "--resume" : "--session-id", ctx.toolSessionId);
|
|
36776
36724
|
}
|
|
36777
36725
|
if (ctx.model) args.push("--model", ctx.model);
|
|
36778
|
-
args.push("--permission-mode", ctx.permissionMode
|
|
36726
|
+
args.push("--permission-mode", ctx.permissionMode ?? "bypassPermissions");
|
|
36779
36727
|
if (ctx.effort) args.push("--effort", ctx.effort);
|
|
36780
36728
|
if (ctx.extraSettings) args.push("--settings", ctx.extraSettings);
|
|
36781
36729
|
return args;
|
|
36782
36730
|
}
|
|
36783
36731
|
function jsonlExistsForCtx(ctx) {
|
|
36784
36732
|
if (!ctx.toolSessionId) return false;
|
|
36785
|
-
const home =
|
|
36786
|
-
const file =
|
|
36733
|
+
const home = import_node_os5.default.homedir();
|
|
36734
|
+
const file = import_node_path9.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
|
|
36787
36735
|
try {
|
|
36788
36736
|
return import_node_fs11.default.statSync(file).isFile();
|
|
36789
36737
|
} catch {
|
|
@@ -36980,13 +36928,13 @@ function mapSkillsListResponse(res) {
|
|
|
36980
36928
|
const r = s ?? {};
|
|
36981
36929
|
const name = str3(r.name);
|
|
36982
36930
|
if (!name) continue;
|
|
36983
|
-
const
|
|
36931
|
+
const path58 = str3(r.path);
|
|
36984
36932
|
const description = str3(r.description);
|
|
36985
36933
|
const isPlugin = name.includes(":");
|
|
36986
36934
|
out.push({
|
|
36987
36935
|
name,
|
|
36988
36936
|
source: isPlugin ? "plugin" : "project",
|
|
36989
|
-
...
|
|
36937
|
+
...path58 ? { path: path58 } : {},
|
|
36990
36938
|
...description ? { description } : {},
|
|
36991
36939
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
36992
36940
|
});
|
|
@@ -37026,15 +36974,15 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
37026
36974
|
|
|
37027
36975
|
// src/workspace/browser.ts
|
|
37028
36976
|
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
37029
|
-
var
|
|
37030
|
-
var
|
|
36977
|
+
var import_node_os6 = __toESM(require("os"), 1);
|
|
36978
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
37031
36979
|
init_protocol();
|
|
37032
36980
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
37033
36981
|
function resolveInsideCwd(cwd, subpath) {
|
|
37034
|
-
const absCwd =
|
|
37035
|
-
const joined =
|
|
37036
|
-
const rel =
|
|
37037
|
-
if (rel.startsWith("..") ||
|
|
36982
|
+
const absCwd = import_node_path10.default.resolve(cwd);
|
|
36983
|
+
const joined = import_node_path10.default.resolve(absCwd, subpath ?? ".");
|
|
36984
|
+
const rel = import_node_path10.default.relative(absCwd, joined);
|
|
36985
|
+
if (rel.startsWith("..") || import_node_path10.default.isAbsolute(rel)) {
|
|
37038
36986
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
37039
36987
|
}
|
|
37040
36988
|
return joined;
|
|
@@ -37052,7 +37000,7 @@ function ensureCwd(cwd) {
|
|
|
37052
37000
|
}
|
|
37053
37001
|
var WorkspaceBrowser = class {
|
|
37054
37002
|
list(args) {
|
|
37055
|
-
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd :
|
|
37003
|
+
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os6.default.homedir();
|
|
37056
37004
|
ensureCwd(cwd);
|
|
37057
37005
|
const full = resolveInsideCwd(cwd, args.path);
|
|
37058
37006
|
const dirents = import_node_fs12.default.readdirSync(full, { withFileTypes: true });
|
|
@@ -37065,7 +37013,7 @@ var WorkspaceBrowser = class {
|
|
|
37065
37013
|
mtime: ""
|
|
37066
37014
|
};
|
|
37067
37015
|
try {
|
|
37068
|
-
const st = import_node_fs12.default.statSync(
|
|
37016
|
+
const st = import_node_fs12.default.statSync(import_node_path10.default.join(full, d.name));
|
|
37069
37017
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
37070
37018
|
if (d.isFile()) entry.size = st.size;
|
|
37071
37019
|
} catch {
|
|
@@ -37111,8 +37059,8 @@ var WorkspaceBrowser = class {
|
|
|
37111
37059
|
|
|
37112
37060
|
// src/skills/agents-scanner.ts
|
|
37113
37061
|
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
37114
|
-
var
|
|
37115
|
-
var
|
|
37062
|
+
var import_node_os7 = __toESM(require("os"), 1);
|
|
37063
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
37116
37064
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
37117
37065
|
function isDirLikeSync2(p2) {
|
|
37118
37066
|
try {
|
|
@@ -37150,10 +37098,10 @@ function scanAgentsDir(dir, source, seen, out) {
|
|
|
37150
37098
|
}
|
|
37151
37099
|
for (const ent of entries) {
|
|
37152
37100
|
if (!ent.name.endsWith(".md")) continue;
|
|
37153
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
37101
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path11.default.join(dir, ent.name)))) {
|
|
37154
37102
|
continue;
|
|
37155
37103
|
}
|
|
37156
|
-
const filePath =
|
|
37104
|
+
const filePath = import_node_path11.default.join(dir, ent.name);
|
|
37157
37105
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
37158
37106
|
if (seen.has(baseName)) continue;
|
|
37159
37107
|
seen.add(baseName);
|
|
@@ -37176,7 +37124,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
37176
37124
|
return;
|
|
37177
37125
|
}
|
|
37178
37126
|
for (const ent of entries) {
|
|
37179
|
-
const childPath =
|
|
37127
|
+
const childPath = import_node_path11.default.join(dir, ent.name);
|
|
37180
37128
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
37181
37129
|
walk2(childPath, [...namespaces, ent.name]);
|
|
37182
37130
|
continue;
|
|
@@ -37201,9 +37149,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
37201
37149
|
walk2(root, []);
|
|
37202
37150
|
}
|
|
37203
37151
|
function readInstalledPlugins2(home) {
|
|
37204
|
-
const pluginsDir =
|
|
37205
|
-
const v2 =
|
|
37206
|
-
const v1 =
|
|
37152
|
+
const pluginsDir = import_node_path11.default.join(home, ".claude", "plugins");
|
|
37153
|
+
const v2 = import_node_path11.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
37154
|
+
const v1 = import_node_path11.default.join(pluginsDir, "installed_plugins.json");
|
|
37207
37155
|
let raw = null;
|
|
37208
37156
|
for (const candidate of [v2, v1]) {
|
|
37209
37157
|
try {
|
|
@@ -37232,19 +37180,19 @@ function readInstalledPlugins2(home) {
|
|
|
37232
37180
|
return out;
|
|
37233
37181
|
}
|
|
37234
37182
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
37235
|
-
let cur =
|
|
37236
|
-
const fsRoot =
|
|
37183
|
+
let cur = import_node_path11.default.resolve(startCwd);
|
|
37184
|
+
const fsRoot = import_node_path11.default.parse(cur).root;
|
|
37237
37185
|
while (true) {
|
|
37238
|
-
scanAgentsDir(
|
|
37186
|
+
scanAgentsDir(import_node_path11.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
37239
37187
|
let hasGit = false;
|
|
37240
37188
|
try {
|
|
37241
|
-
hasGit = import_node_fs13.default.existsSync(
|
|
37189
|
+
hasGit = import_node_fs13.default.existsSync(import_node_path11.default.join(cur, ".git"));
|
|
37242
37190
|
} catch {
|
|
37243
37191
|
}
|
|
37244
37192
|
if (hasGit) return;
|
|
37245
37193
|
if (cur === home) return;
|
|
37246
37194
|
if (cur === fsRoot) return;
|
|
37247
|
-
const parent =
|
|
37195
|
+
const parent = import_node_path11.default.dirname(cur);
|
|
37248
37196
|
if (parent === cur) return;
|
|
37249
37197
|
cur = parent;
|
|
37250
37198
|
}
|
|
@@ -37254,7 +37202,7 @@ var AgentsScanner = class {
|
|
|
37254
37202
|
extraPluginRoots;
|
|
37255
37203
|
policyDir;
|
|
37256
37204
|
constructor(opts = {}) {
|
|
37257
|
-
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ??
|
|
37205
|
+
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os7.default.homedir();
|
|
37258
37206
|
this.extraPluginRoots = opts.extraPluginRoots ?? [];
|
|
37259
37207
|
if (opts.policyDir !== void 0) {
|
|
37260
37208
|
this.policyDir = opts.policyDir;
|
|
@@ -37279,7 +37227,7 @@ var AgentsScanner = class {
|
|
|
37279
37227
|
}
|
|
37280
37228
|
const fsBlock = [];
|
|
37281
37229
|
scanAgentsDir(
|
|
37282
|
-
|
|
37230
|
+
import_node_path11.default.join(this.home, ".claude", "agents"),
|
|
37283
37231
|
"global",
|
|
37284
37232
|
seen,
|
|
37285
37233
|
fsBlock
|
|
@@ -37293,7 +37241,7 @@ var AgentsScanner = class {
|
|
|
37293
37241
|
...this.extraPluginRoots
|
|
37294
37242
|
];
|
|
37295
37243
|
for (const { name, root } of plugins) {
|
|
37296
|
-
const agentsRoot =
|
|
37244
|
+
const agentsRoot = import_node_path11.default.join(root, "agents");
|
|
37297
37245
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
37298
37246
|
}
|
|
37299
37247
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -37302,27 +37250,27 @@ var AgentsScanner = class {
|
|
|
37302
37250
|
|
|
37303
37251
|
// src/observer/session-observer.ts
|
|
37304
37252
|
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
37305
|
-
var
|
|
37306
|
-
var
|
|
37253
|
+
var import_node_os9 = __toESM(require("os"), 1);
|
|
37254
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
37307
37255
|
init_claude_history();
|
|
37308
37256
|
|
|
37309
37257
|
// src/observer/subagent-meta-observer.ts
|
|
37310
37258
|
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
37311
|
-
var
|
|
37312
|
-
var
|
|
37259
|
+
var import_node_os8 = __toESM(require("os"), 1);
|
|
37260
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
37313
37261
|
init_claude_history();
|
|
37314
37262
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
37315
37263
|
var SubagentMetaObserver = class {
|
|
37316
37264
|
constructor(opts) {
|
|
37317
37265
|
this.opts = opts;
|
|
37318
|
-
this.home = opts.home ??
|
|
37266
|
+
this.home = opts.home ?? import_node_os8.default.homedir();
|
|
37319
37267
|
}
|
|
37320
37268
|
opts;
|
|
37321
37269
|
home;
|
|
37322
37270
|
watches = /* @__PURE__ */ new Map();
|
|
37323
37271
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
37324
37272
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
37325
|
-
return
|
|
37273
|
+
return import_node_path12.default.join(
|
|
37326
37274
|
this.home,
|
|
37327
37275
|
".claude",
|
|
37328
37276
|
"projects",
|
|
@@ -37378,7 +37326,7 @@ var SubagentMetaObserver = class {
|
|
|
37378
37326
|
if (!m2) return;
|
|
37379
37327
|
const agentId = m2[1];
|
|
37380
37328
|
if (w2.emitted.has(agentId)) return;
|
|
37381
|
-
const file =
|
|
37329
|
+
const file = import_node_path12.default.join(w2.dirPath, name);
|
|
37382
37330
|
let raw;
|
|
37383
37331
|
try {
|
|
37384
37332
|
raw = import_node_fs14.default.readFileSync(file, "utf8");
|
|
@@ -37426,7 +37374,7 @@ var SubagentMetaObserver = class {
|
|
|
37426
37374
|
var SessionObserver = class {
|
|
37427
37375
|
constructor(opts) {
|
|
37428
37376
|
this.opts = opts;
|
|
37429
|
-
this.home = opts.home ??
|
|
37377
|
+
this.home = opts.home ?? import_node_os9.default.homedir();
|
|
37430
37378
|
this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
|
|
37431
37379
|
}
|
|
37432
37380
|
opts;
|
|
@@ -37438,7 +37386,7 @@ var SessionObserver = class {
|
|
|
37438
37386
|
metaObserver;
|
|
37439
37387
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
37440
37388
|
if (override) return override;
|
|
37441
|
-
return
|
|
37389
|
+
return import_node_path13.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
37442
37390
|
}
|
|
37443
37391
|
start(args) {
|
|
37444
37392
|
this.stop(args.sessionId);
|
|
@@ -37459,10 +37407,10 @@ var SessionObserver = class {
|
|
|
37459
37407
|
prevIsRejectSentinel: false
|
|
37460
37408
|
};
|
|
37461
37409
|
try {
|
|
37462
|
-
import_node_fs15.default.mkdirSync(
|
|
37410
|
+
import_node_fs15.default.mkdirSync(import_node_path13.default.dirname(filePath), { recursive: true });
|
|
37463
37411
|
} catch {
|
|
37464
37412
|
}
|
|
37465
|
-
w2.watcher = import_node_fs15.default.watch(
|
|
37413
|
+
w2.watcher = import_node_fs15.default.watch(import_node_path13.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
37466
37414
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
37467
37415
|
this.poll(w2);
|
|
37468
37416
|
});
|
|
@@ -38269,7 +38217,7 @@ async function authenticate(token, deps) {
|
|
|
38269
38217
|
|
|
38270
38218
|
// src/permission/capability-store.ts
|
|
38271
38219
|
var fs18 = __toESM(require("fs"), 1);
|
|
38272
|
-
var
|
|
38220
|
+
var path18 = __toESM(require("path"), 1);
|
|
38273
38221
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
38274
38222
|
var FILE_VERSION = 1;
|
|
38275
38223
|
var CapabilityStore = class {
|
|
@@ -38299,7 +38247,7 @@ var CapabilityStore = class {
|
|
|
38299
38247
|
this.flush();
|
|
38300
38248
|
}
|
|
38301
38249
|
filePath() {
|
|
38302
|
-
return
|
|
38250
|
+
return path18.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
38303
38251
|
}
|
|
38304
38252
|
readFromDisk() {
|
|
38305
38253
|
const file = this.filePath();
|
|
@@ -38446,7 +38394,7 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
38446
38394
|
|
|
38447
38395
|
// src/inbox/inbox-store.ts
|
|
38448
38396
|
var fs20 = __toESM(require("fs"), 1);
|
|
38449
|
-
var
|
|
38397
|
+
var path19 = __toESM(require("path"), 1);
|
|
38450
38398
|
var INBOX_SUBDIR = "inbox";
|
|
38451
38399
|
var InboxStore = class {
|
|
38452
38400
|
constructor(dataDir) {
|
|
@@ -38544,10 +38492,10 @@ var InboxStore = class {
|
|
|
38544
38492
|
}
|
|
38545
38493
|
}
|
|
38546
38494
|
dirPath() {
|
|
38547
|
-
return
|
|
38495
|
+
return path19.join(this.dataDir, INBOX_SUBDIR);
|
|
38548
38496
|
}
|
|
38549
38497
|
filePath(peerDeviceId) {
|
|
38550
|
-
return
|
|
38498
|
+
return path19.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
38551
38499
|
}
|
|
38552
38500
|
};
|
|
38553
38501
|
function parseAllLines(raw) {
|
|
@@ -38635,7 +38583,7 @@ var InboxManager = class {
|
|
|
38635
38583
|
|
|
38636
38584
|
// src/state/contact-store.ts
|
|
38637
38585
|
var fs21 = __toESM(require("fs"), 1);
|
|
38638
|
-
var
|
|
38586
|
+
var path20 = __toESM(require("path"), 1);
|
|
38639
38587
|
var FILE_NAME = "contacts.json";
|
|
38640
38588
|
var ContactStore = class {
|
|
38641
38589
|
constructor(dataDir) {
|
|
@@ -38645,7 +38593,7 @@ var ContactStore = class {
|
|
|
38645
38593
|
contacts = /* @__PURE__ */ new Map();
|
|
38646
38594
|
load() {
|
|
38647
38595
|
this.contacts.clear();
|
|
38648
|
-
const file =
|
|
38596
|
+
const file = path20.join(this.dataDir, FILE_NAME);
|
|
38649
38597
|
let raw;
|
|
38650
38598
|
try {
|
|
38651
38599
|
raw = fs21.readFileSync(file, "utf8");
|
|
@@ -38691,7 +38639,7 @@ var ContactStore = class {
|
|
|
38691
38639
|
return existed;
|
|
38692
38640
|
}
|
|
38693
38641
|
flush() {
|
|
38694
|
-
const file =
|
|
38642
|
+
const file = path20.join(this.dataDir, FILE_NAME);
|
|
38695
38643
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
38696
38644
|
const content = JSON.stringify(
|
|
38697
38645
|
{ contacts: Array.from(this.contacts.values()) },
|
|
@@ -38855,52 +38803,52 @@ async function autoReverseContact(args) {
|
|
|
38855
38803
|
|
|
38856
38804
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
38857
38805
|
var fs22 = __toESM(require("fs"), 1);
|
|
38858
|
-
var
|
|
38806
|
+
var path21 = __toESM(require("path"), 1);
|
|
38859
38807
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
38860
38808
|
function migrateFlattenSessions(opts) {
|
|
38861
38809
|
const dataDir = opts.dataDir;
|
|
38862
38810
|
const now = opts.now ?? Date.now;
|
|
38863
|
-
const sessionsDir =
|
|
38864
|
-
const flagPath =
|
|
38811
|
+
const sessionsDir = path21.join(dataDir, "sessions");
|
|
38812
|
+
const flagPath = path21.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
38865
38813
|
if (existsSync3(flagPath)) {
|
|
38866
38814
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
38867
38815
|
}
|
|
38868
38816
|
let movedBare = 0;
|
|
38869
38817
|
let movedVmOwner = 0;
|
|
38870
38818
|
let archivedListener = 0;
|
|
38871
|
-
const defaultDir =
|
|
38819
|
+
const defaultDir = path21.join(sessionsDir, "default");
|
|
38872
38820
|
if (existsSync3(defaultDir)) {
|
|
38873
38821
|
for (const entry of readdirSafe(defaultDir)) {
|
|
38874
38822
|
if (!entry.endsWith(".json")) continue;
|
|
38875
|
-
const src =
|
|
38876
|
-
const dst =
|
|
38823
|
+
const src = path21.join(defaultDir, entry);
|
|
38824
|
+
const dst = path21.join(sessionsDir, entry);
|
|
38877
38825
|
fs22.renameSync(src, dst);
|
|
38878
38826
|
movedBare += 1;
|
|
38879
38827
|
}
|
|
38880
38828
|
rmdirIfEmpty(defaultDir);
|
|
38881
38829
|
}
|
|
38882
38830
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
38883
|
-
const personaDir =
|
|
38831
|
+
const personaDir = path21.join(sessionsDir, pid);
|
|
38884
38832
|
if (!isDir(personaDir)) continue;
|
|
38885
38833
|
if (pid === "default") continue;
|
|
38886
|
-
const ownerSrc =
|
|
38834
|
+
const ownerSrc = path21.join(personaDir, "owner");
|
|
38887
38835
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
38888
|
-
const ownerDst =
|
|
38836
|
+
const ownerDst = path21.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
38889
38837
|
fs22.mkdirSync(ownerDst, { recursive: true });
|
|
38890
38838
|
for (const file of readdirSafe(ownerSrc)) {
|
|
38891
38839
|
if (!file.endsWith(".json")) continue;
|
|
38892
|
-
fs22.renameSync(
|
|
38840
|
+
fs22.renameSync(path21.join(ownerSrc, file), path21.join(ownerDst, file));
|
|
38893
38841
|
movedVmOwner += 1;
|
|
38894
38842
|
}
|
|
38895
38843
|
rmdirIfEmpty(ownerSrc);
|
|
38896
38844
|
}
|
|
38897
|
-
const listenerSrc =
|
|
38845
|
+
const listenerSrc = path21.join(personaDir, "listener");
|
|
38898
38846
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
38899
|
-
const archiveDst =
|
|
38847
|
+
const archiveDst = path21.join(dataDir, ".legacy", `listener-${pid}`);
|
|
38900
38848
|
fs22.mkdirSync(archiveDst, { recursive: true });
|
|
38901
38849
|
for (const file of readdirSafe(listenerSrc)) {
|
|
38902
38850
|
if (!file.endsWith(".json")) continue;
|
|
38903
|
-
fs22.renameSync(
|
|
38851
|
+
fs22.renameSync(path21.join(listenerSrc, file), path21.join(archiveDst, file));
|
|
38904
38852
|
archivedListener += 1;
|
|
38905
38853
|
}
|
|
38906
38854
|
rmdirIfEmpty(listenerSrc);
|
|
@@ -38948,10 +38896,10 @@ function rmdirIfEmpty(p2) {
|
|
|
38948
38896
|
|
|
38949
38897
|
// src/transport/http-router.ts
|
|
38950
38898
|
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
38951
|
-
var
|
|
38899
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
38952
38900
|
|
|
38953
38901
|
// src/attachment/mime.ts
|
|
38954
|
-
var
|
|
38902
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
38955
38903
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
38956
38904
|
var EXT_TO_NATIVE_MIME = {
|
|
38957
38905
|
// 图片
|
|
@@ -39058,7 +39006,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
39058
39006
|
".mk"
|
|
39059
39007
|
]);
|
|
39060
39008
|
function lookupMime(filePathOrName) {
|
|
39061
|
-
const ext =
|
|
39009
|
+
const ext = import_node_path14.default.extname(filePathOrName).toLowerCase();
|
|
39062
39010
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
39063
39011
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
39064
39012
|
return "application/octet-stream";
|
|
@@ -39128,7 +39076,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
39128
39076
|
|
|
39129
39077
|
// src/attachment/upload.ts
|
|
39130
39078
|
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
39131
|
-
var
|
|
39079
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
39132
39080
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
39133
39081
|
var import_promises = require("stream/promises");
|
|
39134
39082
|
var UploadError = class extends Error {
|
|
@@ -39140,14 +39088,14 @@ var UploadError = class extends Error {
|
|
|
39140
39088
|
code;
|
|
39141
39089
|
};
|
|
39142
39090
|
function assertValidFileName(fileName) {
|
|
39143
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
39091
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path15.default.basename(fileName)) {
|
|
39144
39092
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
39145
39093
|
}
|
|
39146
39094
|
}
|
|
39147
39095
|
var HASH_PREFIX_LEN = 16;
|
|
39148
39096
|
async function writeUploadedAttachment(args) {
|
|
39149
39097
|
assertValidFileName(args.fileName);
|
|
39150
|
-
const attachmentsRoot =
|
|
39098
|
+
const attachmentsRoot = import_node_path15.default.join(args.sessionDir, ".attachments");
|
|
39151
39099
|
try {
|
|
39152
39100
|
import_node_fs16.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
39153
39101
|
} catch (err) {
|
|
@@ -39155,7 +39103,7 @@ async function writeUploadedAttachment(args) {
|
|
|
39155
39103
|
}
|
|
39156
39104
|
const hasher = import_node_crypto5.default.createHash("sha256");
|
|
39157
39105
|
let actualSize = 0;
|
|
39158
|
-
const tmpPath =
|
|
39106
|
+
const tmpPath = import_node_path15.default.join(
|
|
39159
39107
|
attachmentsRoot,
|
|
39160
39108
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto5.default.randomBytes(4).toString("hex")}`
|
|
39161
39109
|
);
|
|
@@ -39190,7 +39138,7 @@ async function writeUploadedAttachment(args) {
|
|
|
39190
39138
|
);
|
|
39191
39139
|
}
|
|
39192
39140
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
39193
|
-
const hashDir =
|
|
39141
|
+
const hashDir = import_node_path15.default.join(attachmentsRoot, attachmentId);
|
|
39194
39142
|
let finalFileName;
|
|
39195
39143
|
let hashDirExists = false;
|
|
39196
39144
|
try {
|
|
@@ -39208,7 +39156,7 @@ async function writeUploadedAttachment(args) {
|
|
|
39208
39156
|
try {
|
|
39209
39157
|
import_node_fs16.default.mkdirSync(hashDir, { recursive: true });
|
|
39210
39158
|
finalFileName = args.fileName;
|
|
39211
|
-
import_node_fs16.default.renameSync(tmpPath,
|
|
39159
|
+
import_node_fs16.default.renameSync(tmpPath, import_node_path15.default.join(hashDir, finalFileName));
|
|
39212
39160
|
} catch (err) {
|
|
39213
39161
|
try {
|
|
39214
39162
|
import_node_fs16.default.unlinkSync(tmpPath);
|
|
@@ -39217,8 +39165,8 @@ async function writeUploadedAttachment(args) {
|
|
|
39217
39165
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
39218
39166
|
}
|
|
39219
39167
|
}
|
|
39220
|
-
const absPath =
|
|
39221
|
-
const relPath =
|
|
39168
|
+
const absPath = import_node_path15.default.join(hashDir, finalFileName);
|
|
39169
|
+
const relPath = import_node_path15.default.relative(args.sessionDir, absPath);
|
|
39222
39170
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
39223
39171
|
relPath: absPath,
|
|
39224
39172
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -39232,8 +39180,8 @@ async function writeUploadedAttachment(args) {
|
|
|
39232
39180
|
|
|
39233
39181
|
// src/extension/import.ts
|
|
39234
39182
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
39235
|
-
var
|
|
39236
|
-
var
|
|
39183
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
39184
|
+
var import_node_os10 = __toESM(require("os"), 1);
|
|
39237
39185
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
39238
39186
|
var ImportError = class extends Error {
|
|
39239
39187
|
constructor(code, message) {
|
|
@@ -39250,7 +39198,7 @@ async function importZip(buf, root) {
|
|
|
39250
39198
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
39251
39199
|
}
|
|
39252
39200
|
for (const name of Object.keys(zip.files)) {
|
|
39253
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
39201
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path16.default.isAbsolute(name)) {
|
|
39254
39202
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
39255
39203
|
}
|
|
39256
39204
|
}
|
|
@@ -39283,7 +39231,7 @@ async function importZip(buf, root) {
|
|
|
39283
39231
|
);
|
|
39284
39232
|
}
|
|
39285
39233
|
}
|
|
39286
|
-
const destDir =
|
|
39234
|
+
const destDir = import_node_path16.default.join(root, manifest.id);
|
|
39287
39235
|
let destExists = false;
|
|
39288
39236
|
try {
|
|
39289
39237
|
await import_promises2.default.access(destDir);
|
|
@@ -39293,15 +39241,15 @@ async function importZip(buf, root) {
|
|
|
39293
39241
|
if (destExists) {
|
|
39294
39242
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
39295
39243
|
}
|
|
39296
|
-
const stage = await import_promises2.default.mkdtemp(
|
|
39244
|
+
const stage = await import_promises2.default.mkdtemp(import_node_path16.default.join(import_node_os10.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
39297
39245
|
try {
|
|
39298
39246
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
39299
|
-
const dest =
|
|
39247
|
+
const dest = import_node_path16.default.join(stage, name);
|
|
39300
39248
|
if (entry.dir) {
|
|
39301
39249
|
await import_promises2.default.mkdir(dest, { recursive: true });
|
|
39302
39250
|
continue;
|
|
39303
39251
|
}
|
|
39304
|
-
await import_promises2.default.mkdir(
|
|
39252
|
+
await import_promises2.default.mkdir(import_node_path16.default.dirname(dest), { recursive: true });
|
|
39305
39253
|
const content = await entry.async("nodebuffer");
|
|
39306
39254
|
await import_promises2.default.writeFile(dest, content);
|
|
39307
39255
|
}
|
|
@@ -39415,7 +39363,7 @@ function isValidUploadFileName(fileName) {
|
|
|
39415
39363
|
if (fileName === "." || fileName === "..") return false;
|
|
39416
39364
|
if (fileName.startsWith(".")) return false;
|
|
39417
39365
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
39418
|
-
return fileName ===
|
|
39366
|
+
return fileName === import_node_path17.default.basename(fileName);
|
|
39419
39367
|
}
|
|
39420
39368
|
function createHttpRouter(deps) {
|
|
39421
39369
|
return async (req, res) => {
|
|
@@ -39644,7 +39592,7 @@ function createHttpRouter(deps) {
|
|
|
39644
39592
|
return true;
|
|
39645
39593
|
}
|
|
39646
39594
|
let absPath;
|
|
39647
|
-
if (
|
|
39595
|
+
if (import_node_path17.default.isAbsolute(pathParam)) {
|
|
39648
39596
|
absPath = pathParam;
|
|
39649
39597
|
} else if (deps.sessionStore) {
|
|
39650
39598
|
const file = deps.sessionStore.read(sid);
|
|
@@ -39652,7 +39600,7 @@ function createHttpRouter(deps) {
|
|
|
39652
39600
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
39653
39601
|
return true;
|
|
39654
39602
|
}
|
|
39655
|
-
absPath =
|
|
39603
|
+
absPath = import_node_path17.default.join(file.cwd, pathParam);
|
|
39656
39604
|
} else {
|
|
39657
39605
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
39658
39606
|
return true;
|
|
@@ -39750,7 +39698,7 @@ function streamFile(res, absPath, logger) {
|
|
|
39750
39698
|
return;
|
|
39751
39699
|
}
|
|
39752
39700
|
const mime = lookupMime(absPath);
|
|
39753
|
-
const basename =
|
|
39701
|
+
const basename = import_node_path17.default.basename(absPath);
|
|
39754
39702
|
res.writeHead(200, {
|
|
39755
39703
|
"Content-Type": mime,
|
|
39756
39704
|
"Content-Length": String(stat.size),
|
|
@@ -39768,7 +39716,7 @@ function streamFile(res, absPath, logger) {
|
|
|
39768
39716
|
|
|
39769
39717
|
// src/attachment/gc.ts
|
|
39770
39718
|
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
39771
|
-
var
|
|
39719
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
39772
39720
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
39773
39721
|
function runAttachmentGc(args) {
|
|
39774
39722
|
const now = (args.now ?? Date.now)();
|
|
@@ -39777,17 +39725,17 @@ function runAttachmentGc(args) {
|
|
|
39777
39725
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
39778
39726
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
39779
39727
|
if (entry.stale) continue;
|
|
39780
|
-
if (
|
|
39728
|
+
if (import_node_path18.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
39781
39729
|
}
|
|
39782
39730
|
}
|
|
39783
39731
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
39784
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
39732
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path18.default.join(
|
|
39785
39733
|
args.dataDir,
|
|
39786
39734
|
"sessions",
|
|
39787
39735
|
...scopeSubPath(scope).map(safeFileName),
|
|
39788
39736
|
safeFileName(sessionId)
|
|
39789
39737
|
);
|
|
39790
|
-
const attRoot =
|
|
39738
|
+
const attRoot = import_node_path18.default.join(sessionDir, ".attachments");
|
|
39791
39739
|
let hashDirs;
|
|
39792
39740
|
try {
|
|
39793
39741
|
hashDirs = import_node_fs18.default.readdirSync(attRoot);
|
|
@@ -39797,7 +39745,7 @@ function runAttachmentGc(args) {
|
|
|
39797
39745
|
continue;
|
|
39798
39746
|
}
|
|
39799
39747
|
for (const hashDir of hashDirs) {
|
|
39800
|
-
const hashDirAbs =
|
|
39748
|
+
const hashDirAbs = import_node_path18.default.join(attRoot, hashDir);
|
|
39801
39749
|
let files;
|
|
39802
39750
|
try {
|
|
39803
39751
|
files = import_node_fs18.default.readdirSync(hashDirAbs);
|
|
@@ -39805,7 +39753,7 @@ function runAttachmentGc(args) {
|
|
|
39805
39753
|
continue;
|
|
39806
39754
|
}
|
|
39807
39755
|
for (const name of files) {
|
|
39808
|
-
const file =
|
|
39756
|
+
const file = import_node_path18.default.join(hashDirAbs, name);
|
|
39809
39757
|
let stat;
|
|
39810
39758
|
try {
|
|
39811
39759
|
stat = import_node_fs18.default.statSync(file);
|
|
@@ -39836,7 +39784,7 @@ function runAttachmentGc(args) {
|
|
|
39836
39784
|
|
|
39837
39785
|
// src/attachment/group.ts
|
|
39838
39786
|
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
39839
|
-
var
|
|
39787
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
39840
39788
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
39841
39789
|
init_protocol();
|
|
39842
39790
|
var GroupFileStore = class {
|
|
@@ -39848,11 +39796,11 @@ var GroupFileStore = class {
|
|
|
39848
39796
|
this.logger = opts.logger;
|
|
39849
39797
|
}
|
|
39850
39798
|
rootForScope(scope) {
|
|
39851
|
-
return
|
|
39799
|
+
return import_node_path19.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
39852
39800
|
}
|
|
39853
39801
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
39854
39802
|
filePath(scope, sessionId) {
|
|
39855
|
-
return
|
|
39803
|
+
return import_node_path19.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
39856
39804
|
}
|
|
39857
39805
|
cacheKey(scope, sessionId) {
|
|
39858
39806
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -39887,7 +39835,7 @@ var GroupFileStore = class {
|
|
|
39887
39835
|
}
|
|
39888
39836
|
writeFile(scope, sessionId, entries) {
|
|
39889
39837
|
const file = this.filePath(scope, sessionId);
|
|
39890
|
-
import_node_fs19.default.mkdirSync(
|
|
39838
|
+
import_node_fs19.default.mkdirSync(import_node_path19.default.dirname(file), { recursive: true });
|
|
39891
39839
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
39892
39840
|
import_node_fs19.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
39893
39841
|
import_node_fs19.default.renameSync(tmp, file);
|
|
@@ -39977,9 +39925,9 @@ var GroupFileStore = class {
|
|
|
39977
39925
|
|
|
39978
39926
|
// src/discovery/state-file.ts
|
|
39979
39927
|
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
39980
|
-
var
|
|
39928
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
39981
39929
|
function defaultStateFilePath(dataDir) {
|
|
39982
|
-
return
|
|
39930
|
+
return import_node_path20.default.join(dataDir, "state.json");
|
|
39983
39931
|
}
|
|
39984
39932
|
function isPidAlive(pid) {
|
|
39985
39933
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -40015,7 +39963,7 @@ var StateFileManager = class {
|
|
|
40015
39963
|
return { status: "stale", existing };
|
|
40016
39964
|
}
|
|
40017
39965
|
write(state) {
|
|
40018
|
-
import_node_fs20.default.mkdirSync(
|
|
39966
|
+
import_node_fs20.default.mkdirSync(import_node_path20.default.dirname(this.file), { recursive: true });
|
|
40019
39967
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
40020
39968
|
import_node_fs20.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
40021
39969
|
import_node_fs20.default.renameSync(tmp, this.file);
|
|
@@ -40044,13 +39992,13 @@ function readDaemonSourceFromEnv(env = process.env) {
|
|
|
40044
39992
|
|
|
40045
39993
|
// src/tunnel/tunnel-manager.ts
|
|
40046
39994
|
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
40047
|
-
var
|
|
39995
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
40048
39996
|
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
40049
39997
|
var import_node_child_process9 = require("child_process");
|
|
40050
39998
|
|
|
40051
39999
|
// src/tunnel/tunnel-store.ts
|
|
40052
40000
|
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
40053
|
-
var
|
|
40001
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
40054
40002
|
var TunnelStore = class {
|
|
40055
40003
|
constructor(filePath) {
|
|
40056
40004
|
this.filePath = filePath;
|
|
@@ -40069,7 +40017,7 @@ var TunnelStore = class {
|
|
|
40069
40017
|
}
|
|
40070
40018
|
}
|
|
40071
40019
|
async set(v2) {
|
|
40072
|
-
const dir =
|
|
40020
|
+
const dir = import_node_path21.default.dirname(this.filePath);
|
|
40073
40021
|
await import_node_fs21.default.promises.mkdir(dir, { recursive: true });
|
|
40074
40022
|
const data = JSON.stringify(v2, null, 2);
|
|
40075
40023
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
@@ -40180,8 +40128,8 @@ function escape(v2) {
|
|
|
40180
40128
|
|
|
40181
40129
|
// src/tunnel/frpc-binary.ts
|
|
40182
40130
|
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
40183
|
-
var
|
|
40184
|
-
var
|
|
40131
|
+
var import_node_os11 = __toESM(require("os"), 1);
|
|
40132
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
40185
40133
|
var import_node_child_process7 = require("child_process");
|
|
40186
40134
|
var import_node_stream2 = require("stream");
|
|
40187
40135
|
var import_promises3 = require("stream/promises");
|
|
@@ -40220,13 +40168,13 @@ async function ensureFrpcBinary(opts) {
|
|
|
40220
40168
|
}
|
|
40221
40169
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
40222
40170
|
const platform = opts.platform ?? detectPlatform();
|
|
40223
|
-
const binDir =
|
|
40171
|
+
const binDir = import_node_path22.default.join(opts.dataDir, "bin");
|
|
40224
40172
|
import_node_fs22.default.mkdirSync(binDir, { recursive: true });
|
|
40225
40173
|
cleanupStaleArtifacts(binDir);
|
|
40226
|
-
const stableBin =
|
|
40174
|
+
const stableBin = import_node_path22.default.join(binDir, "frpc");
|
|
40227
40175
|
if (import_node_fs22.default.existsSync(stableBin)) return stableBin;
|
|
40228
40176
|
const partialBin = `${stableBin}.partial`;
|
|
40229
|
-
const tarballPath =
|
|
40177
|
+
const tarballPath = import_node_path22.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
40230
40178
|
try {
|
|
40231
40179
|
const url = frpcDownloadUrl(version2, platform);
|
|
40232
40180
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -40252,7 +40200,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
40252
40200
|
}
|
|
40253
40201
|
for (const name of entries) {
|
|
40254
40202
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
40255
|
-
const full =
|
|
40203
|
+
const full = import_node_path22.default.join(binDir, name);
|
|
40256
40204
|
try {
|
|
40257
40205
|
import_node_fs22.default.rmSync(full, { recursive: true, force: true });
|
|
40258
40206
|
} catch {
|
|
@@ -40278,7 +40226,7 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
40278
40226
|
await (0, import_promises3.pipeline)(nodeStream, out);
|
|
40279
40227
|
}
|
|
40280
40228
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
40281
|
-
const work =
|
|
40229
|
+
const work = import_node_path22.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
40282
40230
|
import_node_fs22.default.mkdirSync(work, { recursive: true });
|
|
40283
40231
|
try {
|
|
40284
40232
|
await new Promise((resolve6, reject) => {
|
|
@@ -40287,7 +40235,7 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
40287
40235
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
40288
40236
|
});
|
|
40289
40237
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
40290
|
-
const src =
|
|
40238
|
+
const src = import_node_path22.default.join(work, dirName, "frpc");
|
|
40291
40239
|
if (!import_node_fs22.default.existsSync(src)) {
|
|
40292
40240
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
40293
40241
|
}
|
|
@@ -40299,10 +40247,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
40299
40247
|
|
|
40300
40248
|
// src/tunnel/frpc-process.ts
|
|
40301
40249
|
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
40302
|
-
var
|
|
40250
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
40303
40251
|
var import_node_child_process8 = require("child_process");
|
|
40304
40252
|
function frpcPidFilePath(dataDir) {
|
|
40305
|
-
return
|
|
40253
|
+
return import_node_path23.default.join(dataDir, "frpc.pid");
|
|
40306
40254
|
}
|
|
40307
40255
|
function writeFrpcPid(dataDir, pid) {
|
|
40308
40256
|
try {
|
|
@@ -40344,7 +40292,7 @@ function defaultSleep(ms) {
|
|
|
40344
40292
|
}
|
|
40345
40293
|
async function killStaleFrpc(deps) {
|
|
40346
40294
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
40347
|
-
const tomlPath =
|
|
40295
|
+
const tomlPath = import_node_path23.default.join(deps.dataDir, "frpc.toml");
|
|
40348
40296
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
40349
40297
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
40350
40298
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -40416,7 +40364,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
40416
40364
|
var TunnelManager = class {
|
|
40417
40365
|
constructor(deps) {
|
|
40418
40366
|
this.deps = deps;
|
|
40419
|
-
this.store = deps.store ?? new TunnelStore(
|
|
40367
|
+
this.store = deps.store ?? new TunnelStore(import_node_path24.default.join(deps.dataDir, "tunnel.json"));
|
|
40420
40368
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
40421
40369
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
40422
40370
|
}
|
|
@@ -40543,7 +40491,7 @@ var TunnelManager = class {
|
|
|
40543
40491
|
dataDir: this.deps.dataDir,
|
|
40544
40492
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
40545
40493
|
});
|
|
40546
|
-
const tomlPath =
|
|
40494
|
+
const tomlPath = import_node_path24.default.join(this.deps.dataDir, "frpc.toml");
|
|
40547
40495
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
|
|
40548
40496
|
const toml = buildFrpcToml({
|
|
40549
40497
|
serverAddr: t.frpsHost,
|
|
@@ -40558,7 +40506,7 @@ var TunnelManager = class {
|
|
|
40558
40506
|
const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
|
|
40559
40507
|
stdio: ["ignore", "pipe", "pipe"]
|
|
40560
40508
|
});
|
|
40561
|
-
const logFilePath =
|
|
40509
|
+
const logFilePath = import_node_path24.default.join(this.deps.dataDir, "frpc.log");
|
|
40562
40510
|
const logStream = import_node_fs24.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
40563
40511
|
logStream.on("error", () => {
|
|
40564
40512
|
});
|
|
@@ -40641,16 +40589,16 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
40641
40589
|
}
|
|
40642
40590
|
|
|
40643
40591
|
// src/tunnel/device-key.ts
|
|
40644
|
-
var
|
|
40645
|
-
var
|
|
40592
|
+
var import_node_os12 = __toESM(require("os"), 1);
|
|
40593
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
40646
40594
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
40647
40595
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
40648
40596
|
function deriveStableDeviceKey(opts = {}) {
|
|
40649
|
-
const hostname = opts.hostname ??
|
|
40650
|
-
const uid = opts.uid ?? (typeof
|
|
40651
|
-
const home = opts.home ??
|
|
40652
|
-
const defaultDataDir =
|
|
40653
|
-
const normalizedDataDir = opts.dataDir ?
|
|
40597
|
+
const hostname = opts.hostname ?? import_node_os12.default.hostname();
|
|
40598
|
+
const uid = opts.uid ?? (typeof import_node_os12.default.userInfo === "function" ? import_node_os12.default.userInfo().uid : 0);
|
|
40599
|
+
const home = opts.home ?? import_node_os12.default.homedir();
|
|
40600
|
+
const defaultDataDir = import_node_path25.default.resolve(import_node_path25.default.join(home, ".clawd"));
|
|
40601
|
+
const normalizedDataDir = opts.dataDir ? import_node_path25.default.resolve(opts.dataDir) : null;
|
|
40654
40602
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
40655
40603
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
40656
40604
|
return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
@@ -40658,11 +40606,11 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
40658
40606
|
|
|
40659
40607
|
// src/auth-store.ts
|
|
40660
40608
|
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
40661
|
-
var
|
|
40609
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
40662
40610
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
40663
40611
|
var AUTH_FILE_NAME = "auth.json";
|
|
40664
40612
|
function authFilePath(dataDir) {
|
|
40665
|
-
return
|
|
40613
|
+
return import_node_path26.default.join(dataDir, AUTH_FILE_NAME);
|
|
40666
40614
|
}
|
|
40667
40615
|
function loadOrCreateAuthFile(opts) {
|
|
40668
40616
|
const file = authFilePath(opts.dataDir);
|
|
@@ -40715,7 +40663,7 @@ function readAuthFile(file) {
|
|
|
40715
40663
|
}
|
|
40716
40664
|
}
|
|
40717
40665
|
function writeAuthFile(file, content) {
|
|
40718
|
-
import_node_fs25.default.mkdirSync(
|
|
40666
|
+
import_node_fs25.default.mkdirSync(import_node_path26.default.dirname(file), { recursive: true });
|
|
40719
40667
|
import_node_fs25.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
40720
40668
|
try {
|
|
40721
40669
|
import_node_fs25.default.chmodSync(file, 384);
|
|
@@ -40725,12 +40673,12 @@ function writeAuthFile(file, content) {
|
|
|
40725
40673
|
|
|
40726
40674
|
// src/owner-profile.ts
|
|
40727
40675
|
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
40728
|
-
var
|
|
40729
|
-
var
|
|
40676
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
40677
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
40730
40678
|
var PROFILE_FILENAME = "profile.json";
|
|
40731
40679
|
function loadOwnerDisplayName(dataDir) {
|
|
40732
|
-
const fallback =
|
|
40733
|
-
const profilePath =
|
|
40680
|
+
const fallback = import_node_os13.default.userInfo().username;
|
|
40681
|
+
const profilePath = import_node_path27.default.join(dataDir, PROFILE_FILENAME);
|
|
40734
40682
|
let raw;
|
|
40735
40683
|
try {
|
|
40736
40684
|
raw = import_node_fs26.default.readFileSync(profilePath, "utf8");
|
|
@@ -40757,12 +40705,12 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
40757
40705
|
|
|
40758
40706
|
// src/feishu-auth/owner-identity-store.ts
|
|
40759
40707
|
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
40760
|
-
var
|
|
40708
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
40761
40709
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
40762
40710
|
var OwnerIdentityStore = class {
|
|
40763
40711
|
file;
|
|
40764
40712
|
constructor(dataDir) {
|
|
40765
|
-
this.file =
|
|
40713
|
+
this.file = import_node_path28.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
40766
40714
|
}
|
|
40767
40715
|
read() {
|
|
40768
40716
|
let raw;
|
|
@@ -40794,7 +40742,7 @@ var OwnerIdentityStore = class {
|
|
|
40794
40742
|
};
|
|
40795
40743
|
}
|
|
40796
40744
|
write(record) {
|
|
40797
|
-
import_node_fs27.default.mkdirSync(
|
|
40745
|
+
import_node_fs27.default.mkdirSync(import_node_path28.default.dirname(this.file), { recursive: true });
|
|
40798
40746
|
import_node_fs27.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
40799
40747
|
try {
|
|
40800
40748
|
import_node_fs27.default.chmodSync(this.file, 384);
|
|
@@ -40922,9 +40870,9 @@ var CentralClientError = class extends Error {
|
|
|
40922
40870
|
code;
|
|
40923
40871
|
cause;
|
|
40924
40872
|
};
|
|
40925
|
-
async function centralRequest(opts,
|
|
40873
|
+
async function centralRequest(opts, path58, init) {
|
|
40926
40874
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
40927
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
40875
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path58}`;
|
|
40928
40876
|
const ctrl = new AbortController();
|
|
40929
40877
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
40930
40878
|
let res;
|
|
@@ -41067,7 +41015,7 @@ function verifyConnectToken(args) {
|
|
|
41067
41015
|
|
|
41068
41016
|
// src/feishu-auth/server-key.ts
|
|
41069
41017
|
var fs36 = __toESM(require("fs"), 1);
|
|
41070
|
-
var
|
|
41018
|
+
var path37 = __toESM(require("path"), 1);
|
|
41071
41019
|
var FILE_NAME2 = "server-signing-key.json";
|
|
41072
41020
|
var ServerKeyStore = class {
|
|
41073
41021
|
constructor(dataDir) {
|
|
@@ -41075,7 +41023,7 @@ var ServerKeyStore = class {
|
|
|
41075
41023
|
}
|
|
41076
41024
|
dataDir;
|
|
41077
41025
|
filePath() {
|
|
41078
|
-
return
|
|
41026
|
+
return path37.join(this.dataDir, FILE_NAME2);
|
|
41079
41027
|
}
|
|
41080
41028
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
41081
41029
|
read() {
|
|
@@ -41114,8 +41062,8 @@ init_protocol();
|
|
|
41114
41062
|
|
|
41115
41063
|
// src/session/fork.ts
|
|
41116
41064
|
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
41117
|
-
var
|
|
41118
|
-
var
|
|
41065
|
+
var import_node_os14 = __toESM(require("os"), 1);
|
|
41066
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
41119
41067
|
init_claude_history();
|
|
41120
41068
|
function readJsonlEntries(file) {
|
|
41121
41069
|
const raw = import_node_fs28.default.readFileSync(file, "utf8");
|
|
@@ -41131,9 +41079,9 @@ function readJsonlEntries(file) {
|
|
|
41131
41079
|
return out;
|
|
41132
41080
|
}
|
|
41133
41081
|
function forkSession(input) {
|
|
41134
|
-
const baseDir = input.baseDir ??
|
|
41135
|
-
const projectDir =
|
|
41136
|
-
const sourceFile =
|
|
41082
|
+
const baseDir = input.baseDir ?? import_node_path29.default.join(import_node_os14.default.homedir(), ".claude");
|
|
41083
|
+
const projectDir = import_node_path29.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
41084
|
+
const sourceFile = import_node_path29.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
41137
41085
|
if (!import_node_fs28.default.existsSync(sourceFile)) {
|
|
41138
41086
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
41139
41087
|
}
|
|
@@ -41164,7 +41112,7 @@ function forkSession(input) {
|
|
|
41164
41112
|
}
|
|
41165
41113
|
forkedLines.push(JSON.stringify(forked));
|
|
41166
41114
|
}
|
|
41167
|
-
const forkedFilePath =
|
|
41115
|
+
const forkedFilePath = import_node_path29.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
41168
41116
|
import_node_fs28.default.mkdirSync(projectDir, { recursive: true });
|
|
41169
41117
|
import_node_fs28.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
41170
41118
|
return { forkedToolSessionId, forkedFilePath };
|
|
@@ -41542,7 +41490,7 @@ function buildPermissionHandlers(deps) {
|
|
|
41542
41490
|
}
|
|
41543
41491
|
|
|
41544
41492
|
// src/handlers/history.ts
|
|
41545
|
-
var
|
|
41493
|
+
var path40 = __toESM(require("path"), 1);
|
|
41546
41494
|
init_protocol();
|
|
41547
41495
|
|
|
41548
41496
|
// src/session/recent-dirs.ts
|
|
@@ -41560,7 +41508,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
41560
41508
|
}
|
|
41561
41509
|
|
|
41562
41510
|
// src/permission/persona-paths.ts
|
|
41563
|
-
var
|
|
41511
|
+
var path39 = __toESM(require("path"), 1);
|
|
41564
41512
|
function getAllowedPersonaIds(grants, action) {
|
|
41565
41513
|
const ids = /* @__PURE__ */ new Set();
|
|
41566
41514
|
for (const g2 of grants) {
|
|
@@ -41573,31 +41521,31 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
41573
41521
|
return ids;
|
|
41574
41522
|
}
|
|
41575
41523
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
41576
|
-
const target =
|
|
41524
|
+
const target = path39.resolve(absPath);
|
|
41577
41525
|
if (userWorkDir) {
|
|
41578
|
-
const u =
|
|
41579
|
-
const usep = u.endsWith(
|
|
41526
|
+
const u = path39.resolve(userWorkDir);
|
|
41527
|
+
const usep = u.endsWith(path39.sep) ? "" : path39.sep;
|
|
41580
41528
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
41581
41529
|
}
|
|
41582
|
-
const root =
|
|
41583
|
-
const sep2 = root.endsWith(
|
|
41530
|
+
const root = path39.resolve(personaRoot);
|
|
41531
|
+
const sep2 = root.endsWith(path39.sep) ? "" : path39.sep;
|
|
41584
41532
|
if (!target.startsWith(root + sep2)) return false;
|
|
41585
|
-
const rel =
|
|
41533
|
+
const rel = path39.relative(root, target);
|
|
41586
41534
|
if (!rel || rel.startsWith("..")) return false;
|
|
41587
|
-
const personaId = rel.split(
|
|
41535
|
+
const personaId = rel.split(path39.sep)[0];
|
|
41588
41536
|
if (!personaId) return false;
|
|
41589
41537
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
41590
41538
|
if (allowed === "*") return true;
|
|
41591
41539
|
return allowed.has(personaId);
|
|
41592
41540
|
}
|
|
41593
41541
|
function personaIdFromPath(absPath, personaRoot) {
|
|
41594
|
-
const root =
|
|
41595
|
-
const target =
|
|
41596
|
-
const sep2 = root.endsWith(
|
|
41542
|
+
const root = path39.resolve(personaRoot);
|
|
41543
|
+
const target = path39.resolve(absPath);
|
|
41544
|
+
const sep2 = root.endsWith(path39.sep) ? "" : path39.sep;
|
|
41597
41545
|
if (!target.startsWith(root + sep2)) return null;
|
|
41598
|
-
const rel =
|
|
41546
|
+
const rel = path39.relative(root, target);
|
|
41599
41547
|
if (!rel || rel.startsWith("..")) return null;
|
|
41600
|
-
const id = rel.split(
|
|
41548
|
+
const id = rel.split(path39.sep)[0];
|
|
41601
41549
|
return id || null;
|
|
41602
41550
|
}
|
|
41603
41551
|
|
|
@@ -41624,7 +41572,7 @@ function buildHistoryHandlers(deps) {
|
|
|
41624
41572
|
if (!pid) return false;
|
|
41625
41573
|
return isGuestPathAllowed(
|
|
41626
41574
|
ctx.grants,
|
|
41627
|
-
|
|
41575
|
+
path40.join(personaRoot, pid),
|
|
41628
41576
|
personaRoot,
|
|
41629
41577
|
"read",
|
|
41630
41578
|
userWorkDir
|
|
@@ -41636,7 +41584,7 @@ function buildHistoryHandlers(deps) {
|
|
|
41636
41584
|
};
|
|
41637
41585
|
const list = async (frame, _client, ctx) => {
|
|
41638
41586
|
const args = HistoryListArgs.parse(frame);
|
|
41639
|
-
assertGuestPath(ctx,
|
|
41587
|
+
assertGuestPath(ctx, path40.resolve(args.projectPath), personaRoot, "history:list");
|
|
41640
41588
|
const sessions = await history.listSessions(args);
|
|
41641
41589
|
return { response: { type: "history:list", sessions } };
|
|
41642
41590
|
};
|
|
@@ -41668,13 +41616,13 @@ function buildHistoryHandlers(deps) {
|
|
|
41668
41616
|
};
|
|
41669
41617
|
const subagents = async (frame, _client, ctx) => {
|
|
41670
41618
|
const args = HistorySubagentsArgs.parse(frame);
|
|
41671
|
-
assertGuestPath(ctx,
|
|
41619
|
+
assertGuestPath(ctx, path40.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
41672
41620
|
const subs = await history.listSubagents(args);
|
|
41673
41621
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
41674
41622
|
};
|
|
41675
41623
|
const subagentRead = async (frame, _client, ctx) => {
|
|
41676
41624
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
41677
|
-
assertGuestPath(ctx,
|
|
41625
|
+
assertGuestPath(ctx, path40.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
41678
41626
|
const res = await history.readSubagent(args);
|
|
41679
41627
|
return { response: { type: "history:subagent-read", ...res } };
|
|
41680
41628
|
};
|
|
@@ -41683,7 +41631,7 @@ function buildHistoryHandlers(deps) {
|
|
|
41683
41631
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
41684
41632
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
41685
41633
|
const filtered = dirs.filter(
|
|
41686
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
41634
|
+
(d) => isGuestPathAllowed(ctx.grants, path40.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
41687
41635
|
);
|
|
41688
41636
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
41689
41637
|
}
|
|
@@ -41700,8 +41648,8 @@ function buildHistoryHandlers(deps) {
|
|
|
41700
41648
|
}
|
|
41701
41649
|
|
|
41702
41650
|
// src/handlers/workspace.ts
|
|
41703
|
-
var
|
|
41704
|
-
var
|
|
41651
|
+
var path41 = __toESM(require("path"), 1);
|
|
41652
|
+
var os15 = __toESM(require("os"), 1);
|
|
41705
41653
|
init_protocol();
|
|
41706
41654
|
init_protocol();
|
|
41707
41655
|
function buildEnabledPluginNames(personaManager, personaId) {
|
|
@@ -41741,23 +41689,23 @@ function buildWorkspaceHandlers(deps) {
|
|
|
41741
41689
|
const list = async (frame, _client, ctx) => {
|
|
41742
41690
|
const args = WorkspaceListArgs.parse(frame);
|
|
41743
41691
|
const isGuest = ctx?.principal.kind === "guest";
|
|
41744
|
-
const fallbackCwd = isGuest && personaRoot ? personaRoot :
|
|
41745
|
-
const resolvedCwd =
|
|
41746
|
-
const target = args.path ?
|
|
41692
|
+
const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
|
|
41693
|
+
const resolvedCwd = path41.resolve(args.cwd ?? fallbackCwd);
|
|
41694
|
+
const target = args.path ? path41.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
41747
41695
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
41748
41696
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
41749
41697
|
return { response: { type: "workspace:list", ...res } };
|
|
41750
41698
|
};
|
|
41751
41699
|
const read = async (frame, _client, ctx) => {
|
|
41752
41700
|
const args = WorkspaceReadArgs.parse(frame);
|
|
41753
|
-
const target =
|
|
41701
|
+
const target = path41.isAbsolute(args.path) ? path41.resolve(args.path) : path41.resolve(args.cwd, args.path);
|
|
41754
41702
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
41755
41703
|
const res = workspace.read(args);
|
|
41756
41704
|
return { response: { type: "workspace:read", ...res } };
|
|
41757
41705
|
};
|
|
41758
41706
|
const skillsList = async (frame, _client, ctx) => {
|
|
41759
41707
|
const args = SkillsListArgs.parse(frame);
|
|
41760
|
-
const cwdAbs =
|
|
41708
|
+
const cwdAbs = path41.resolve(args.cwd);
|
|
41761
41709
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
41762
41710
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
41763
41711
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -41769,7 +41717,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
41769
41717
|
};
|
|
41770
41718
|
const agentsList = async (frame, _client, ctx) => {
|
|
41771
41719
|
const args = AgentsListArgs.parse(frame);
|
|
41772
|
-
const cwdAbs =
|
|
41720
|
+
const cwdAbs = path41.resolve(args.cwd);
|
|
41773
41721
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
41774
41722
|
if (args.tool === "codex") {
|
|
41775
41723
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -41791,18 +41739,18 @@ function buildWorkspaceHandlers(deps) {
|
|
|
41791
41739
|
}
|
|
41792
41740
|
|
|
41793
41741
|
// src/handlers/git.ts
|
|
41794
|
-
var
|
|
41742
|
+
var path43 = __toESM(require("path"), 1);
|
|
41795
41743
|
init_protocol();
|
|
41796
41744
|
init_protocol();
|
|
41797
41745
|
|
|
41798
41746
|
// src/workspace/git.ts
|
|
41799
41747
|
var import_node_child_process10 = require("child_process");
|
|
41800
41748
|
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
41801
|
-
var
|
|
41749
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
41802
41750
|
var import_node_util = require("util");
|
|
41803
41751
|
var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
|
|
41804
41752
|
function normalizePath(p2) {
|
|
41805
|
-
const resolved =
|
|
41753
|
+
const resolved = import_node_path30.default.resolve(p2);
|
|
41806
41754
|
try {
|
|
41807
41755
|
return import_node_fs29.default.realpathSync(resolved);
|
|
41808
41756
|
} catch {
|
|
@@ -41878,7 +41826,7 @@ async function listGitBranches(cwd) {
|
|
|
41878
41826
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
41879
41827
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
41880
41828
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
41881
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
41829
|
+
if (!isGuestPathAllowed(ctx.grants, path43.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
41882
41830
|
throw new ClawdError(
|
|
41883
41831
|
ERROR_CODES.UNAUTHORIZED,
|
|
41884
41832
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -42266,7 +42214,7 @@ function buildDeviceHandlers(deps) {
|
|
|
42266
42214
|
}
|
|
42267
42215
|
|
|
42268
42216
|
// src/handlers/meta.ts
|
|
42269
|
-
var
|
|
42217
|
+
var import_node_os15 = __toESM(require("os"), 1);
|
|
42270
42218
|
init_protocol();
|
|
42271
42219
|
|
|
42272
42220
|
// src/version.ts
|
|
@@ -42297,7 +42245,7 @@ function buildReadyFrame(deps, client) {
|
|
|
42297
42245
|
return {
|
|
42298
42246
|
version,
|
|
42299
42247
|
protocolVersion: PROTOCOL_VERSION,
|
|
42300
|
-
hostname:
|
|
42248
|
+
hostname: import_node_os15.default.hostname(),
|
|
42301
42249
|
os: process.platform,
|
|
42302
42250
|
tools,
|
|
42303
42251
|
runningSessions: info.runningSessions,
|
|
@@ -42392,7 +42340,7 @@ function buildPersonaHandlers(deps) {
|
|
|
42392
42340
|
}
|
|
42393
42341
|
|
|
42394
42342
|
// src/handlers/attachment.ts
|
|
42395
|
-
var
|
|
42343
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
42396
42344
|
init_protocol();
|
|
42397
42345
|
init_protocol();
|
|
42398
42346
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -42447,12 +42395,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
42447
42395
|
`session ${args.sessionId} scope unresolved`
|
|
42448
42396
|
);
|
|
42449
42397
|
}
|
|
42450
|
-
const cwdAbs =
|
|
42451
|
-
const candidateAbs =
|
|
42398
|
+
const cwdAbs = import_node_path31.default.resolve(sessionFile.cwd);
|
|
42399
|
+
const candidateAbs = import_node_path31.default.isAbsolute(args.relPath) ? import_node_path31.default.resolve(args.relPath) : import_node_path31.default.resolve(cwdAbs, args.relPath);
|
|
42452
42400
|
assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl", deps.usersRoot);
|
|
42453
42401
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
42454
42402
|
const entry = entries.find((e) => {
|
|
42455
|
-
const storedAbs =
|
|
42403
|
+
const storedAbs = import_node_path31.default.isAbsolute(e.relPath) ? import_node_path31.default.resolve(e.relPath) : import_node_path31.default.resolve(cwdAbs, e.relPath);
|
|
42456
42404
|
return storedAbs === candidateAbs && !e.stale;
|
|
42457
42405
|
});
|
|
42458
42406
|
if (!entry) {
|
|
@@ -42476,7 +42424,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
42476
42424
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
42477
42425
|
const f = deps.sessionStore.read(sessionId);
|
|
42478
42426
|
if (!f) return;
|
|
42479
|
-
assertGuestAttachmentPath(ctx,
|
|
42427
|
+
assertGuestAttachmentPath(ctx, import_node_path31.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
42480
42428
|
}
|
|
42481
42429
|
const groupAdd = async (frame, _client, ctx) => {
|
|
42482
42430
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -42548,19 +42496,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
42548
42496
|
|
|
42549
42497
|
// src/handlers/extension.ts
|
|
42550
42498
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
42551
|
-
var
|
|
42499
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
42552
42500
|
init_protocol();
|
|
42553
42501
|
|
|
42554
42502
|
// src/extension/bundle-zip.ts
|
|
42555
42503
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
42556
|
-
var
|
|
42504
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
42557
42505
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
42558
42506
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
42559
42507
|
async function bundleExtensionDir(dir) {
|
|
42560
42508
|
const entries = await listFilesSorted(dir);
|
|
42561
42509
|
const zip = new import_jszip2.default();
|
|
42562
42510
|
for (const rel of entries) {
|
|
42563
|
-
const abs =
|
|
42511
|
+
const abs = import_node_path32.default.join(dir, rel);
|
|
42564
42512
|
const content = await import_promises4.default.readFile(abs);
|
|
42565
42513
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
42566
42514
|
}
|
|
@@ -42581,7 +42529,7 @@ async function listFilesSorted(rootDir) {
|
|
|
42581
42529
|
return out;
|
|
42582
42530
|
}
|
|
42583
42531
|
async function walk(absRoot, relPrefix, out) {
|
|
42584
|
-
const dirAbs =
|
|
42532
|
+
const dirAbs = import_node_path32.default.join(absRoot, relPrefix);
|
|
42585
42533
|
const entries = await import_promises4.default.readdir(dirAbs, { withFileTypes: true });
|
|
42586
42534
|
for (const e of entries) {
|
|
42587
42535
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -42635,25 +42583,25 @@ function computePublishCheck(args) {
|
|
|
42635
42583
|
|
|
42636
42584
|
// src/extension/install-flow.ts
|
|
42637
42585
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
42638
|
-
var
|
|
42639
|
-
var
|
|
42586
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
42587
|
+
var import_node_os17 = __toESM(require("os"), 1);
|
|
42640
42588
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
42641
42589
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
42642
42590
|
|
|
42643
42591
|
// src/extension/paths.ts
|
|
42644
|
-
var
|
|
42645
|
-
var
|
|
42592
|
+
var import_node_os16 = __toESM(require("os"), 1);
|
|
42593
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
42646
42594
|
function clawdHomeRoot(override) {
|
|
42647
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
42595
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path33.default.join(import_node_os16.default.homedir(), ".clawd");
|
|
42648
42596
|
}
|
|
42649
42597
|
function extensionsRoot(override) {
|
|
42650
|
-
return
|
|
42598
|
+
return import_node_path33.default.join(clawdHomeRoot(override), "extensions");
|
|
42651
42599
|
}
|
|
42652
42600
|
function publishedChannelsFile(override) {
|
|
42653
|
-
return
|
|
42601
|
+
return import_node_path33.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
42654
42602
|
}
|
|
42655
42603
|
function bundleCacheRoot(override) {
|
|
42656
|
-
return
|
|
42604
|
+
return import_node_path33.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
42657
42605
|
}
|
|
42658
42606
|
|
|
42659
42607
|
// src/extension/install-flow.ts
|
|
@@ -42680,7 +42628,7 @@ async function installFromChannel(args, deps) {
|
|
|
42680
42628
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
42681
42629
|
}
|
|
42682
42630
|
for (const name of Object.keys(zip.files)) {
|
|
42683
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
42631
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path34.default.isAbsolute(name)) {
|
|
42684
42632
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
42685
42633
|
}
|
|
42686
42634
|
}
|
|
@@ -42712,7 +42660,7 @@ async function installFromChannel(args, deps) {
|
|
|
42712
42660
|
);
|
|
42713
42661
|
}
|
|
42714
42662
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
42715
|
-
const destDir =
|
|
42663
|
+
const destDir = import_node_path34.default.join(deps.extensionsRoot, localExtId);
|
|
42716
42664
|
let destExists = false;
|
|
42717
42665
|
try {
|
|
42718
42666
|
await import_promises5.default.access(destDir);
|
|
@@ -42726,16 +42674,16 @@ async function installFromChannel(args, deps) {
|
|
|
42726
42674
|
);
|
|
42727
42675
|
}
|
|
42728
42676
|
const stage = await import_promises5.default.mkdtemp(
|
|
42729
|
-
|
|
42677
|
+
import_node_path34.default.join(import_node_os17.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
42730
42678
|
);
|
|
42731
42679
|
try {
|
|
42732
42680
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
42733
|
-
const dest =
|
|
42681
|
+
const dest = import_node_path34.default.join(stage, name);
|
|
42734
42682
|
if (entry.dir) {
|
|
42735
42683
|
await import_promises5.default.mkdir(dest, { recursive: true });
|
|
42736
42684
|
continue;
|
|
42737
42685
|
}
|
|
42738
|
-
await import_promises5.default.mkdir(
|
|
42686
|
+
await import_promises5.default.mkdir(import_node_path34.default.dirname(dest), { recursive: true });
|
|
42739
42687
|
if (name === "manifest.json") {
|
|
42740
42688
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
42741
42689
|
await import_promises5.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -42756,8 +42704,8 @@ async function installFromChannel(args, deps) {
|
|
|
42756
42704
|
|
|
42757
42705
|
// src/extension/update-flow.ts
|
|
42758
42706
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
42759
|
-
var
|
|
42760
|
-
var
|
|
42707
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
42708
|
+
var import_node_os18 = __toESM(require("os"), 1);
|
|
42761
42709
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
42762
42710
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
42763
42711
|
var UpdateError = class extends Error {
|
|
@@ -42773,11 +42721,11 @@ async function updateFromChannel(args, deps) {
|
|
|
42773
42721
|
channelRef.extId,
|
|
42774
42722
|
channelRef.ownerPrincipalId
|
|
42775
42723
|
);
|
|
42776
|
-
const liveDir =
|
|
42724
|
+
const liveDir = import_node_path35.default.join(deps.extensionsRoot, localExtId);
|
|
42777
42725
|
const prevDir = `${liveDir}.prev`;
|
|
42778
42726
|
let existingVersion;
|
|
42779
42727
|
try {
|
|
42780
|
-
const raw = await import_promises6.default.readFile(
|
|
42728
|
+
const raw = await import_promises6.default.readFile(import_node_path35.default.join(liveDir, "manifest.json"), "utf8");
|
|
42781
42729
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
42782
42730
|
if (!parsed2.success) {
|
|
42783
42731
|
throw new UpdateError(
|
|
@@ -42810,7 +42758,7 @@ async function updateFromChannel(args, deps) {
|
|
|
42810
42758
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
42811
42759
|
}
|
|
42812
42760
|
for (const name of Object.keys(zip.files)) {
|
|
42813
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
42761
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path35.default.isAbsolute(name)) {
|
|
42814
42762
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
42815
42763
|
}
|
|
42816
42764
|
}
|
|
@@ -42845,16 +42793,16 @@ async function updateFromChannel(args, deps) {
|
|
|
42845
42793
|
await import_promises6.default.rm(prevDir, { recursive: true, force: true });
|
|
42846
42794
|
await import_promises6.default.rename(liveDir, prevDir);
|
|
42847
42795
|
const stage = await import_promises6.default.mkdtemp(
|
|
42848
|
-
|
|
42796
|
+
import_node_path35.default.join(import_node_os18.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
42849
42797
|
);
|
|
42850
42798
|
try {
|
|
42851
42799
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
42852
|
-
const dest =
|
|
42800
|
+
const dest = import_node_path35.default.join(stage, name);
|
|
42853
42801
|
if (entry.dir) {
|
|
42854
42802
|
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
42855
42803
|
continue;
|
|
42856
42804
|
}
|
|
42857
|
-
await import_promises6.default.mkdir(
|
|
42805
|
+
await import_promises6.default.mkdir(import_node_path35.default.dirname(dest), { recursive: true });
|
|
42858
42806
|
if (name === "manifest.json") {
|
|
42859
42807
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
42860
42808
|
await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -42947,7 +42895,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
42947
42895
|
);
|
|
42948
42896
|
}
|
|
42949
42897
|
}
|
|
42950
|
-
const manifestPath =
|
|
42898
|
+
const manifestPath = import_node_path36.default.join(root, extId, "manifest.json");
|
|
42951
42899
|
const manifest = await readManifest(root, extId);
|
|
42952
42900
|
const next = { ...manifest, version: newVersion };
|
|
42953
42901
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -42955,7 +42903,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
42955
42903
|
await import_promises7.default.rename(tmp, manifestPath);
|
|
42956
42904
|
}
|
|
42957
42905
|
async function readManifest(root, extId) {
|
|
42958
|
-
const file =
|
|
42906
|
+
const file = import_node_path36.default.join(root, extId, "manifest.json");
|
|
42959
42907
|
let raw;
|
|
42960
42908
|
try {
|
|
42961
42909
|
raw = await import_promises7.default.readFile(file, "utf8");
|
|
@@ -43046,7 +42994,7 @@ function buildExtensionHandlers(deps) {
|
|
|
43046
42994
|
};
|
|
43047
42995
|
async function buildSnapshotMeta(extId) {
|
|
43048
42996
|
const manifest = await readManifest(deps.root, extId);
|
|
43049
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
42997
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path36.default.join(deps.root, extId));
|
|
43050
42998
|
return { manifest, contentHash: sha256, buffer };
|
|
43051
42999
|
}
|
|
43052
43000
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -43343,7 +43291,7 @@ var PublishJobRegistry = class {
|
|
|
43343
43291
|
// src/app-builder/publish-job-runner.ts
|
|
43344
43292
|
var import_node_child_process12 = require("child_process");
|
|
43345
43293
|
var import_node_fs30 = require("fs");
|
|
43346
|
-
var
|
|
43294
|
+
var import_node_path37 = require("path");
|
|
43347
43295
|
|
|
43348
43296
|
// src/app-builder/publish-stage-parser.ts
|
|
43349
43297
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -43375,7 +43323,7 @@ async function startPublishJob(deps, args) {
|
|
|
43375
43323
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
43376
43324
|
}
|
|
43377
43325
|
const projDir = projectDir(args.name);
|
|
43378
|
-
const logPath = (0,
|
|
43326
|
+
const logPath = (0, import_node_path37.join)(projDir, ".publish.log");
|
|
43379
43327
|
let logStream = null;
|
|
43380
43328
|
try {
|
|
43381
43329
|
logStream = (0, import_node_fs30.createWriteStream)(logPath, { flags: "w" });
|
|
@@ -43635,7 +43583,7 @@ async function recoverInterruptedJobs(deps) {
|
|
|
43635
43583
|
|
|
43636
43584
|
// src/handlers/app-builder.ts
|
|
43637
43585
|
init_protocol();
|
|
43638
|
-
var
|
|
43586
|
+
var import_node_path38 = require("path");
|
|
43639
43587
|
var import_node_fs31 = require("fs");
|
|
43640
43588
|
var APP_BUILDER_PERSONAS = ["persona-app-builder"];
|
|
43641
43589
|
var PUBLISH_SCRIPT_REL = "extension-kit/scripts/publish.sh";
|
|
@@ -44012,7 +43960,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44012
43960
|
});
|
|
44013
43961
|
await userStore.clearPublishJob(args.name);
|
|
44014
43962
|
}
|
|
44015
|
-
const scriptPath = (0,
|
|
43963
|
+
const scriptPath = (0, import_node_path38.join)(deps.personaRoot, PUBLISH_SCRIPT_REL);
|
|
44016
43964
|
deps.logger?.info("app-builder.publish.start", {
|
|
44017
43965
|
name: args.name,
|
|
44018
43966
|
sessionId: boundSession.sessionId,
|
|
@@ -44106,7 +44054,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44106
44054
|
|
|
44107
44055
|
// src/extension/registry.ts
|
|
44108
44056
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
44109
|
-
var
|
|
44057
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
44110
44058
|
async function loadAll(root) {
|
|
44111
44059
|
let entries;
|
|
44112
44060
|
try {
|
|
@@ -44119,13 +44067,13 @@ async function loadAll(root) {
|
|
|
44119
44067
|
for (const ent of entries) {
|
|
44120
44068
|
if (!ent.isDirectory()) continue;
|
|
44121
44069
|
if (ent.name.startsWith(".")) continue;
|
|
44122
|
-
records.push(await loadOne(
|
|
44070
|
+
records.push(await loadOne(import_node_path39.default.join(root, ent.name), ent.name));
|
|
44123
44071
|
}
|
|
44124
44072
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
44125
44073
|
return records;
|
|
44126
44074
|
}
|
|
44127
44075
|
async function loadOne(dir, dirName) {
|
|
44128
|
-
const manifestPath =
|
|
44076
|
+
const manifestPath = import_node_path39.default.join(dir, "manifest.json");
|
|
44129
44077
|
let raw;
|
|
44130
44078
|
try {
|
|
44131
44079
|
raw = await import_promises8.default.readFile(manifestPath, "utf8");
|
|
@@ -44170,7 +44118,7 @@ async function loadOne(dir, dirName) {
|
|
|
44170
44118
|
|
|
44171
44119
|
// src/extension/uninstall.ts
|
|
44172
44120
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
44173
|
-
var
|
|
44121
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
44174
44122
|
var UninstallError = class extends Error {
|
|
44175
44123
|
constructor(code, message) {
|
|
44176
44124
|
super(message);
|
|
@@ -44179,7 +44127,7 @@ var UninstallError = class extends Error {
|
|
|
44179
44127
|
code;
|
|
44180
44128
|
};
|
|
44181
44129
|
async function uninstall(deps) {
|
|
44182
|
-
const dir =
|
|
44130
|
+
const dir = import_node_path40.default.join(deps.root, deps.extId);
|
|
44183
44131
|
try {
|
|
44184
44132
|
await import_promises9.default.access(dir);
|
|
44185
44133
|
} catch {
|
|
@@ -44260,7 +44208,7 @@ function buildMethodHandlers(deps) {
|
|
|
44260
44208
|
// src/app-builder/project-store.ts
|
|
44261
44209
|
var import_node_fs32 = require("fs");
|
|
44262
44210
|
var import_node_child_process13 = require("child_process");
|
|
44263
|
-
var
|
|
44211
|
+
var import_node_path41 = require("path");
|
|
44264
44212
|
init_protocol();
|
|
44265
44213
|
var PROJECTS_DIR = "projects";
|
|
44266
44214
|
var META_FILE = ".clawd-project.json";
|
|
@@ -44275,14 +44223,14 @@ var ProjectStore = class {
|
|
|
44275
44223
|
root;
|
|
44276
44224
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
44277
44225
|
metaPath(name) {
|
|
44278
|
-
return (0,
|
|
44226
|
+
return (0, import_node_path41.join)(this.projectsRoot(), name, META_FILE);
|
|
44279
44227
|
}
|
|
44280
44228
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
44281
44229
|
projectDir(name) {
|
|
44282
|
-
return (0,
|
|
44230
|
+
return (0, import_node_path41.join)(this.projectsRoot(), name);
|
|
44283
44231
|
}
|
|
44284
44232
|
projectsRoot() {
|
|
44285
|
-
return (0,
|
|
44233
|
+
return (0, import_node_path41.join)(this.root, PROJECTS_DIR);
|
|
44286
44234
|
}
|
|
44287
44235
|
async list() {
|
|
44288
44236
|
let entries;
|
|
@@ -44363,7 +44311,7 @@ var ProjectStore = class {
|
|
|
44363
44311
|
* 代码再参考"。assistant 进 project 时目录已是完整模板,直接 pnpm install 即可。
|
|
44364
44312
|
*/
|
|
44365
44313
|
async scaffold(name, template = DEFAULT_TEMPLATE, personaRoot = this.root) {
|
|
44366
|
-
const scriptPath = (0,
|
|
44314
|
+
const scriptPath = (0, import_node_path41.join)(personaRoot, SCAFFOLD_SCRIPT_REL);
|
|
44367
44315
|
const destDir = this.projectDir(name);
|
|
44368
44316
|
return await new Promise((resolve6, reject) => {
|
|
44369
44317
|
const child = (0, import_node_child_process13.spawn)("bash", [scriptPath, name, template, destDir], {
|
|
@@ -44901,7 +44849,7 @@ function computeGrantForFrame(method, frame) {
|
|
|
44901
44849
|
|
|
44902
44850
|
// src/extension/runtime.ts
|
|
44903
44851
|
var import_node_child_process15 = require("child_process");
|
|
44904
|
-
var
|
|
44852
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
44905
44853
|
var import_promises10 = require("timers/promises");
|
|
44906
44854
|
|
|
44907
44855
|
// src/extension/port-allocator.ts
|
|
@@ -45002,7 +44950,7 @@ var Runtime = class {
|
|
|
45002
44950
|
/\$CLAWOS_EXT_PORT/g,
|
|
45003
44951
|
String(port)
|
|
45004
44952
|
);
|
|
45005
|
-
const dir =
|
|
44953
|
+
const dir = import_node_path42.default.join(this.root, extId);
|
|
45006
44954
|
const env = {
|
|
45007
44955
|
...process.env,
|
|
45008
44956
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -45114,7 +45062,7 @@ ${handle.stderrTail}`
|
|
|
45114
45062
|
|
|
45115
45063
|
// src/extension/published-channels.ts
|
|
45116
45064
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
45117
|
-
var
|
|
45065
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
45118
45066
|
init_zod();
|
|
45119
45067
|
var PublishedChannelsError = class extends Error {
|
|
45120
45068
|
constructor(code, message) {
|
|
@@ -45213,7 +45161,7 @@ var PublishedChannelStore = class {
|
|
|
45213
45161
|
)
|
|
45214
45162
|
};
|
|
45215
45163
|
const tmp = `${this.filePath}.tmp`;
|
|
45216
|
-
await import_promises11.default.mkdir(
|
|
45164
|
+
await import_promises11.default.mkdir(import_node_path43.default.dirname(this.filePath), { recursive: true });
|
|
45217
45165
|
await import_promises11.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
45218
45166
|
await import_promises11.default.rename(tmp, this.filePath);
|
|
45219
45167
|
}
|
|
@@ -45221,7 +45169,7 @@ var PublishedChannelStore = class {
|
|
|
45221
45169
|
|
|
45222
45170
|
// src/extension/bundle-cache.ts
|
|
45223
45171
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
45224
|
-
var
|
|
45172
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
45225
45173
|
var BundleCache = class {
|
|
45226
45174
|
constructor(rootDir) {
|
|
45227
45175
|
this.rootDir = rootDir;
|
|
@@ -45230,14 +45178,14 @@ var BundleCache = class {
|
|
|
45230
45178
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
45231
45179
|
async write(snapshotHash, buffer) {
|
|
45232
45180
|
await import_promises12.default.mkdir(this.rootDir, { recursive: true });
|
|
45233
|
-
const file =
|
|
45181
|
+
const file = import_node_path44.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45234
45182
|
const tmp = `${file}.tmp`;
|
|
45235
45183
|
await import_promises12.default.writeFile(tmp, buffer, { mode: 384 });
|
|
45236
45184
|
await import_promises12.default.rename(tmp, file);
|
|
45237
45185
|
}
|
|
45238
45186
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
45239
45187
|
async read(snapshotHash) {
|
|
45240
|
-
const file =
|
|
45188
|
+
const file = import_node_path44.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45241
45189
|
try {
|
|
45242
45190
|
return await import_promises12.default.readFile(file);
|
|
45243
45191
|
} catch (e) {
|
|
@@ -45247,7 +45195,7 @@ var BundleCache = class {
|
|
|
45247
45195
|
}
|
|
45248
45196
|
/** Idempotent — missing file is not an error. */
|
|
45249
45197
|
async delete(snapshotHash) {
|
|
45250
|
-
const file =
|
|
45198
|
+
const file = import_node_path44.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45251
45199
|
await import_promises12.default.rm(file, { force: true });
|
|
45252
45200
|
}
|
|
45253
45201
|
};
|
|
@@ -45256,7 +45204,7 @@ var BundleCache = class {
|
|
|
45256
45204
|
async function startDaemon(config) {
|
|
45257
45205
|
const logger = createLogger({
|
|
45258
45206
|
level: config.logLevel,
|
|
45259
|
-
file:
|
|
45207
|
+
file: import_node_path45.default.join(config.dataDir, "clawd.log")
|
|
45260
45208
|
});
|
|
45261
45209
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
45262
45210
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -45392,8 +45340,8 @@ async function startDaemon(config) {
|
|
|
45392
45340
|
const agents = new AgentsScanner();
|
|
45393
45341
|
const history = new ClaudeHistoryReader();
|
|
45394
45342
|
let transport = null;
|
|
45395
|
-
const personaStore = new PersonaStore(
|
|
45396
|
-
const usersRoot =
|
|
45343
|
+
const personaStore = new PersonaStore(import_node_path45.default.join(config.dataDir, "personas"));
|
|
45344
|
+
const usersRoot = import_node_path45.default.join(config.dataDir, "users");
|
|
45397
45345
|
const defaultsRoot = findDefaultsRoot();
|
|
45398
45346
|
if (defaultsRoot) {
|
|
45399
45347
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -45413,7 +45361,7 @@ async function startDaemon(config) {
|
|
|
45413
45361
|
getAdapter,
|
|
45414
45362
|
historyReader: history,
|
|
45415
45363
|
dataDir: config.dataDir,
|
|
45416
|
-
personaRoot:
|
|
45364
|
+
personaRoot: import_node_path45.default.join(config.dataDir, "personas"),
|
|
45417
45365
|
usersRoot,
|
|
45418
45366
|
personaStore,
|
|
45419
45367
|
ownerDisplayName,
|
|
@@ -45443,7 +45391,7 @@ async function startDaemon(config) {
|
|
|
45443
45391
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
45444
45392
|
attachmentGroup: {
|
|
45445
45393
|
onFileEdit: (input) => {
|
|
45446
|
-
const absPath =
|
|
45394
|
+
const absPath = import_node_path45.default.isAbsolute(input.relPath) ? input.relPath : import_node_path45.default.join(input.cwd, input.relPath);
|
|
45447
45395
|
let size = 0;
|
|
45448
45396
|
try {
|
|
45449
45397
|
size = import_node_fs33.default.statSync(absPath).size;
|
|
@@ -45632,11 +45580,11 @@ async function startDaemon(config) {
|
|
|
45632
45580
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
45633
45581
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
45634
45582
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
45635
|
-
personaRoot:
|
|
45583
|
+
personaRoot: import_node_path45.default.join(config.dataDir, "personas"),
|
|
45636
45584
|
usersRoot
|
|
45637
45585
|
},
|
|
45638
45586
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
45639
|
-
personaRoot:
|
|
45587
|
+
personaRoot: import_node_path45.default.join(config.dataDir, "personas"),
|
|
45640
45588
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
45641
45589
|
usersRoot,
|
|
45642
45590
|
// capability:list / delete handler 依赖
|
|
@@ -45725,7 +45673,7 @@ async function startDaemon(config) {
|
|
|
45725
45673
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
45726
45674
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
45727
45675
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
45728
|
-
appBuilderPersonaRoot:
|
|
45676
|
+
appBuilderPersonaRoot: import_node_path45.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
45729
45677
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
45730
45678
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
45731
45679
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -45974,8 +45922,8 @@ async function startDaemon(config) {
|
|
|
45974
45922
|
const lines = [
|
|
45975
45923
|
`Tunnel: ${r.url}`,
|
|
45976
45924
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
45977
|
-
`Frpc config: ${
|
|
45978
|
-
`Frpc log: ${
|
|
45925
|
+
`Frpc config: ${import_node_path45.default.join(config.dataDir, "frpc.toml")}`,
|
|
45926
|
+
`Frpc log: ${import_node_path45.default.join(config.dataDir, "frpc.log")}`
|
|
45979
45927
|
];
|
|
45980
45928
|
const width = Math.max(...lines.map((l) => l.length));
|
|
45981
45929
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -45988,7 +45936,7 @@ ${bar}
|
|
|
45988
45936
|
|
|
45989
45937
|
`);
|
|
45990
45938
|
try {
|
|
45991
|
-
const connectPath =
|
|
45939
|
+
const connectPath = import_node_path45.default.join(config.dataDir, "connect.txt");
|
|
45992
45940
|
import_node_fs33.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
45993
45941
|
} catch {
|
|
45994
45942
|
}
|
|
@@ -46060,7 +46008,7 @@ ${bar}
|
|
|
46060
46008
|
};
|
|
46061
46009
|
}
|
|
46062
46010
|
function migrateDropPersonsDir(dataDir) {
|
|
46063
|
-
const dir =
|
|
46011
|
+
const dir = import_node_path45.default.join(dataDir, "persons");
|
|
46064
46012
|
try {
|
|
46065
46013
|
import_node_fs33.default.rmSync(dir, { recursive: true, force: true });
|
|
46066
46014
|
} catch {
|