@clawos-dev/clawd 0.2.33 → 0.2.34-beta.50.1515dc2
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 +257 -183
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -296,8 +296,8 @@ var require_req = __commonJS({
|
|
|
296
296
|
if (req.originalUrl) {
|
|
297
297
|
_req.url = req.originalUrl;
|
|
298
298
|
} else {
|
|
299
|
-
const
|
|
300
|
-
_req.url = typeof
|
|
299
|
+
const path23 = req.path;
|
|
300
|
+
_req.url = typeof path23 === "string" ? path23 : req.url ? req.url.path || req.url : void 0;
|
|
301
301
|
}
|
|
302
302
|
if (req.query) {
|
|
303
303
|
_req.query = req.query;
|
|
@@ -462,14 +462,14 @@ var require_redact = __commonJS({
|
|
|
462
462
|
}
|
|
463
463
|
return obj;
|
|
464
464
|
}
|
|
465
|
-
function parsePath(
|
|
465
|
+
function parsePath(path23) {
|
|
466
466
|
const parts = [];
|
|
467
467
|
let current = "";
|
|
468
468
|
let inBrackets = false;
|
|
469
469
|
let inQuotes = false;
|
|
470
470
|
let quoteChar = "";
|
|
471
|
-
for (let i = 0; i <
|
|
472
|
-
const char =
|
|
471
|
+
for (let i = 0; i < path23.length; i++) {
|
|
472
|
+
const char = path23[i];
|
|
473
473
|
if (!inBrackets && char === ".") {
|
|
474
474
|
if (current) {
|
|
475
475
|
parts.push(current);
|
|
@@ -600,10 +600,10 @@ var require_redact = __commonJS({
|
|
|
600
600
|
return current;
|
|
601
601
|
}
|
|
602
602
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
603
|
-
for (const
|
|
604
|
-
const parts = parsePath(
|
|
603
|
+
for (const path23 of paths) {
|
|
604
|
+
const parts = parsePath(path23);
|
|
605
605
|
if (parts.includes("*")) {
|
|
606
|
-
redactWildcardPath(obj, parts, censor,
|
|
606
|
+
redactWildcardPath(obj, parts, censor, path23, remove);
|
|
607
607
|
} else {
|
|
608
608
|
if (remove) {
|
|
609
609
|
removeKey(obj, parts);
|
|
@@ -688,8 +688,8 @@ var require_redact = __commonJS({
|
|
|
688
688
|
}
|
|
689
689
|
} else {
|
|
690
690
|
if (afterWildcard.includes("*")) {
|
|
691
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
692
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
691
|
+
const wrappedCensor = typeof censor === "function" ? (value, path23) => {
|
|
692
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path23];
|
|
693
693
|
return censor(value, fullPath);
|
|
694
694
|
} : censor;
|
|
695
695
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -724,8 +724,8 @@ var require_redact = __commonJS({
|
|
|
724
724
|
return null;
|
|
725
725
|
}
|
|
726
726
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
727
|
-
for (const
|
|
728
|
-
const parts = parsePath(
|
|
727
|
+
for (const path23 of pathsToClone) {
|
|
728
|
+
const parts = parsePath(path23);
|
|
729
729
|
let current = pathStructure;
|
|
730
730
|
for (let i = 0; i < parts.length; i++) {
|
|
731
731
|
const part = parts[i];
|
|
@@ -777,24 +777,24 @@ var require_redact = __commonJS({
|
|
|
777
777
|
}
|
|
778
778
|
return cloneSelectively(obj, pathStructure);
|
|
779
779
|
}
|
|
780
|
-
function validatePath(
|
|
781
|
-
if (typeof
|
|
780
|
+
function validatePath(path23) {
|
|
781
|
+
if (typeof path23 !== "string") {
|
|
782
782
|
throw new Error("Paths must be (non-empty) strings");
|
|
783
783
|
}
|
|
784
|
-
if (
|
|
784
|
+
if (path23 === "") {
|
|
785
785
|
throw new Error("Invalid redaction path ()");
|
|
786
786
|
}
|
|
787
|
-
if (
|
|
788
|
-
throw new Error(`Invalid redaction path (${
|
|
787
|
+
if (path23.includes("..")) {
|
|
788
|
+
throw new Error(`Invalid redaction path (${path23})`);
|
|
789
789
|
}
|
|
790
|
-
if (
|
|
791
|
-
throw new Error(`Invalid redaction path (${
|
|
790
|
+
if (path23.includes(",")) {
|
|
791
|
+
throw new Error(`Invalid redaction path (${path23})`);
|
|
792
792
|
}
|
|
793
793
|
let bracketCount = 0;
|
|
794
794
|
let inQuotes = false;
|
|
795
795
|
let quoteChar = "";
|
|
796
|
-
for (let i = 0; i <
|
|
797
|
-
const char =
|
|
796
|
+
for (let i = 0; i < path23.length; i++) {
|
|
797
|
+
const char = path23[i];
|
|
798
798
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
799
799
|
if (!inQuotes) {
|
|
800
800
|
inQuotes = true;
|
|
@@ -808,20 +808,20 @@ var require_redact = __commonJS({
|
|
|
808
808
|
} else if (char === "]" && !inQuotes) {
|
|
809
809
|
bracketCount--;
|
|
810
810
|
if (bracketCount < 0) {
|
|
811
|
-
throw new Error(`Invalid redaction path (${
|
|
811
|
+
throw new Error(`Invalid redaction path (${path23})`);
|
|
812
812
|
}
|
|
813
813
|
}
|
|
814
814
|
}
|
|
815
815
|
if (bracketCount !== 0) {
|
|
816
|
-
throw new Error(`Invalid redaction path (${
|
|
816
|
+
throw new Error(`Invalid redaction path (${path23})`);
|
|
817
817
|
}
|
|
818
818
|
}
|
|
819
819
|
function validatePaths(paths) {
|
|
820
820
|
if (!Array.isArray(paths)) {
|
|
821
821
|
throw new TypeError("paths must be an array");
|
|
822
822
|
}
|
|
823
|
-
for (const
|
|
824
|
-
validatePath(
|
|
823
|
+
for (const path23 of paths) {
|
|
824
|
+
validatePath(path23);
|
|
825
825
|
}
|
|
826
826
|
}
|
|
827
827
|
function slowRedact(options = {}) {
|
|
@@ -989,8 +989,8 @@ var require_redaction = __commonJS({
|
|
|
989
989
|
if (shape[k] === null) {
|
|
990
990
|
o[k] = (value) => topCensor(value, [k]);
|
|
991
991
|
} else {
|
|
992
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
993
|
-
return censor(value, [k, ...
|
|
992
|
+
const wrappedCensor = typeof censor === "function" ? (value, path23) => {
|
|
993
|
+
return censor(value, [k, ...path23]);
|
|
994
994
|
} : censor;
|
|
995
995
|
o[k] = Redact({
|
|
996
996
|
paths: shape[k],
|
|
@@ -1211,7 +1211,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1211
1211
|
var fs22 = require("fs");
|
|
1212
1212
|
var EventEmitter = require("events");
|
|
1213
1213
|
var inherits = require("util").inherits;
|
|
1214
|
-
var
|
|
1214
|
+
var path23 = require("path");
|
|
1215
1215
|
var sleep = require_atomic_sleep();
|
|
1216
1216
|
var assert = require("assert");
|
|
1217
1217
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -1265,7 +1265,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1265
1265
|
const mode = sonic.mode;
|
|
1266
1266
|
if (sonic.sync) {
|
|
1267
1267
|
try {
|
|
1268
|
-
if (sonic.mkdir) fs22.mkdirSync(
|
|
1268
|
+
if (sonic.mkdir) fs22.mkdirSync(path23.dirname(file), { recursive: true });
|
|
1269
1269
|
const fd = fs22.openSync(file, flags, mode);
|
|
1270
1270
|
fileOpened(null, fd);
|
|
1271
1271
|
} catch (err) {
|
|
@@ -1273,7 +1273,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1273
1273
|
throw err;
|
|
1274
1274
|
}
|
|
1275
1275
|
} else if (sonic.mkdir) {
|
|
1276
|
-
fs22.mkdir(
|
|
1276
|
+
fs22.mkdir(path23.dirname(file), { recursive: true }, (err) => {
|
|
1277
1277
|
if (err) return fileOpened(err);
|
|
1278
1278
|
fs22.open(file, flags, mode, fileOpened);
|
|
1279
1279
|
});
|
|
@@ -4892,8 +4892,8 @@ var init_parseUtil = __esm({
|
|
|
4892
4892
|
init_errors2();
|
|
4893
4893
|
init_en();
|
|
4894
4894
|
makeIssue = (params) => {
|
|
4895
|
-
const { data, path:
|
|
4896
|
-
const fullPath = [...
|
|
4895
|
+
const { data, path: path23, errorMaps, issueData } = params;
|
|
4896
|
+
const fullPath = [...path23, ...issueData.path || []];
|
|
4897
4897
|
const fullIssue = {
|
|
4898
4898
|
...issueData,
|
|
4899
4899
|
path: fullPath
|
|
@@ -5204,11 +5204,11 @@ var init_types = __esm({
|
|
|
5204
5204
|
init_parseUtil();
|
|
5205
5205
|
init_util();
|
|
5206
5206
|
ParseInputLazyPath = class {
|
|
5207
|
-
constructor(parent, value,
|
|
5207
|
+
constructor(parent, value, path23, key) {
|
|
5208
5208
|
this._cachedPath = [];
|
|
5209
5209
|
this.parent = parent;
|
|
5210
5210
|
this.data = value;
|
|
5211
|
-
this._path =
|
|
5211
|
+
this._path = path23;
|
|
5212
5212
|
this._key = key;
|
|
5213
5213
|
}
|
|
5214
5214
|
get path() {
|
|
@@ -8741,6 +8741,9 @@ var init_schemas = __esm({
|
|
|
8741
8741
|
// 由 session:fork 派生的 session 在 create 时记录源 transcript 的 toolSessionId;
|
|
8742
8742
|
// sidebar 据此挂 fork 图标。非 fork session 该字段缺省
|
|
8743
8743
|
forkedFromToolSessionId: external_exports.string().min(1).optional(),
|
|
8744
|
+
// owner-mode persona session 身份标识;UI 用它在 SessionList 过滤 + jump,
|
|
8745
|
+
// daemon 用它做 idempotent dedupe + spawn 时派生 ctx.personaMode='owner'
|
|
8746
|
+
ownerPersonaId: external_exports.string().min(1).optional(),
|
|
8744
8747
|
createdAt: external_exports.string().min(1),
|
|
8745
8748
|
updatedAt: external_exports.string().min(1)
|
|
8746
8749
|
});
|
|
@@ -8940,7 +8943,8 @@ var init_schemas = __esm({
|
|
|
8940
8943
|
})
|
|
8941
8944
|
]);
|
|
8942
8945
|
SessionCreateArgs = external_exports.object({
|
|
8943
|
-
cwd
|
|
8946
|
+
// 当 ownerPersonaId 存在时 cwd 由 daemon 派生,UI 可不传
|
|
8947
|
+
cwd: external_exports.string().min(1).optional(),
|
|
8944
8948
|
tool: external_exports.string().optional(),
|
|
8945
8949
|
label: external_exports.string().optional(),
|
|
8946
8950
|
model: external_exports.string().optional(),
|
|
@@ -8952,7 +8956,12 @@ var init_schemas = __esm({
|
|
|
8952
8956
|
worktreeRoot: external_exports.string().min(1).optional(),
|
|
8953
8957
|
worktreeBranch: external_exports.string().min(1).optional(),
|
|
8954
8958
|
// session:fork 派生 session 时由 UI 传入,daemon 写到 SessionFile.forkedFromToolSessionId
|
|
8955
|
-
forkedFromToolSessionId: external_exports.string().min(1).optional()
|
|
8959
|
+
forkedFromToolSessionId: external_exports.string().min(1).optional(),
|
|
8960
|
+
// owner-mode persona session:传此字段时 daemon 自行派生 cwd 和启动参数,
|
|
8961
|
+
// 且按 ownerPersonaId 做 idempotent dedupe(每 persona 永远只有一个 owner session)
|
|
8962
|
+
ownerPersonaId: external_exports.string().min(1).optional()
|
|
8963
|
+
}).refine((args) => args.cwd != null || args.ownerPersonaId != null, {
|
|
8964
|
+
message: "cwd \u4E0E ownerPersonaId \u81F3\u5C11\u4F20\u4E00\u4E2A"
|
|
8956
8965
|
});
|
|
8957
8966
|
SessionIdArgs = external_exports.object({ sessionId: external_exports.string().min(1) });
|
|
8958
8967
|
SessionUpdateArgs = external_exports.object({
|
|
@@ -9202,6 +9211,13 @@ var init_frames = __esm({
|
|
|
9202
9211
|
}
|
|
9203
9212
|
});
|
|
9204
9213
|
|
|
9214
|
+
// ../protocol/src/persona-mode.ts
|
|
9215
|
+
var init_persona_mode = __esm({
|
|
9216
|
+
"../protocol/src/persona-mode.ts"() {
|
|
9217
|
+
"use strict";
|
|
9218
|
+
}
|
|
9219
|
+
});
|
|
9220
|
+
|
|
9205
9221
|
// ../protocol/src/runtime.ts
|
|
9206
9222
|
var init_runtime = __esm({
|
|
9207
9223
|
"../protocol/src/runtime.ts"() {
|
|
@@ -9212,6 +9228,7 @@ var init_runtime = __esm({
|
|
|
9212
9228
|
init_schemas();
|
|
9213
9229
|
init_frames();
|
|
9214
9230
|
init_persona_schemas();
|
|
9231
|
+
init_persona_mode();
|
|
9215
9232
|
}
|
|
9216
9233
|
});
|
|
9217
9234
|
|
|
@@ -9788,11 +9805,11 @@ var init_lib = __esm({
|
|
|
9788
9805
|
}
|
|
9789
9806
|
}
|
|
9790
9807
|
},
|
|
9791
|
-
addToPath: function addToPath(
|
|
9792
|
-
var last =
|
|
9808
|
+
addToPath: function addToPath(path23, added, removed, oldPosInc, options) {
|
|
9809
|
+
var last = path23.lastComponent;
|
|
9793
9810
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
9794
9811
|
return {
|
|
9795
|
-
oldPos:
|
|
9812
|
+
oldPos: path23.oldPos + oldPosInc,
|
|
9796
9813
|
lastComponent: {
|
|
9797
9814
|
count: last.count + 1,
|
|
9798
9815
|
added,
|
|
@@ -9802,7 +9819,7 @@ var init_lib = __esm({
|
|
|
9802
9819
|
};
|
|
9803
9820
|
} else {
|
|
9804
9821
|
return {
|
|
9805
|
-
oldPos:
|
|
9822
|
+
oldPos: path23.oldPos + oldPosInc,
|
|
9806
9823
|
lastComponent: {
|
|
9807
9824
|
count: 1,
|
|
9808
9825
|
added,
|
|
@@ -10233,10 +10250,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
10233
10250
|
const memories = raw.map((m) => {
|
|
10234
10251
|
if (!m || typeof m !== "object") return null;
|
|
10235
10252
|
const rec = m;
|
|
10236
|
-
const
|
|
10253
|
+
const path23 = typeof rec.path === "string" ? rec.path : null;
|
|
10237
10254
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
10238
|
-
if (!
|
|
10239
|
-
const entry = { path:
|
|
10255
|
+
if (!path23 || content == null) return null;
|
|
10256
|
+
const entry = { path: path23, content };
|
|
10240
10257
|
if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
|
|
10241
10258
|
return entry;
|
|
10242
10259
|
}).filter((m) => m !== null);
|
|
@@ -10273,7 +10290,7 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
|
10273
10290
|
if (backupFileName === null) return null;
|
|
10274
10291
|
try {
|
|
10275
10292
|
return import_node_fs6.default.readFileSync(
|
|
10276
|
-
|
|
10293
|
+
import_node_path6.default.join(fileHistoryRoot, toolSessionId, backupFileName),
|
|
10277
10294
|
"utf8"
|
|
10278
10295
|
);
|
|
10279
10296
|
} catch {
|
|
@@ -10288,13 +10305,13 @@ function readCurrentContent(filePath) {
|
|
|
10288
10305
|
return null;
|
|
10289
10306
|
}
|
|
10290
10307
|
}
|
|
10291
|
-
var import_node_fs6, import_node_os2,
|
|
10308
|
+
var import_node_fs6, import_node_os2, import_node_path6, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
|
|
10292
10309
|
var init_claude_history = __esm({
|
|
10293
10310
|
"src/tools/claude-history.ts"() {
|
|
10294
10311
|
"use strict";
|
|
10295
10312
|
import_node_fs6 = __toESM(require("fs"), 1);
|
|
10296
10313
|
import_node_os2 = __toESM(require("os"), 1);
|
|
10297
|
-
|
|
10314
|
+
import_node_path6 = __toESM(require("path"), 1);
|
|
10298
10315
|
init_lib();
|
|
10299
10316
|
init_tool_result_extra();
|
|
10300
10317
|
TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
|
|
@@ -10318,9 +10335,9 @@ var init_claude_history = __esm({
|
|
|
10318
10335
|
// 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
|
|
10319
10336
|
fileHistoryRoot;
|
|
10320
10337
|
constructor(opts = {}) {
|
|
10321
|
-
const base = opts.baseDir ??
|
|
10322
|
-
this.projectsRoot =
|
|
10323
|
-
this.fileHistoryRoot =
|
|
10338
|
+
const base = opts.baseDir ?? import_node_path6.default.join(import_node_os2.default.homedir(), ".claude");
|
|
10339
|
+
this.projectsRoot = import_node_path6.default.join(base, "projects");
|
|
10340
|
+
this.fileHistoryRoot = import_node_path6.default.join(base, "file-history");
|
|
10324
10341
|
}
|
|
10325
10342
|
async listProjects() {
|
|
10326
10343
|
let entries;
|
|
@@ -10333,9 +10350,9 @@ var init_claude_history = __esm({
|
|
|
10333
10350
|
const out = [];
|
|
10334
10351
|
for (const ent of entries) {
|
|
10335
10352
|
if (!ent.isDirectory()) continue;
|
|
10336
|
-
const dir =
|
|
10353
|
+
const dir = import_node_path6.default.join(this.projectsRoot, ent.name);
|
|
10337
10354
|
const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
10338
|
-
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(
|
|
10355
|
+
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path6.default.join(dir, f))), 0);
|
|
10339
10356
|
out.push({
|
|
10340
10357
|
projectPath: hashDirToCwd(ent.name),
|
|
10341
10358
|
hashDir: ent.name,
|
|
@@ -10347,7 +10364,7 @@ var init_claude_history = __esm({
|
|
|
10347
10364
|
return out;
|
|
10348
10365
|
}
|
|
10349
10366
|
async listSessions(args) {
|
|
10350
|
-
const dir =
|
|
10367
|
+
const dir = import_node_path6.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
|
|
10351
10368
|
let files;
|
|
10352
10369
|
try {
|
|
10353
10370
|
files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
@@ -10357,7 +10374,7 @@ var init_claude_history = __esm({
|
|
|
10357
10374
|
}
|
|
10358
10375
|
const out = [];
|
|
10359
10376
|
for (const f of files) {
|
|
10360
|
-
const full =
|
|
10377
|
+
const full = import_node_path6.default.join(dir, f);
|
|
10361
10378
|
const toolSessionId = f.slice(0, -".jsonl".length);
|
|
10362
10379
|
const lines = readJsonlLines(full);
|
|
10363
10380
|
let summary = "";
|
|
@@ -10412,7 +10429,7 @@ var init_claude_history = __esm({
|
|
|
10412
10429
|
return out;
|
|
10413
10430
|
}
|
|
10414
10431
|
async read(args) {
|
|
10415
|
-
const file =
|
|
10432
|
+
const file = import_node_path6.default.join(
|
|
10416
10433
|
this.projectsRoot,
|
|
10417
10434
|
cwdToHashDir(args.cwd),
|
|
10418
10435
|
`${args.toolSessionId}.jsonl`
|
|
@@ -10445,7 +10462,7 @@ var init_claude_history = __esm({
|
|
|
10445
10462
|
// 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
|
|
10446
10463
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
10447
10464
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
10448
|
-
const dir =
|
|
10465
|
+
const dir = import_node_path6.default.join(
|
|
10449
10466
|
this.projectsRoot,
|
|
10450
10467
|
cwdToHashDir(cwd),
|
|
10451
10468
|
toolSessionId,
|
|
@@ -10463,7 +10480,7 @@ var init_claude_history = __esm({
|
|
|
10463
10480
|
if (!e.isFile()) continue;
|
|
10464
10481
|
if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
|
|
10465
10482
|
const subagentId = e.name.slice("agent-".length, -".jsonl".length);
|
|
10466
|
-
const filePath =
|
|
10483
|
+
const filePath = import_node_path6.default.join(dir, e.name);
|
|
10467
10484
|
const lines = readJsonlLines(filePath);
|
|
10468
10485
|
let firstText = "";
|
|
10469
10486
|
let messageCount = 0;
|
|
@@ -10480,7 +10497,7 @@ var init_claude_history = __esm({
|
|
|
10480
10497
|
return out;
|
|
10481
10498
|
}
|
|
10482
10499
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
10483
|
-
const file =
|
|
10500
|
+
const file = import_node_path6.default.join(
|
|
10484
10501
|
this.projectsRoot,
|
|
10485
10502
|
cwdToHashDir(cwd),
|
|
10486
10503
|
`${toolSessionId}.jsonl`
|
|
@@ -10515,7 +10532,7 @@ var init_claude_history = __esm({
|
|
|
10515
10532
|
}
|
|
10516
10533
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
10517
10534
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
10518
|
-
const file =
|
|
10535
|
+
const file = import_node_path6.default.join(
|
|
10519
10536
|
this.projectsRoot,
|
|
10520
10537
|
cwdToHashDir(cwd),
|
|
10521
10538
|
toolSessionId,
|
|
@@ -10543,7 +10560,7 @@ var init_claude_history = __esm({
|
|
|
10543
10560
|
* "那一刻每个 tracked 文件对应的 backup 文件名"
|
|
10544
10561
|
*/
|
|
10545
10562
|
readFileHistorySnapshots(args) {
|
|
10546
|
-
const file =
|
|
10563
|
+
const file = import_node_path6.default.join(
|
|
10547
10564
|
this.projectsRoot,
|
|
10548
10565
|
cwdToHashDir(args.cwd),
|
|
10549
10566
|
`${args.toolSessionId}.jsonl`
|
|
@@ -10588,7 +10605,7 @@ var init_claude_history = __esm({
|
|
|
10588
10605
|
for (const [anchorId, target] of snapshots) {
|
|
10589
10606
|
let hasAny = false;
|
|
10590
10607
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
10591
|
-
const absPath =
|
|
10608
|
+
const absPath = import_node_path6.default.isAbsolute(rawPath) ? rawPath : import_node_path6.default.join(args.cwd, rawPath);
|
|
10592
10609
|
const backupContent = readBackupContent(
|
|
10593
10610
|
this.fileHistoryRoot,
|
|
10594
10611
|
args.toolSessionId,
|
|
@@ -10628,7 +10645,7 @@ var init_claude_history = __esm({
|
|
|
10628
10645
|
let totalInsertions = 0;
|
|
10629
10646
|
let totalDeletions = 0;
|
|
10630
10647
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
10631
|
-
const absPath =
|
|
10648
|
+
const absPath = import_node_path6.default.isAbsolute(rawPath) ? rawPath : import_node_path6.default.join(args.cwd, rawPath);
|
|
10632
10649
|
const backupContent = readBackupContent(
|
|
10633
10650
|
this.fileHistoryRoot,
|
|
10634
10651
|
args.toolSessionId,
|
|
@@ -10675,7 +10692,7 @@ var init_claude_history = __esm({
|
|
|
10675
10692
|
};
|
|
10676
10693
|
}
|
|
10677
10694
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
10678
|
-
const file =
|
|
10695
|
+
const file = import_node_path6.default.join(
|
|
10679
10696
|
this.projectsRoot,
|
|
10680
10697
|
cwdToHashDir(cwd),
|
|
10681
10698
|
`${toolSessionId}.jsonl`
|
|
@@ -10699,7 +10716,7 @@ var init_claude_history = __esm({
|
|
|
10699
10716
|
// src/tools/claude.ts
|
|
10700
10717
|
function macOSDesktopCandidates(home) {
|
|
10701
10718
|
return [
|
|
10702
|
-
|
|
10719
|
+
import_node_path7.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
|
|
10703
10720
|
"/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
10704
10721
|
];
|
|
10705
10722
|
}
|
|
@@ -10744,10 +10761,21 @@ function buildSpawnArgs(ctx) {
|
|
|
10744
10761
|
"--verbose"
|
|
10745
10762
|
];
|
|
10746
10763
|
if (ctx.model) args.push("--model", ctx.model);
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10764
|
+
switch (ctx.personaMode) {
|
|
10765
|
+
case "listener":
|
|
10766
|
+
args.push("--setting-sources", "project,local");
|
|
10767
|
+
break;
|
|
10768
|
+
case "owner":
|
|
10769
|
+
args.push("--setting-sources", "user");
|
|
10770
|
+
args.push("--permission-mode", "bypassPermissions");
|
|
10771
|
+
break;
|
|
10772
|
+
case void 0:
|
|
10773
|
+
if (ctx.permissionMode) args.push("--permission-mode", ctx.permissionMode);
|
|
10774
|
+
break;
|
|
10775
|
+
default: {
|
|
10776
|
+
const _exhaustive = ctx.personaMode;
|
|
10777
|
+
throw new Error(`unexpected personaMode: ${String(_exhaustive)}`);
|
|
10778
|
+
}
|
|
10751
10779
|
}
|
|
10752
10780
|
if (ctx.effort) args.push("--effort", ctx.effort);
|
|
10753
10781
|
if (ctx.toolSessionId) args.push("--resume", ctx.toolSessionId);
|
|
@@ -11027,10 +11055,10 @@ function parseAttachment(obj) {
|
|
|
11027
11055
|
const memories = raw.map((m) => {
|
|
11028
11056
|
if (!m || typeof m !== "object") return null;
|
|
11029
11057
|
const rec = m;
|
|
11030
|
-
const
|
|
11058
|
+
const path23 = typeof rec.path === "string" ? rec.path : null;
|
|
11031
11059
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
11032
|
-
if (!
|
|
11033
|
-
const out = { path:
|
|
11060
|
+
if (!path23 || content == null) return null;
|
|
11061
|
+
const out = { path: path23, content };
|
|
11034
11062
|
if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
|
|
11035
11063
|
return out;
|
|
11036
11064
|
}).filter((m) => m !== null);
|
|
@@ -11134,7 +11162,7 @@ function encodeClaudeStdin(text) {
|
|
|
11134
11162
|
};
|
|
11135
11163
|
return JSON.stringify(frame) + "\n";
|
|
11136
11164
|
}
|
|
11137
|
-
var import_node_child_process, import_node_child_process2, import_node_fs7, import_node_os3,
|
|
11165
|
+
var import_node_child_process, import_node_child_process2, import_node_fs7, import_node_os3, import_node_path7, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
|
|
11138
11166
|
var init_claude = __esm({
|
|
11139
11167
|
"src/tools/claude.ts"() {
|
|
11140
11168
|
"use strict";
|
|
@@ -11142,7 +11170,7 @@ var init_claude = __esm({
|
|
|
11142
11170
|
import_node_child_process2 = require("child_process");
|
|
11143
11171
|
import_node_fs7 = __toESM(require("fs"), 1);
|
|
11144
11172
|
import_node_os3 = __toESM(require("os"), 1);
|
|
11145
|
-
|
|
11173
|
+
import_node_path7 = __toESM(require("path"), 1);
|
|
11146
11174
|
init_protocol();
|
|
11147
11175
|
init_claude_history();
|
|
11148
11176
|
init_tool_result_extra();
|
|
@@ -14897,7 +14925,7 @@ var require_websocket_server = __commonJS({
|
|
|
14897
14925
|
// src/run-case/recorder.ts
|
|
14898
14926
|
function startRunCaseRecorder(opts) {
|
|
14899
14927
|
const now = opts.now ?? Date.now;
|
|
14900
|
-
const dir =
|
|
14928
|
+
const dir = import_node_path20.default.dirname(opts.recordPath);
|
|
14901
14929
|
let stream = null;
|
|
14902
14930
|
let closing = false;
|
|
14903
14931
|
let closedSettled = false;
|
|
@@ -14937,12 +14965,12 @@ function startRunCaseRecorder(opts) {
|
|
|
14937
14965
|
};
|
|
14938
14966
|
return { tap, close, closed };
|
|
14939
14967
|
}
|
|
14940
|
-
var import_node_fs20,
|
|
14968
|
+
var import_node_fs20, import_node_path20;
|
|
14941
14969
|
var init_recorder = __esm({
|
|
14942
14970
|
"src/run-case/recorder.ts"() {
|
|
14943
14971
|
"use strict";
|
|
14944
14972
|
import_node_fs20 = __toESM(require("fs"), 1);
|
|
14945
|
-
|
|
14973
|
+
import_node_path20 = __toESM(require("path"), 1);
|
|
14946
14974
|
}
|
|
14947
14975
|
});
|
|
14948
14976
|
|
|
@@ -14985,7 +15013,7 @@ var init_wire = __esm({
|
|
|
14985
15013
|
// src/run-case/controller.ts
|
|
14986
15014
|
async function runController(opts) {
|
|
14987
15015
|
const now = opts.now ?? Date.now;
|
|
14988
|
-
const cwd = opts.cwd ?? (0, import_node_fs21.mkdtempSync)(
|
|
15016
|
+
const cwd = opts.cwd ?? (0, import_node_fs21.mkdtempSync)(import_node_path21.default.join(import_node_os13.default.tmpdir(), "clawd-runcase-"));
|
|
14989
15017
|
const ownsCwd = opts.cwd === void 0;
|
|
14990
15018
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
14991
15019
|
const spawnCtx = { cwd };
|
|
@@ -15152,13 +15180,13 @@ async function runController(opts) {
|
|
|
15152
15180
|
}
|
|
15153
15181
|
return exitCode ?? 0;
|
|
15154
15182
|
}
|
|
15155
|
-
var import_node_fs21, import_node_os13,
|
|
15183
|
+
var import_node_fs21, import_node_os13, import_node_path21;
|
|
15156
15184
|
var init_controller = __esm({
|
|
15157
15185
|
"src/run-case/controller.ts"() {
|
|
15158
15186
|
"use strict";
|
|
15159
15187
|
import_node_fs21 = require("fs");
|
|
15160
15188
|
import_node_os13 = __toESM(require("os"), 1);
|
|
15161
|
-
|
|
15189
|
+
import_node_path21 = __toESM(require("path"), 1);
|
|
15162
15190
|
init_claude();
|
|
15163
15191
|
init_stdout_splitter();
|
|
15164
15192
|
init_permission_stdio();
|
|
@@ -15383,7 +15411,7 @@ Env (advanced):
|
|
|
15383
15411
|
`;
|
|
15384
15412
|
|
|
15385
15413
|
// src/index.ts
|
|
15386
|
-
var
|
|
15414
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
15387
15415
|
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
15388
15416
|
|
|
15389
15417
|
// src/logger.ts
|
|
@@ -15514,6 +15542,7 @@ var SessionStore = class {
|
|
|
15514
15542
|
|
|
15515
15543
|
// src/session/manager.ts
|
|
15516
15544
|
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
15545
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
15517
15546
|
|
|
15518
15547
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
15519
15548
|
var byteToHex = [];
|
|
@@ -15660,7 +15689,7 @@ function buildSpawnContext(state) {
|
|
|
15660
15689
|
};
|
|
15661
15690
|
const meta = state.subSessionMeta;
|
|
15662
15691
|
if (meta?.personaMode) {
|
|
15663
|
-
ctx.personaMode =
|
|
15692
|
+
ctx.personaMode = meta.personaMode;
|
|
15664
15693
|
}
|
|
15665
15694
|
return ctx;
|
|
15666
15695
|
}
|
|
@@ -16657,10 +16686,22 @@ var SessionManager = class {
|
|
|
16657
16686
|
this.capabilitiesCache.set(tool, caps);
|
|
16658
16687
|
return caps;
|
|
16659
16688
|
}
|
|
16689
|
+
// 按优先级解析 SubSessionMeta:subSessionMetaBySid 缓存(内存,首次 create/registerSubSession 写入)
|
|
16690
|
+
// → SessionFile.ownerPersonaId 派生(持久化兜底,daemon 重启后 subSessionMetaBySid 丢失时生效)
|
|
16691
|
+
// → undefined(普通 session)
|
|
16692
|
+
resolveSubSessionMeta(file) {
|
|
16693
|
+
const cached = this.subSessionMetaBySid.get(file.sessionId);
|
|
16694
|
+
if (cached) return cached;
|
|
16695
|
+
if (file.ownerPersonaId) {
|
|
16696
|
+
return { idleKillEnabled: false, personaMode: "owner" };
|
|
16697
|
+
}
|
|
16698
|
+
return void 0;
|
|
16699
|
+
}
|
|
16660
16700
|
// 创建 runner 时包一层 broadcast hook:所有外出 frame 统一走 routeFromRunner,
|
|
16661
16701
|
// 经过 compressFrameForWire 后决定是 push collector 还是走 deps.broadcastFrame
|
|
16662
16702
|
// store:默认 deps.store;persona sub-session 路径下传该 personaId 对应的 SessionStore
|
|
16663
|
-
// subSessionMeta:
|
|
16703
|
+
// subSessionMeta:listener 传 { idleKillEnabled: true, personaMode: 'listener' };
|
|
16704
|
+
// owner 传 { idleKillEnabled: false, personaMode: 'owner' };普通 session 不传
|
|
16664
16705
|
newRunner(file, opts = {}) {
|
|
16665
16706
|
const adapter = this.deps.getAdapter(file.tool ?? "claude");
|
|
16666
16707
|
const store = opts.store ?? this.deps.store;
|
|
@@ -16718,18 +16759,34 @@ var SessionManager = class {
|
|
|
16718
16759
|
}
|
|
16719
16760
|
// ---- 命令方法:均返回 { response, broadcast[] },由 dispatcher 聚合 ----
|
|
16720
16761
|
create(args) {
|
|
16762
|
+
if (args.ownerPersonaId) {
|
|
16763
|
+
const existing = this.deps.store.list().find((s) => s.ownerPersonaId === args.ownerPersonaId);
|
|
16764
|
+
if (existing) {
|
|
16765
|
+
return { response: existing, broadcast: [] };
|
|
16766
|
+
}
|
|
16767
|
+
}
|
|
16768
|
+
let cwd = args.cwd;
|
|
16769
|
+
if (args.ownerPersonaId && !cwd) {
|
|
16770
|
+
if (!this.deps.personaRoot) {
|
|
16771
|
+
throw new Error("personaRoot required to derive cwd from ownerPersonaId");
|
|
16772
|
+
}
|
|
16773
|
+
cwd = import_node_path5.default.join(this.deps.personaRoot, safeFileName(args.ownerPersonaId));
|
|
16774
|
+
}
|
|
16775
|
+
if (!cwd) {
|
|
16776
|
+
throw new ClawdError(ERROR_CODES.INVALID_CWD, "cwd required when ownerPersonaId is absent");
|
|
16777
|
+
}
|
|
16721
16778
|
try {
|
|
16722
|
-
const stat = import_node_fs5.default.statSync(
|
|
16779
|
+
const stat = import_node_fs5.default.statSync(cwd);
|
|
16723
16780
|
if (!stat.isDirectory()) throw new Error("not dir");
|
|
16724
16781
|
} catch {
|
|
16725
|
-
throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${
|
|
16782
|
+
throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${cwd}`);
|
|
16726
16783
|
}
|
|
16727
16784
|
const tool = args.tool ?? "claude";
|
|
16728
16785
|
this.deps.getAdapter(tool);
|
|
16729
16786
|
const iso = nowIso2(this.deps);
|
|
16730
16787
|
const file = {
|
|
16731
16788
|
sessionId: newSessionId(),
|
|
16732
|
-
cwd
|
|
16789
|
+
cwd,
|
|
16733
16790
|
tool,
|
|
16734
16791
|
label: args.label,
|
|
16735
16792
|
model: args.model,
|
|
@@ -16739,10 +16796,17 @@ var SessionManager = class {
|
|
|
16739
16796
|
worktreeRoot: args.worktreeRoot,
|
|
16740
16797
|
worktreeBranch: args.worktreeBranch,
|
|
16741
16798
|
forkedFromToolSessionId: args.forkedFromToolSessionId,
|
|
16799
|
+
ownerPersonaId: args.ownerPersonaId,
|
|
16742
16800
|
createdAt: iso,
|
|
16743
16801
|
updatedAt: iso
|
|
16744
16802
|
};
|
|
16745
16803
|
const written = this.deps.store.write(file);
|
|
16804
|
+
if (args.ownerPersonaId) {
|
|
16805
|
+
this.subSessionMetaBySid.set(written.sessionId, {
|
|
16806
|
+
idleKillEnabled: false,
|
|
16807
|
+
personaMode: "owner"
|
|
16808
|
+
});
|
|
16809
|
+
}
|
|
16746
16810
|
return { response: written, broadcast: [] };
|
|
16747
16811
|
}
|
|
16748
16812
|
pin(args) {
|
|
@@ -16898,7 +16962,8 @@ var SessionManager = class {
|
|
|
16898
16962
|
const existing = this.getFile(args.sessionId);
|
|
16899
16963
|
let runner = this.runners.get(args.sessionId);
|
|
16900
16964
|
if (!runner) {
|
|
16901
|
-
|
|
16965
|
+
const subSessionMeta = this.resolveSubSessionMeta(existing);
|
|
16966
|
+
runner = this.newRunner(existing, { subSessionMeta });
|
|
16902
16967
|
this.runners.set(args.sessionId, runner);
|
|
16903
16968
|
}
|
|
16904
16969
|
const { broadcast } = this.withCollector(() => {
|
|
@@ -16992,7 +17057,8 @@ var SessionManager = class {
|
|
|
16992
17057
|
const file = this.getFile(args.sessionId);
|
|
16993
17058
|
let runner = this.runners.get(args.sessionId);
|
|
16994
17059
|
if (!runner) {
|
|
16995
|
-
|
|
17060
|
+
const subSessionMeta = this.resolveSubSessionMeta(file);
|
|
17061
|
+
runner = this.newRunner(file, { subSessionMeta });
|
|
16996
17062
|
this.runners.set(args.sessionId, runner);
|
|
16997
17063
|
}
|
|
16998
17064
|
if (!runner.getState().procAlive) {
|
|
@@ -17150,7 +17216,7 @@ var SessionManager = class {
|
|
|
17150
17216
|
ensureSession(file) {
|
|
17151
17217
|
let r = this.runners.get(file.sessionId);
|
|
17152
17218
|
if (r) return r;
|
|
17153
|
-
const subSessionMeta = this.
|
|
17219
|
+
const subSessionMeta = this.resolveSubSessionMeta(file);
|
|
17154
17220
|
r = this.newRunner(file, { subSessionMeta });
|
|
17155
17221
|
this.runners.set(file.sessionId, r);
|
|
17156
17222
|
return r;
|
|
@@ -17326,7 +17392,7 @@ var SessionManager = class {
|
|
|
17326
17392
|
const existing = this.runners.get(file.sessionId);
|
|
17327
17393
|
if (existing) return existing;
|
|
17328
17394
|
const store = this.storeFor(agentId);
|
|
17329
|
-
const subSessionMeta = this.
|
|
17395
|
+
const subSessionMeta = this.resolveSubSessionMeta(file);
|
|
17330
17396
|
const runner = this.newRunner(file, { store, subSessionMeta });
|
|
17331
17397
|
this.runners.set(file.sessionId, runner);
|
|
17332
17398
|
return runner;
|
|
@@ -17348,7 +17414,7 @@ var SessionManager = class {
|
|
|
17348
17414
|
}
|
|
17349
17415
|
let runner = this.runners.get(args.sessionId);
|
|
17350
17416
|
if (!runner) {
|
|
17351
|
-
const subSessionMeta = this.
|
|
17417
|
+
const subSessionMeta = this.resolveSubSessionMeta(file);
|
|
17352
17418
|
runner = this.newRunner(file, { store, subSessionMeta });
|
|
17353
17419
|
this.runners.set(args.sessionId, runner);
|
|
17354
17420
|
}
|
|
@@ -17420,7 +17486,7 @@ var SessionManager = class {
|
|
|
17420
17486
|
|
|
17421
17487
|
// src/persona/store.ts
|
|
17422
17488
|
var fs6 = __toESM(require("fs"), 1);
|
|
17423
|
-
var
|
|
17489
|
+
var path6 = __toESM(require("path"), 1);
|
|
17424
17490
|
init_protocol();
|
|
17425
17491
|
var DEFAULT_SETTINGS = {
|
|
17426
17492
|
permissions: {
|
|
@@ -17449,21 +17515,21 @@ var PersonaStore = class {
|
|
|
17449
17515
|
}
|
|
17450
17516
|
root;
|
|
17451
17517
|
personaDir(personaId) {
|
|
17452
|
-
return
|
|
17518
|
+
return path6.join(this.root, safeFileName(personaId));
|
|
17453
17519
|
}
|
|
17454
17520
|
metaPath(personaId) {
|
|
17455
|
-
return
|
|
17521
|
+
return path6.join(this.personaDir(personaId), ".clawd", "persona.json");
|
|
17456
17522
|
}
|
|
17457
17523
|
claudeMdPath(personaId) {
|
|
17458
|
-
return
|
|
17524
|
+
return path6.join(this.personaDir(personaId), "CLAUDE.md");
|
|
17459
17525
|
}
|
|
17460
17526
|
settingsPath(personaId) {
|
|
17461
|
-
return
|
|
17527
|
+
return path6.join(this.personaDir(personaId), ".claude", "settings.json");
|
|
17462
17528
|
}
|
|
17463
17529
|
write(persona, personality) {
|
|
17464
17530
|
const dir = this.personaDir(persona.personaId);
|
|
17465
|
-
fs6.mkdirSync(
|
|
17466
|
-
fs6.mkdirSync(
|
|
17531
|
+
fs6.mkdirSync(path6.join(dir, ".claude"), { recursive: true });
|
|
17532
|
+
fs6.mkdirSync(path6.join(dir, ".clawd"), { recursive: true });
|
|
17467
17533
|
this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
|
|
17468
17534
|
this.atomicWrite(this.settingsPath(persona.personaId), JSON.stringify(DEFAULT_SETTINGS, null, 2));
|
|
17469
17535
|
this.atomicWrite(this.metaPath(persona.personaId), JSON.stringify(persona, null, 2));
|
|
@@ -17488,7 +17554,7 @@ var PersonaStore = class {
|
|
|
17488
17554
|
list() {
|
|
17489
17555
|
if (!fs6.existsSync(this.root)) return [];
|
|
17490
17556
|
return fs6.readdirSync(this.root).filter((name) => {
|
|
17491
|
-
return fs6.existsSync(
|
|
17557
|
+
return fs6.existsSync(path6.join(this.root, name, ".clawd", "persona.json"));
|
|
17492
17558
|
});
|
|
17493
17559
|
}
|
|
17494
17560
|
remove(personaId) {
|
|
@@ -17653,7 +17719,7 @@ var PersonaManager = class {
|
|
|
17653
17719
|
tool: "claude",
|
|
17654
17720
|
label: subLabel,
|
|
17655
17721
|
model: persona.model,
|
|
17656
|
-
subSessionMeta: { idleKillEnabled: true, personaMode:
|
|
17722
|
+
subSessionMeta: { idleKillEnabled: true, personaMode: "listener" }
|
|
17657
17723
|
});
|
|
17658
17724
|
return { sessionFile, isNew: true };
|
|
17659
17725
|
}
|
|
@@ -17689,14 +17755,14 @@ init_claude_history();
|
|
|
17689
17755
|
// src/workspace/browser.ts
|
|
17690
17756
|
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
17691
17757
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
17692
|
-
var
|
|
17758
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
17693
17759
|
init_protocol();
|
|
17694
17760
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
17695
17761
|
function resolveInsideCwd(cwd, subpath) {
|
|
17696
|
-
const absCwd =
|
|
17697
|
-
const joined =
|
|
17698
|
-
const rel =
|
|
17699
|
-
if (rel.startsWith("..") ||
|
|
17762
|
+
const absCwd = import_node_path8.default.resolve(cwd);
|
|
17763
|
+
const joined = import_node_path8.default.resolve(absCwd, subpath ?? ".");
|
|
17764
|
+
const rel = import_node_path8.default.relative(absCwd, joined);
|
|
17765
|
+
if (rel.startsWith("..") || import_node_path8.default.isAbsolute(rel)) {
|
|
17700
17766
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
17701
17767
|
}
|
|
17702
17768
|
return joined;
|
|
@@ -17727,7 +17793,7 @@ var WorkspaceBrowser = class {
|
|
|
17727
17793
|
mtime: ""
|
|
17728
17794
|
};
|
|
17729
17795
|
try {
|
|
17730
|
-
const st = import_node_fs8.default.statSync(
|
|
17796
|
+
const st = import_node_fs8.default.statSync(import_node_path8.default.join(full, d.name));
|
|
17731
17797
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
17732
17798
|
if (d.isFile()) entry.size = st.size;
|
|
17733
17799
|
} catch {
|
|
@@ -17774,7 +17840,7 @@ var WorkspaceBrowser = class {
|
|
|
17774
17840
|
// src/skills/scanner.ts
|
|
17775
17841
|
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
17776
17842
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
17777
|
-
var
|
|
17843
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
17778
17844
|
|
|
17779
17845
|
// src/skills/frontmatter.ts
|
|
17780
17846
|
var STRIP_QUOTES = /^["']|["']$/g;
|
|
@@ -17896,14 +17962,14 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
|
17896
17962
|
return;
|
|
17897
17963
|
}
|
|
17898
17964
|
for (const ent of entries) {
|
|
17899
|
-
const entryPath =
|
|
17965
|
+
const entryPath = import_node_path9.default.join(dir, ent.name);
|
|
17900
17966
|
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
17901
17967
|
let content;
|
|
17902
17968
|
try {
|
|
17903
|
-
content = import_node_fs9.default.readFileSync(
|
|
17969
|
+
content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "SKILL.md"), "utf8");
|
|
17904
17970
|
} catch {
|
|
17905
17971
|
try {
|
|
17906
|
-
content = import_node_fs9.default.readFileSync(
|
|
17972
|
+
content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "skill.md"), "utf8");
|
|
17907
17973
|
} catch {
|
|
17908
17974
|
continue;
|
|
17909
17975
|
}
|
|
@@ -17926,7 +17992,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
17926
17992
|
return;
|
|
17927
17993
|
}
|
|
17928
17994
|
for (const ent of entries) {
|
|
17929
|
-
const entryPath =
|
|
17995
|
+
const entryPath = import_node_path9.default.join(dir, ent.name);
|
|
17930
17996
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
17931
17997
|
const ns = ent.name;
|
|
17932
17998
|
let subEntries;
|
|
@@ -17937,7 +18003,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
17937
18003
|
}
|
|
17938
18004
|
for (const se of subEntries) {
|
|
17939
18005
|
if (!se.name.endsWith(".md")) continue;
|
|
17940
|
-
const sePath =
|
|
18006
|
+
const sePath = import_node_path9.default.join(entryPath, se.name);
|
|
17941
18007
|
let content;
|
|
17942
18008
|
try {
|
|
17943
18009
|
content = import_node_fs9.default.readFileSync(sePath, "utf8");
|
|
@@ -17973,7 +18039,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
17973
18039
|
}
|
|
17974
18040
|
}
|
|
17975
18041
|
function readInstalledPlugins(home) {
|
|
17976
|
-
const file =
|
|
18042
|
+
const file = import_node_path9.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
17977
18043
|
let raw;
|
|
17978
18044
|
try {
|
|
17979
18045
|
raw = import_node_fs9.default.readFileSync(file, "utf8");
|
|
@@ -18024,14 +18090,14 @@ var SkillsScanner = class {
|
|
|
18024
18090
|
});
|
|
18025
18091
|
}
|
|
18026
18092
|
const fsBlock = [];
|
|
18027
|
-
scanSkillDir(
|
|
18028
|
-
scanCommandDir(
|
|
18029
|
-
scanSkillDir(
|
|
18030
|
-
scanCommandDir(
|
|
18093
|
+
scanSkillDir(import_node_path9.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
|
|
18094
|
+
scanCommandDir(import_node_path9.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
|
|
18095
|
+
scanSkillDir(import_node_path9.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
|
|
18096
|
+
scanCommandDir(import_node_path9.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
|
|
18031
18097
|
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
18032
18098
|
for (const { name, root } of plugins) {
|
|
18033
|
-
scanSkillDir(
|
|
18034
|
-
scanCommandDir(
|
|
18099
|
+
scanSkillDir(import_node_path9.default.join(root, "skills"), "plugin", seen, fsBlock, name);
|
|
18100
|
+
scanCommandDir(import_node_path9.default.join(root, "commands"), "plugin", seen, fsBlock, name);
|
|
18035
18101
|
}
|
|
18036
18102
|
fsBlock.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
18037
18103
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -18041,7 +18107,7 @@ var SkillsScanner = class {
|
|
|
18041
18107
|
// src/skills/agents-scanner.ts
|
|
18042
18108
|
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
18043
18109
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
18044
|
-
var
|
|
18110
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
18045
18111
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
18046
18112
|
function isDirLikeSync2(p) {
|
|
18047
18113
|
try {
|
|
@@ -18079,10 +18145,10 @@ function scanAgentsDir(dir, source, seen, out) {
|
|
|
18079
18145
|
}
|
|
18080
18146
|
for (const ent of entries) {
|
|
18081
18147
|
if (!ent.name.endsWith(".md")) continue;
|
|
18082
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
18148
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path10.default.join(dir, ent.name)))) {
|
|
18083
18149
|
continue;
|
|
18084
18150
|
}
|
|
18085
|
-
const filePath =
|
|
18151
|
+
const filePath = import_node_path10.default.join(dir, ent.name);
|
|
18086
18152
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
18087
18153
|
if (seen.has(baseName)) continue;
|
|
18088
18154
|
seen.add(baseName);
|
|
@@ -18105,7 +18171,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
18105
18171
|
return;
|
|
18106
18172
|
}
|
|
18107
18173
|
for (const ent of entries) {
|
|
18108
|
-
const childPath =
|
|
18174
|
+
const childPath = import_node_path10.default.join(dir, ent.name);
|
|
18109
18175
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
18110
18176
|
walk(childPath, [...namespaces, ent.name]);
|
|
18111
18177
|
continue;
|
|
@@ -18130,9 +18196,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
18130
18196
|
walk(root, []);
|
|
18131
18197
|
}
|
|
18132
18198
|
function readInstalledPlugins2(home) {
|
|
18133
|
-
const pluginsDir =
|
|
18134
|
-
const v2 =
|
|
18135
|
-
const v1 =
|
|
18199
|
+
const pluginsDir = import_node_path10.default.join(home, ".claude", "plugins");
|
|
18200
|
+
const v2 = import_node_path10.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
18201
|
+
const v1 = import_node_path10.default.join(pluginsDir, "installed_plugins.json");
|
|
18136
18202
|
let raw = null;
|
|
18137
18203
|
for (const candidate of [v2, v1]) {
|
|
18138
18204
|
try {
|
|
@@ -18161,19 +18227,19 @@ function readInstalledPlugins2(home) {
|
|
|
18161
18227
|
return out;
|
|
18162
18228
|
}
|
|
18163
18229
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
18164
|
-
let cur =
|
|
18165
|
-
const fsRoot =
|
|
18230
|
+
let cur = import_node_path10.default.resolve(startCwd);
|
|
18231
|
+
const fsRoot = import_node_path10.default.parse(cur).root;
|
|
18166
18232
|
while (true) {
|
|
18167
|
-
scanAgentsDir(
|
|
18233
|
+
scanAgentsDir(import_node_path10.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
18168
18234
|
let hasGit = false;
|
|
18169
18235
|
try {
|
|
18170
|
-
hasGit = import_node_fs10.default.existsSync(
|
|
18236
|
+
hasGit = import_node_fs10.default.existsSync(import_node_path10.default.join(cur, ".git"));
|
|
18171
18237
|
} catch {
|
|
18172
18238
|
}
|
|
18173
18239
|
if (hasGit) return;
|
|
18174
18240
|
if (cur === home) return;
|
|
18175
18241
|
if (cur === fsRoot) return;
|
|
18176
|
-
const parent =
|
|
18242
|
+
const parent = import_node_path10.default.dirname(cur);
|
|
18177
18243
|
if (parent === cur) return;
|
|
18178
18244
|
cur = parent;
|
|
18179
18245
|
}
|
|
@@ -18208,7 +18274,7 @@ var AgentsScanner = class {
|
|
|
18208
18274
|
}
|
|
18209
18275
|
const fsBlock = [];
|
|
18210
18276
|
scanAgentsDir(
|
|
18211
|
-
|
|
18277
|
+
import_node_path10.default.join(this.home, ".claude", "agents"),
|
|
18212
18278
|
"global",
|
|
18213
18279
|
seen,
|
|
18214
18280
|
fsBlock
|
|
@@ -18222,7 +18288,7 @@ var AgentsScanner = class {
|
|
|
18222
18288
|
...this.extraPluginRoots
|
|
18223
18289
|
];
|
|
18224
18290
|
for (const { name, root } of plugins) {
|
|
18225
|
-
const agentsRoot =
|
|
18291
|
+
const agentsRoot = import_node_path10.default.join(root, "agents");
|
|
18226
18292
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
18227
18293
|
}
|
|
18228
18294
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -18232,7 +18298,7 @@ var AgentsScanner = class {
|
|
|
18232
18298
|
// src/observer/session-observer.ts
|
|
18233
18299
|
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
18234
18300
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
18235
|
-
var
|
|
18301
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
18236
18302
|
init_claude_history();
|
|
18237
18303
|
var SessionObserver = class {
|
|
18238
18304
|
constructor(opts) {
|
|
@@ -18244,7 +18310,7 @@ var SessionObserver = class {
|
|
|
18244
18310
|
watches = /* @__PURE__ */ new Map();
|
|
18245
18311
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
18246
18312
|
if (override) return override;
|
|
18247
|
-
return
|
|
18313
|
+
return import_node_path11.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
18248
18314
|
}
|
|
18249
18315
|
start(args) {
|
|
18250
18316
|
this.stop(args.sessionId);
|
|
@@ -18264,10 +18330,10 @@ var SessionObserver = class {
|
|
|
18264
18330
|
adapter: args.adapter
|
|
18265
18331
|
};
|
|
18266
18332
|
try {
|
|
18267
|
-
import_node_fs11.default.mkdirSync(
|
|
18333
|
+
import_node_fs11.default.mkdirSync(import_node_path11.default.dirname(filePath), { recursive: true });
|
|
18268
18334
|
} catch {
|
|
18269
18335
|
}
|
|
18270
|
-
w.watcher = import_node_fs11.default.watch(
|
|
18336
|
+
w.watcher = import_node_fs11.default.watch(import_node_path11.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
18271
18337
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
18272
18338
|
this.poll(w);
|
|
18273
18339
|
});
|
|
@@ -18983,9 +19049,9 @@ function isLocalhost(addr) {
|
|
|
18983
19049
|
|
|
18984
19050
|
// src/discovery/state-file.ts
|
|
18985
19051
|
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
18986
|
-
var
|
|
19052
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
18987
19053
|
function defaultStateFilePath(dataDir) {
|
|
18988
|
-
return
|
|
19054
|
+
return import_node_path12.default.join(dataDir, "state.json");
|
|
18989
19055
|
}
|
|
18990
19056
|
function isPidAlive(pid) {
|
|
18991
19057
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -19021,7 +19087,7 @@ var StateFileManager = class {
|
|
|
19021
19087
|
return { status: "stale", existing };
|
|
19022
19088
|
}
|
|
19023
19089
|
write(state) {
|
|
19024
|
-
import_node_fs12.default.mkdirSync(
|
|
19090
|
+
import_node_fs12.default.mkdirSync(import_node_path12.default.dirname(this.file), { recursive: true });
|
|
19025
19091
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
19026
19092
|
import_node_fs12.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
19027
19093
|
import_node_fs12.default.renameSync(tmp, this.file);
|
|
@@ -19042,13 +19108,13 @@ var StateFileManager = class {
|
|
|
19042
19108
|
|
|
19043
19109
|
// src/tunnel/tunnel-manager.ts
|
|
19044
19110
|
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
19045
|
-
var
|
|
19111
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
19046
19112
|
var import_node_crypto4 = __toESM(require("crypto"), 1);
|
|
19047
19113
|
var import_node_child_process4 = require("child_process");
|
|
19048
19114
|
|
|
19049
19115
|
// src/tunnel/tunnel-store.ts
|
|
19050
19116
|
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
19051
|
-
var
|
|
19117
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
19052
19118
|
var TunnelStore = class {
|
|
19053
19119
|
constructor(filePath) {
|
|
19054
19120
|
this.filePath = filePath;
|
|
@@ -19067,7 +19133,7 @@ var TunnelStore = class {
|
|
|
19067
19133
|
}
|
|
19068
19134
|
}
|
|
19069
19135
|
async set(v) {
|
|
19070
|
-
const dir =
|
|
19136
|
+
const dir = import_node_path13.default.dirname(this.filePath);
|
|
19071
19137
|
await import_node_fs13.default.promises.mkdir(dir, { recursive: true });
|
|
19072
19138
|
const data = JSON.stringify(v, null, 2);
|
|
19073
19139
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
@@ -19179,7 +19245,7 @@ function escape(v) {
|
|
|
19179
19245
|
// src/tunnel/frpc-binary.ts
|
|
19180
19246
|
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
19181
19247
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
19182
|
-
var
|
|
19248
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
19183
19249
|
var import_node_child_process3 = require("child_process");
|
|
19184
19250
|
var import_node_stream = require("stream");
|
|
19185
19251
|
var import_promises = require("stream/promises");
|
|
@@ -19218,13 +19284,13 @@ async function ensureFrpcBinary(opts) {
|
|
|
19218
19284
|
}
|
|
19219
19285
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
19220
19286
|
const platform = opts.platform ?? detectPlatform();
|
|
19221
|
-
const binDir =
|
|
19287
|
+
const binDir = import_node_path14.default.join(opts.dataDir, "bin");
|
|
19222
19288
|
import_node_fs14.default.mkdirSync(binDir, { recursive: true });
|
|
19223
19289
|
cleanupStaleArtifacts(binDir);
|
|
19224
|
-
const stableBin =
|
|
19290
|
+
const stableBin = import_node_path14.default.join(binDir, "frpc");
|
|
19225
19291
|
if (import_node_fs14.default.existsSync(stableBin)) return stableBin;
|
|
19226
19292
|
const partialBin = `${stableBin}.partial`;
|
|
19227
|
-
const tarballPath =
|
|
19293
|
+
const tarballPath = import_node_path14.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
19228
19294
|
try {
|
|
19229
19295
|
const url = frpcDownloadUrl(version2, platform);
|
|
19230
19296
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -19250,7 +19316,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
19250
19316
|
}
|
|
19251
19317
|
for (const name of entries) {
|
|
19252
19318
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
19253
|
-
const full =
|
|
19319
|
+
const full = import_node_path14.default.join(binDir, name);
|
|
19254
19320
|
try {
|
|
19255
19321
|
import_node_fs14.default.rmSync(full, { recursive: true, force: true });
|
|
19256
19322
|
} catch {
|
|
@@ -19276,7 +19342,7 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
19276
19342
|
await (0, import_promises.pipeline)(nodeStream, out);
|
|
19277
19343
|
}
|
|
19278
19344
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
19279
|
-
const work =
|
|
19345
|
+
const work = import_node_path14.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
19280
19346
|
import_node_fs14.default.mkdirSync(work, { recursive: true });
|
|
19281
19347
|
try {
|
|
19282
19348
|
await new Promise((resolve, reject) => {
|
|
@@ -19285,7 +19351,7 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
19285
19351
|
proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
|
|
19286
19352
|
});
|
|
19287
19353
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
19288
|
-
const src =
|
|
19354
|
+
const src = import_node_path14.default.join(work, dirName, "frpc");
|
|
19289
19355
|
if (!import_node_fs14.default.existsSync(src)) {
|
|
19290
19356
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
19291
19357
|
}
|
|
@@ -19300,7 +19366,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
19300
19366
|
var TunnelManager = class {
|
|
19301
19367
|
constructor(deps) {
|
|
19302
19368
|
this.deps = deps;
|
|
19303
|
-
this.store = deps.store ?? new TunnelStore(
|
|
19369
|
+
this.store = deps.store ?? new TunnelStore(import_node_path15.default.join(deps.dataDir, "tunnel.json"));
|
|
19304
19370
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
19305
19371
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
19306
19372
|
}
|
|
@@ -19417,7 +19483,7 @@ var TunnelManager = class {
|
|
|
19417
19483
|
dataDir: this.deps.dataDir,
|
|
19418
19484
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
19419
19485
|
});
|
|
19420
|
-
const tomlPath =
|
|
19486
|
+
const tomlPath = import_node_path15.default.join(this.deps.dataDir, "frpc.toml");
|
|
19421
19487
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto4.default.randomBytes(3).toString("hex")}`;
|
|
19422
19488
|
const toml = buildFrpcToml({
|
|
19423
19489
|
serverAddr: t.frpsHost,
|
|
@@ -19432,7 +19498,7 @@ var TunnelManager = class {
|
|
|
19432
19498
|
const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
|
|
19433
19499
|
stdio: ["ignore", "pipe", "pipe"]
|
|
19434
19500
|
});
|
|
19435
|
-
const logFilePath =
|
|
19501
|
+
const logFilePath = import_node_path15.default.join(this.deps.dataDir, "frpc.log");
|
|
19436
19502
|
const logStream = import_node_fs15.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
19437
19503
|
logStream.on("error", () => {
|
|
19438
19504
|
});
|
|
@@ -19526,11 +19592,11 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
19526
19592
|
|
|
19527
19593
|
// src/auth-store.ts
|
|
19528
19594
|
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
19529
|
-
var
|
|
19595
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
19530
19596
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
19531
19597
|
var AUTH_FILE_NAME = "auth.json";
|
|
19532
19598
|
function authFilePath(dataDir) {
|
|
19533
|
-
return
|
|
19599
|
+
return import_node_path16.default.join(dataDir, AUTH_FILE_NAME);
|
|
19534
19600
|
}
|
|
19535
19601
|
function loadOrCreateAuthToken(opts) {
|
|
19536
19602
|
const file = authFilePath(opts.dataDir);
|
|
@@ -19562,7 +19628,7 @@ function readAuthFile(file) {
|
|
|
19562
19628
|
}
|
|
19563
19629
|
}
|
|
19564
19630
|
function writeAuthFile(file, content) {
|
|
19565
|
-
import_node_fs16.default.mkdirSync(
|
|
19631
|
+
import_node_fs16.default.mkdirSync(import_node_path16.default.dirname(file), { recursive: true });
|
|
19566
19632
|
import_node_fs16.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
19567
19633
|
try {
|
|
19568
19634
|
import_node_fs16.default.chmodSync(file, 384);
|
|
@@ -19579,7 +19645,7 @@ init_protocol();
|
|
|
19579
19645
|
// src/session/fork.ts
|
|
19580
19646
|
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
19581
19647
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
19582
|
-
var
|
|
19648
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
19583
19649
|
init_claude_history();
|
|
19584
19650
|
function readJsonlEntries(file) {
|
|
19585
19651
|
const raw = import_node_fs17.default.readFileSync(file, "utf8");
|
|
@@ -19595,9 +19661,9 @@ function readJsonlEntries(file) {
|
|
|
19595
19661
|
return out;
|
|
19596
19662
|
}
|
|
19597
19663
|
function forkSession(input) {
|
|
19598
|
-
const baseDir = input.baseDir ??
|
|
19599
|
-
const projectDir =
|
|
19600
|
-
const sourceFile =
|
|
19664
|
+
const baseDir = input.baseDir ?? import_node_path17.default.join(import_node_os10.default.homedir(), ".claude");
|
|
19665
|
+
const projectDir = import_node_path17.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
19666
|
+
const sourceFile = import_node_path17.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
19601
19667
|
if (!import_node_fs17.default.existsSync(sourceFile)) {
|
|
19602
19668
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
19603
19669
|
}
|
|
@@ -19628,7 +19694,7 @@ function forkSession(input) {
|
|
|
19628
19694
|
}
|
|
19629
19695
|
forkedLines.push(JSON.stringify(forked));
|
|
19630
19696
|
}
|
|
19631
|
-
const forkedFilePath =
|
|
19697
|
+
const forkedFilePath = import_node_path17.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
19632
19698
|
import_node_fs17.default.mkdirSync(projectDir, { recursive: true });
|
|
19633
19699
|
import_node_fs17.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
19634
19700
|
return { forkedToolSessionId, forkedFilePath };
|
|
@@ -19639,6 +19705,12 @@ function buildSessionHandlers(deps) {
|
|
|
19639
19705
|
const { manager, observer, getAdapter: getAdapter2 } = deps;
|
|
19640
19706
|
const create = async (frame) => {
|
|
19641
19707
|
const args = SessionCreateArgs.parse(frame);
|
|
19708
|
+
if (args.ownerPersonaId) {
|
|
19709
|
+
const persona = deps.personaRegistry.get(args.ownerPersonaId);
|
|
19710
|
+
if (!persona) {
|
|
19711
|
+
throw new Error(`persona not found: ${args.ownerPersonaId}`);
|
|
19712
|
+
}
|
|
19713
|
+
}
|
|
19642
19714
|
const { response, broadcast } = manager.create(args);
|
|
19643
19715
|
return { response: { type: "session:info", ...response }, broadcast };
|
|
19644
19716
|
};
|
|
@@ -19908,7 +19980,7 @@ init_protocol();
|
|
|
19908
19980
|
var import_node_child_process5 = require("child_process");
|
|
19909
19981
|
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
19910
19982
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
19911
|
-
var
|
|
19983
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
19912
19984
|
var import_node_util = require("util");
|
|
19913
19985
|
var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
|
|
19914
19986
|
function formatChildProcessError(err) {
|
|
@@ -19923,7 +19995,7 @@ function formatChildProcessError(err) {
|
|
|
19923
19995
|
return e.message ?? "unknown error";
|
|
19924
19996
|
}
|
|
19925
19997
|
function normalizePath(p) {
|
|
19926
|
-
const resolved =
|
|
19998
|
+
const resolved = import_node_path18.default.resolve(p);
|
|
19927
19999
|
try {
|
|
19928
20000
|
return import_node_fs18.default.realpathSync(resolved);
|
|
19929
20001
|
} catch {
|
|
@@ -20026,13 +20098,13 @@ function flattenToDirName(branch) {
|
|
|
20026
20098
|
}
|
|
20027
20099
|
function encodeClaudeProjectDir(absPath) {
|
|
20028
20100
|
if (!absPath || typeof absPath !== "string") return "";
|
|
20029
|
-
let canonical =
|
|
20101
|
+
let canonical = import_node_path18.default.resolve(absPath);
|
|
20030
20102
|
try {
|
|
20031
20103
|
canonical = import_node_fs18.default.realpathSync(canonical);
|
|
20032
20104
|
} catch {
|
|
20033
20105
|
try {
|
|
20034
|
-
const parent = import_node_fs18.default.realpathSync(
|
|
20035
|
-
canonical =
|
|
20106
|
+
const parent = import_node_fs18.default.realpathSync(import_node_path18.default.dirname(canonical));
|
|
20107
|
+
canonical = import_node_path18.default.join(parent, import_node_path18.default.basename(canonical));
|
|
20036
20108
|
} catch {
|
|
20037
20109
|
}
|
|
20038
20110
|
}
|
|
@@ -20056,17 +20128,19 @@ async function createWorktree(input) {
|
|
|
20056
20128
|
if (!isGitRoot) {
|
|
20057
20129
|
throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
|
|
20058
20130
|
}
|
|
20059
|
-
const parent =
|
|
20060
|
-
if (parent === "/" || parent ===
|
|
20131
|
+
const parent = import_node_path18.default.dirname(import_node_path18.default.resolve(cwd));
|
|
20132
|
+
if (parent === "/" || parent === import_node_path18.default.resolve(cwd)) {
|
|
20061
20133
|
throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
|
|
20062
20134
|
}
|
|
20063
|
-
const worktreeRoot =
|
|
20135
|
+
const worktreeRoot = import_node_path18.default.join(parent, dirName);
|
|
20064
20136
|
try {
|
|
20065
|
-
await pexec("git", ["-C", cwd, "
|
|
20066
|
-
timeout:
|
|
20137
|
+
await pexec("git", ["-C", cwd, "fetch", "origin", baseBranch, "--no-tags"], {
|
|
20138
|
+
timeout: 3e4
|
|
20067
20139
|
});
|
|
20068
|
-
} catch {
|
|
20069
|
-
throw new Error(
|
|
20140
|
+
} catch (err) {
|
|
20141
|
+
throw new Error(
|
|
20142
|
+
`\u57FA\u51C6\u5206\u652F ${baseBranch} \u4E0D\u5B58\u5728\u6216 fetch \u8FDC\u7AEF\u5931\u8D25\uFF1A${formatChildProcessError(err)}`
|
|
20143
|
+
);
|
|
20070
20144
|
}
|
|
20071
20145
|
try {
|
|
20072
20146
|
await pexec("git", ["-C", cwd, "rev-parse", "--verify", `refs/heads/${branch}`], {
|
|
@@ -20083,7 +20157,7 @@ async function createWorktree(input) {
|
|
|
20083
20157
|
try {
|
|
20084
20158
|
await pexec(
|
|
20085
20159
|
"git",
|
|
20086
|
-
["-C", cwd, "worktree", "add", worktreeRoot, "-b", branch, baseBranch],
|
|
20160
|
+
["-C", cwd, "worktree", "add", worktreeRoot, "-b", branch, `origin/${baseBranch}`],
|
|
20087
20161
|
{ timeout: 15e3 }
|
|
20088
20162
|
);
|
|
20089
20163
|
} catch (err) {
|
|
@@ -20105,8 +20179,8 @@ async function removeWorktree(input) {
|
|
|
20105
20179
|
);
|
|
20106
20180
|
const gitCommonDir = stdout.trim();
|
|
20107
20181
|
if (!gitCommonDir) throw new Error("empty git-common-dir");
|
|
20108
|
-
const absGitCommon =
|
|
20109
|
-
repoRoot =
|
|
20182
|
+
const absGitCommon = import_node_path18.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path18.default.resolve(worktreeRoot, gitCommonDir);
|
|
20183
|
+
repoRoot = import_node_path18.default.dirname(absGitCommon);
|
|
20110
20184
|
} catch {
|
|
20111
20185
|
repoRoot = null;
|
|
20112
20186
|
}
|
|
@@ -20137,9 +20211,9 @@ async function removeWorktree(input) {
|
|
|
20137
20211
|
try {
|
|
20138
20212
|
const encoded = encodeClaudeProjectDir(worktreeRoot);
|
|
20139
20213
|
if (encoded) {
|
|
20140
|
-
const projectsRoot =
|
|
20141
|
-
const target =
|
|
20142
|
-
if (target.startsWith(projectsRoot +
|
|
20214
|
+
const projectsRoot = import_node_path18.default.join(import_node_os11.default.homedir(), ".claude", "projects");
|
|
20215
|
+
const target = import_node_path18.default.resolve(projectsRoot, encoded);
|
|
20216
|
+
if (target.startsWith(projectsRoot + import_node_path18.default.sep) && target !== projectsRoot) {
|
|
20143
20217
|
import_node_fs18.default.rmSync(target, { recursive: true, force: true });
|
|
20144
20218
|
}
|
|
20145
20219
|
}
|
|
@@ -20352,7 +20426,7 @@ function buildMethodHandlers(deps) {
|
|
|
20352
20426
|
async function startDaemon(config) {
|
|
20353
20427
|
const logger = createLogger({
|
|
20354
20428
|
level: config.logLevel,
|
|
20355
|
-
file:
|
|
20429
|
+
file: import_node_path19.default.join(config.dataDir, "clawd.log")
|
|
20356
20430
|
});
|
|
20357
20431
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
20358
20432
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -20394,7 +20468,7 @@ async function startDaemon(config) {
|
|
|
20394
20468
|
getAdapter,
|
|
20395
20469
|
historyReader: history,
|
|
20396
20470
|
dataDir: config.dataDir,
|
|
20397
|
-
personaRoot:
|
|
20471
|
+
personaRoot: import_node_path19.default.join(config.dataDir, "personas"),
|
|
20398
20472
|
broadcastFrame: (frame, target) => {
|
|
20399
20473
|
if (target === "all") {
|
|
20400
20474
|
transport?.broadcastAll(frame);
|
|
@@ -20434,7 +20508,7 @@ async function startDaemon(config) {
|
|
|
20434
20508
|
manager.recordRealUserUuid({ sessionId, realUuid, text });
|
|
20435
20509
|
}
|
|
20436
20510
|
});
|
|
20437
|
-
const personaStore = new PersonaStore(
|
|
20511
|
+
const personaStore = new PersonaStore(import_node_path19.default.join(config.dataDir, "personas"));
|
|
20438
20512
|
const personaRegistry = new PersonaRegistry(personaStore);
|
|
20439
20513
|
const personaManager = new PersonaManager({
|
|
20440
20514
|
store: personaStore,
|
|
@@ -20567,8 +20641,8 @@ async function startDaemon(config) {
|
|
|
20567
20641
|
const lines = [
|
|
20568
20642
|
`Tunnel: ${r.url}`,
|
|
20569
20643
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
20570
|
-
`Frpc config: ${
|
|
20571
|
-
`Frpc log: ${
|
|
20644
|
+
`Frpc config: ${import_node_path19.default.join(config.dataDir, "frpc.toml")}`,
|
|
20645
|
+
`Frpc log: ${import_node_path19.default.join(config.dataDir, "frpc.log")}`
|
|
20572
20646
|
];
|
|
20573
20647
|
const width = Math.max(...lines.map((l) => l.length));
|
|
20574
20648
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -20581,7 +20655,7 @@ ${bar}
|
|
|
20581
20655
|
|
|
20582
20656
|
`);
|
|
20583
20657
|
try {
|
|
20584
|
-
const connectPath =
|
|
20658
|
+
const connectPath = import_node_path19.default.join(config.dataDir, "connect.txt");
|
|
20585
20659
|
import_node_fs19.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
20586
20660
|
} catch {
|
|
20587
20661
|
}
|
package/package.json
CHANGED