@clawos-dev/clawd 0.2.603 → 0.2.604
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 +485 -483
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -62563,6 +62563,81 @@ var SubscriptionChannelStore = class {
|
|
|
62563
62563
|
}
|
|
62564
62564
|
};
|
|
62565
62565
|
|
|
62566
|
+
// src/tools/subscription-channels-apply.ts
|
|
62567
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
62568
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
62569
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
62570
|
+
var TABLE_HEADER = /^\s*\[\[?\s*([A-Za-z0-9_.-]+)\s*\]\]?\s*(?:#.*)?$/;
|
|
62571
|
+
var KEY_LINE = /^\s*([A-Za-z0-9_.-]+)\s*=/;
|
|
62572
|
+
function stripCodexProvider(text) {
|
|
62573
|
+
const out = [];
|
|
62574
|
+
let inProviderSection = false;
|
|
62575
|
+
for (const line of text.split("\n")) {
|
|
62576
|
+
const headerMatch = TABLE_HEADER.exec(line);
|
|
62577
|
+
if (headerMatch) {
|
|
62578
|
+
const section = headerMatch[1].trim();
|
|
62579
|
+
inProviderSection = section === "model_providers" || section.startsWith("model_providers.");
|
|
62580
|
+
if (inProviderSection) continue;
|
|
62581
|
+
out.push(line);
|
|
62582
|
+
continue;
|
|
62583
|
+
}
|
|
62584
|
+
if (inProviderSection) continue;
|
|
62585
|
+
const keyMatch = KEY_LINE.exec(line);
|
|
62586
|
+
if (keyMatch) {
|
|
62587
|
+
const key = keyMatch[1].trim();
|
|
62588
|
+
if (key === "model_provider" || key.startsWith("model_providers.")) {
|
|
62589
|
+
continue;
|
|
62590
|
+
}
|
|
62591
|
+
}
|
|
62592
|
+
out.push(line);
|
|
62593
|
+
}
|
|
62594
|
+
return out.join("\n").trim();
|
|
62595
|
+
}
|
|
62596
|
+
function applyCodexSubscriptionChannel(opts) {
|
|
62597
|
+
const codexHome = opts.codexHome || process.env.CODEX_HOME || import_node_path41.default.join(import_node_os13.default.homedir(), ".codex");
|
|
62598
|
+
import_node_fs36.default.mkdirSync(codexHome, { recursive: true });
|
|
62599
|
+
const configFile = import_node_path41.default.join(codexHome, "config.toml");
|
|
62600
|
+
const original = import_node_fs36.default.existsSync(configFile) ? import_node_fs36.default.readFileSync(configFile, "utf8") : "";
|
|
62601
|
+
const rest = stripCodexProvider(original);
|
|
62602
|
+
let content;
|
|
62603
|
+
if (opts.channel) {
|
|
62604
|
+
const ch = opts.channel;
|
|
62605
|
+
content = [
|
|
62606
|
+
'model_provider = "cliproxyapi"',
|
|
62607
|
+
...rest ? ["", rest] : [],
|
|
62608
|
+
"",
|
|
62609
|
+
"[model_providers.cliproxyapi]",
|
|
62610
|
+
'name = "cliproxyapi"',
|
|
62611
|
+
`base_url = ${JSON.stringify(ch.baseUrl)}`,
|
|
62612
|
+
'wire_api = "responses"',
|
|
62613
|
+
`auth = { command = "echo", args = [${JSON.stringify(ch.apiKey)}] }`,
|
|
62614
|
+
""
|
|
62615
|
+
].join("\n");
|
|
62616
|
+
} else {
|
|
62617
|
+
content = [
|
|
62618
|
+
'model_provider = "openai"',
|
|
62619
|
+
...rest ? ["", rest] : [],
|
|
62620
|
+
""
|
|
62621
|
+
].join("\n");
|
|
62622
|
+
}
|
|
62623
|
+
const tmpFile = `${configFile}.tmp.${Date.now()}`;
|
|
62624
|
+
import_node_fs36.default.writeFileSync(tmpFile, content, { mode: 384 });
|
|
62625
|
+
import_node_fs36.default.renameSync(tmpFile, configFile);
|
|
62626
|
+
}
|
|
62627
|
+
function applyPiSubscriptionChannel(opts) {
|
|
62628
|
+
const agentDir = opts.agentDir || process.env.PI_CODING_AGENT_DIR || import_node_path41.default.join(import_node_os13.default.homedir(), ".pi", "agent");
|
|
62629
|
+
if (!import_node_fs36.default.existsSync(agentDir)) return false;
|
|
62630
|
+
const configFile = import_node_path41.default.join(agentDir, "cliproxyapi.json");
|
|
62631
|
+
if (opts.channel) {
|
|
62632
|
+
const data = { baseUrl: opts.channel.baseUrl, apiKey: opts.channel.apiKey };
|
|
62633
|
+
const tmp = `${configFile}.tmp.${Date.now()}`;
|
|
62634
|
+
import_node_fs36.default.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
|
|
62635
|
+
import_node_fs36.default.renameSync(tmp, configFile);
|
|
62636
|
+
return true;
|
|
62637
|
+
}
|
|
62638
|
+
return false;
|
|
62639
|
+
}
|
|
62640
|
+
|
|
62566
62641
|
// src/deploy/local-probe.ts
|
|
62567
62642
|
function pickVersion(s2) {
|
|
62568
62643
|
return /(\d+)\.(\d+)(?:\.(\d+))?/.exec(s2)?.[0];
|
|
@@ -62611,10 +62686,10 @@ async function probeLocalVersion(exec, pkg) {
|
|
|
62611
62686
|
|
|
62612
62687
|
// src/tools/shell-path.ts
|
|
62613
62688
|
var import_node_child_process10 = require("child_process");
|
|
62614
|
-
var
|
|
62689
|
+
var import_node_os14 = __toESM(require("os"), 1);
|
|
62615
62690
|
function refreshPathFromLoginShell() {
|
|
62616
62691
|
if (process.platform === "win32") return;
|
|
62617
|
-
const shell = process.env.SHELL ??
|
|
62692
|
+
const shell = process.env.SHELL ?? import_node_os14.default.userInfo().shell ?? "/bin/zsh";
|
|
62618
62693
|
try {
|
|
62619
62694
|
const out = (0, import_node_child_process10.execFileSync)(shell, ["-ilc", 'command echo -n "$PATH"'], {
|
|
62620
62695
|
encoding: "utf8",
|
|
@@ -63160,15 +63235,15 @@ async function refreshTunnelUrlOnStartup(deps) {
|
|
|
63160
63235
|
}
|
|
63161
63236
|
|
|
63162
63237
|
// src/lark-bot-connector/binding-store.ts
|
|
63163
|
-
var
|
|
63164
|
-
var
|
|
63238
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
63239
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
63165
63240
|
function createLarkBotBindingStore(personaRoot) {
|
|
63166
|
-
const filePath = (personaId2) =>
|
|
63241
|
+
const filePath = (personaId2) => import_node_path42.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
|
|
63167
63242
|
const read = (personaId2) => {
|
|
63168
63243
|
const file = filePath(personaId2);
|
|
63169
|
-
if (!
|
|
63244
|
+
if (!import_node_fs37.default.existsSync(file)) return null;
|
|
63170
63245
|
try {
|
|
63171
|
-
const raw = JSON.parse(
|
|
63246
|
+
const raw = JSON.parse(import_node_fs37.default.readFileSync(file, "utf8"));
|
|
63172
63247
|
if (typeof raw?.appId !== "string" || raw.appId.length === 0) return null;
|
|
63173
63248
|
return raw;
|
|
63174
63249
|
} catch {
|
|
@@ -63177,16 +63252,16 @@ function createLarkBotBindingStore(personaRoot) {
|
|
|
63177
63252
|
};
|
|
63178
63253
|
const write = (personaId2, meta) => {
|
|
63179
63254
|
const file = filePath(personaId2);
|
|
63180
|
-
|
|
63255
|
+
import_node_fs37.default.mkdirSync(import_node_path42.default.dirname(file), { recursive: true });
|
|
63181
63256
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
63182
|
-
|
|
63183
|
-
|
|
63257
|
+
import_node_fs37.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
63258
|
+
import_node_fs37.default.renameSync(tmp, file);
|
|
63184
63259
|
};
|
|
63185
63260
|
return {
|
|
63186
63261
|
read,
|
|
63187
63262
|
write,
|
|
63188
63263
|
remove(personaId2) {
|
|
63189
|
-
|
|
63264
|
+
import_node_fs37.default.rmSync(filePath(personaId2), { force: true });
|
|
63190
63265
|
},
|
|
63191
63266
|
addRemovedChat(personaId2, chatId) {
|
|
63192
63267
|
const meta = read(personaId2);
|
|
@@ -63338,8 +63413,8 @@ function createLarkBotCloudClient(opts) {
|
|
|
63338
63413
|
}
|
|
63339
63414
|
|
|
63340
63415
|
// src/lark-bot-connector/chat-router.ts
|
|
63341
|
-
var
|
|
63342
|
-
var
|
|
63416
|
+
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
63417
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
63343
63418
|
init_protocol();
|
|
63344
63419
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
63345
63420
|
var LOCAL_TURN_RETRIES = 2;
|
|
@@ -63417,9 +63492,9 @@ function createLarkChatRouter(deps) {
|
|
|
63417
63492
|
continue;
|
|
63418
63493
|
}
|
|
63419
63494
|
const dir = deps.mediaRootFor(env.chatId);
|
|
63420
|
-
|
|
63421
|
-
const p3 =
|
|
63422
|
-
|
|
63495
|
+
import_node_fs38.default.mkdirSync(dir, { recursive: true });
|
|
63496
|
+
const p3 = import_node_path43.default.join(dir, `${safeMediaName(ownerMessageId)}-${i2}.${ext}`);
|
|
63497
|
+
import_node_fs38.default.writeFileSync(p3, r2.data);
|
|
63423
63498
|
lines.push(`[\u56FE\u7247: ${p3}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
63424
63499
|
} catch (err) {
|
|
63425
63500
|
deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
|
|
@@ -63440,9 +63515,9 @@ function createLarkChatRouter(deps) {
|
|
|
63440
63515
|
continue;
|
|
63441
63516
|
}
|
|
63442
63517
|
const dir = deps.mediaRootFor(env.chatId);
|
|
63443
|
-
|
|
63444
|
-
const p3 =
|
|
63445
|
-
|
|
63518
|
+
import_node_fs38.default.mkdirSync(dir, { recursive: true });
|
|
63519
|
+
const p3 = import_node_path43.default.join(dir, `${safeMediaName(ownerMessageId)}-${i2}-${safeAttachmentName(f2.name)}`);
|
|
63520
|
+
import_node_fs38.default.writeFileSync(p3, r2.data);
|
|
63446
63521
|
lines.push(`[\u6587\u4EF6: ${p3}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
63447
63522
|
} catch (err) {
|
|
63448
63523
|
deps.logger?.warn(`larkBot file fetch failed ${f2.key}: ${err.message}`);
|
|
@@ -64813,7 +64888,7 @@ function openHttpLineStream(opts) {
|
|
|
64813
64888
|
init_protocol();
|
|
64814
64889
|
|
|
64815
64890
|
// src/tools/codex-cloud-session.ts
|
|
64816
|
-
var
|
|
64891
|
+
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
64817
64892
|
|
|
64818
64893
|
// src/tools/cloud-portable-input.ts
|
|
64819
64894
|
async function portableCloudInput(text, resolvers) {
|
|
@@ -64842,7 +64917,7 @@ function cloudImageInput(deps) {
|
|
|
64842
64917
|
const mime = lookupMime(p3);
|
|
64843
64918
|
if (!mime.startsWith("image/")) return null;
|
|
64844
64919
|
try {
|
|
64845
|
-
const bytes = (deps.readFile ??
|
|
64920
|
+
const bytes = (deps.readFile ?? import_node_fs39.default.readFileSync)(p3);
|
|
64846
64921
|
return { type: "image", url: `data:${mime};base64,${bytes.toString("base64")}` };
|
|
64847
64922
|
} catch (e) {
|
|
64848
64923
|
deps.logger?.warn("cloud image attachment unreadable", { path: p3, message: e.message });
|
|
@@ -65000,7 +65075,7 @@ init_protocol();
|
|
|
65000
65075
|
|
|
65001
65076
|
// src/tools/pi.ts
|
|
65002
65077
|
var import_node_child_process12 = require("child_process");
|
|
65003
|
-
var
|
|
65078
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
65004
65079
|
init_protocol();
|
|
65005
65080
|
|
|
65006
65081
|
// src/tools/pi-rpc-client.ts
|
|
@@ -65101,8 +65176,8 @@ var PiRpcClient = class {
|
|
|
65101
65176
|
// src/tools/pi-session.ts
|
|
65102
65177
|
var import_node_child_process11 = require("child_process");
|
|
65103
65178
|
var import_node_crypto12 = require("crypto");
|
|
65104
|
-
var
|
|
65105
|
-
var
|
|
65179
|
+
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
65180
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
65106
65181
|
|
|
65107
65182
|
// src/tools/pi-events.ts
|
|
65108
65183
|
init_protocol();
|
|
@@ -65374,8 +65449,8 @@ ${dirs.map((d2) => `- ${d2}`).join("\n")}`;
|
|
|
65374
65449
|
function createPiSession(ctx, sink, deps = {}) {
|
|
65375
65450
|
const cmd = process.env.PI_BIN ?? "pi";
|
|
65376
65451
|
const sessionId = ctx.toolSessionId ?? (0, import_node_crypto12.randomUUID)();
|
|
65377
|
-
const skillsDir =
|
|
65378
|
-
const exists = deps.skillsDirExists ?? ((d2) =>
|
|
65452
|
+
const skillsDir = import_node_path44.default.join(ctx.cwd, ".claude", "skills");
|
|
65453
|
+
const exists = deps.skillsDirExists ?? ((d2) => import_node_fs40.default.existsSync(d2));
|
|
65379
65454
|
const args = buildPiArgs(ctx, {
|
|
65380
65455
|
sessionId,
|
|
65381
65456
|
skillsDir: exists(skillsDir) ? skillsDir : void 0,
|
|
@@ -65437,10 +65512,10 @@ var PI_DEFAULT_MODEL_ENTRY = {
|
|
|
65437
65512
|
};
|
|
65438
65513
|
var PI_FULL_ACCESS = { id: "never", label: "Full Access", description: "pi \u65E0\u5BA1\u6279\uFF1A\u4ECE\u4E0D\u8BE2\u95EE\uFF0C\u81EA\u4E3B\u6267\u884C" };
|
|
65439
65514
|
async function probePi(env = process.env) {
|
|
65440
|
-
if (env.PI_BIN &&
|
|
65515
|
+
if (env.PI_BIN && import_node_fs41.default.existsSync(env.PI_BIN)) return { available: true, path: env.PI_BIN };
|
|
65441
65516
|
try {
|
|
65442
65517
|
const out = (0, import_node_child_process12.execFileSync)("which", ["pi"], { encoding: "utf8" }).trim();
|
|
65443
|
-
if (out &&
|
|
65518
|
+
if (out && import_node_fs41.default.existsSync(out)) return { available: true, path: out };
|
|
65444
65519
|
} catch {
|
|
65445
65520
|
}
|
|
65446
65521
|
return { available: false };
|
|
@@ -65757,7 +65832,7 @@ var CloudPiAdapter = class {
|
|
|
65757
65832
|
init_protocol();
|
|
65758
65833
|
|
|
65759
65834
|
// src/tools/codex-skills.ts
|
|
65760
|
-
var
|
|
65835
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
65761
65836
|
function str4(v3) {
|
|
65762
65837
|
return typeof v3 === "string" ? v3 : void 0;
|
|
65763
65838
|
}
|
|
@@ -65794,7 +65869,7 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
65794
65869
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
65795
65870
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
65796
65871
|
beforeRequest: (client) => {
|
|
65797
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
65872
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path45.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
65798
65873
|
}
|
|
65799
65874
|
});
|
|
65800
65875
|
return mapSkillsListResponse(res);
|
|
@@ -65868,23 +65943,23 @@ function rec4(v3) {
|
|
|
65868
65943
|
}
|
|
65869
65944
|
|
|
65870
65945
|
// src/workspace/browser.ts
|
|
65871
|
-
var
|
|
65872
|
-
var
|
|
65873
|
-
var
|
|
65946
|
+
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
65947
|
+
var import_node_os15 = __toESM(require("os"), 1);
|
|
65948
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
65874
65949
|
init_protocol();
|
|
65875
65950
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
65876
65951
|
function resolveInsideCwd(cwd, subpath) {
|
|
65877
|
-
const absCwd =
|
|
65878
|
-
const joined =
|
|
65879
|
-
const rel =
|
|
65880
|
-
if (rel.startsWith("..") ||
|
|
65952
|
+
const absCwd = import_node_path46.default.resolve(cwd);
|
|
65953
|
+
const joined = import_node_path46.default.resolve(absCwd, subpath ?? ".");
|
|
65954
|
+
const rel = import_node_path46.default.relative(absCwd, joined);
|
|
65955
|
+
if (rel.startsWith("..") || import_node_path46.default.isAbsolute(rel)) {
|
|
65881
65956
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
65882
65957
|
}
|
|
65883
65958
|
return joined;
|
|
65884
65959
|
}
|
|
65885
65960
|
function ensureCwd(cwd) {
|
|
65886
65961
|
try {
|
|
65887
|
-
const stat =
|
|
65962
|
+
const stat = import_node_fs42.default.statSync(cwd);
|
|
65888
65963
|
if (!stat.isDirectory()) {
|
|
65889
65964
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
65890
65965
|
}
|
|
@@ -65895,10 +65970,10 @@ function ensureCwd(cwd) {
|
|
|
65895
65970
|
}
|
|
65896
65971
|
var WorkspaceBrowser = class {
|
|
65897
65972
|
list(args) {
|
|
65898
|
-
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd :
|
|
65973
|
+
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os15.default.homedir();
|
|
65899
65974
|
ensureCwd(cwd);
|
|
65900
65975
|
const full = resolveInsideCwd(cwd, args.path);
|
|
65901
|
-
const dirents =
|
|
65976
|
+
const dirents = import_node_fs42.default.readdirSync(full, { withFileTypes: true });
|
|
65902
65977
|
const entries = [];
|
|
65903
65978
|
for (const d2 of dirents) {
|
|
65904
65979
|
if (!args.showHidden && d2.name.startsWith(".")) continue;
|
|
@@ -65908,7 +65983,7 @@ var WorkspaceBrowser = class {
|
|
|
65908
65983
|
mtime: ""
|
|
65909
65984
|
};
|
|
65910
65985
|
try {
|
|
65911
|
-
const st2 =
|
|
65986
|
+
const st2 = import_node_fs42.default.statSync(import_node_path46.default.join(full, d2.name));
|
|
65912
65987
|
entry.mtime = new Date(st2.mtimeMs).toISOString();
|
|
65913
65988
|
if (d2.isFile()) entry.size = st2.size;
|
|
65914
65989
|
} catch {
|
|
@@ -65924,14 +65999,14 @@ var WorkspaceBrowser = class {
|
|
|
65924
65999
|
read(args) {
|
|
65925
66000
|
ensureCwd(args.cwd);
|
|
65926
66001
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
65927
|
-
const st2 =
|
|
66002
|
+
const st2 = import_node_fs42.default.statSync(full);
|
|
65928
66003
|
if (!st2.isFile()) {
|
|
65929
66004
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
65930
66005
|
}
|
|
65931
66006
|
if (st2.size > MAX_FILE_BYTES2) {
|
|
65932
66007
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
|
|
65933
66008
|
}
|
|
65934
|
-
const buf =
|
|
66009
|
+
const buf = import_node_fs42.default.readFileSync(full);
|
|
65935
66010
|
const isBinary = buf.includes(0);
|
|
65936
66011
|
if (isBinary) {
|
|
65937
66012
|
return {
|
|
@@ -65953,20 +66028,20 @@ var WorkspaceBrowser = class {
|
|
|
65953
66028
|
};
|
|
65954
66029
|
|
|
65955
66030
|
// src/skills/agents-scanner.ts
|
|
65956
|
-
var
|
|
65957
|
-
var
|
|
65958
|
-
var
|
|
66031
|
+
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
66032
|
+
var import_node_os16 = __toESM(require("os"), 1);
|
|
66033
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
65959
66034
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
65960
66035
|
function isDirLikeSync2(p3) {
|
|
65961
66036
|
try {
|
|
65962
|
-
return
|
|
66037
|
+
return import_node_fs43.default.statSync(p3).isDirectory();
|
|
65963
66038
|
} catch {
|
|
65964
66039
|
return false;
|
|
65965
66040
|
}
|
|
65966
66041
|
}
|
|
65967
66042
|
function fileExistsSync(p3) {
|
|
65968
66043
|
try {
|
|
65969
|
-
return
|
|
66044
|
+
return import_node_fs43.default.statSync(p3).isFile();
|
|
65970
66045
|
} catch {
|
|
65971
66046
|
return false;
|
|
65972
66047
|
}
|
|
@@ -65974,7 +66049,7 @@ function fileExistsSync(p3) {
|
|
|
65974
66049
|
function parseAgentFile(filePath) {
|
|
65975
66050
|
let content;
|
|
65976
66051
|
try {
|
|
65977
|
-
content =
|
|
66052
|
+
content = import_node_fs43.default.readFileSync(filePath, "utf8");
|
|
65978
66053
|
} catch {
|
|
65979
66054
|
return {};
|
|
65980
66055
|
}
|
|
@@ -65987,16 +66062,16 @@ function parseAgentFile(filePath) {
|
|
|
65987
66062
|
function scanAgentsDir(dir, source, seen, out) {
|
|
65988
66063
|
let entries;
|
|
65989
66064
|
try {
|
|
65990
|
-
entries =
|
|
66065
|
+
entries = import_node_fs43.default.readdirSync(dir, { withFileTypes: true });
|
|
65991
66066
|
} catch {
|
|
65992
66067
|
return;
|
|
65993
66068
|
}
|
|
65994
66069
|
for (const ent of entries) {
|
|
65995
66070
|
if (!ent.name.endsWith(".md")) continue;
|
|
65996
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
66071
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path47.default.join(dir, ent.name)))) {
|
|
65997
66072
|
continue;
|
|
65998
66073
|
}
|
|
65999
|
-
const filePath =
|
|
66074
|
+
const filePath = import_node_path47.default.join(dir, ent.name);
|
|
66000
66075
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
66001
66076
|
if (seen.has(baseName)) continue;
|
|
66002
66077
|
seen.add(baseName);
|
|
@@ -66014,12 +66089,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
66014
66089
|
function walk2(dir, namespaces) {
|
|
66015
66090
|
let entries;
|
|
66016
66091
|
try {
|
|
66017
|
-
entries =
|
|
66092
|
+
entries = import_node_fs43.default.readdirSync(dir, { withFileTypes: true });
|
|
66018
66093
|
} catch {
|
|
66019
66094
|
return;
|
|
66020
66095
|
}
|
|
66021
66096
|
for (const ent of entries) {
|
|
66022
|
-
const childPath =
|
|
66097
|
+
const childPath = import_node_path47.default.join(dir, ent.name);
|
|
66023
66098
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
66024
66099
|
walk2(childPath, [...namespaces, ent.name]);
|
|
66025
66100
|
continue;
|
|
@@ -66044,13 +66119,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
66044
66119
|
walk2(root, []);
|
|
66045
66120
|
}
|
|
66046
66121
|
function readInstalledPlugins2(home) {
|
|
66047
|
-
const pluginsDir =
|
|
66048
|
-
const v22 =
|
|
66049
|
-
const v1 =
|
|
66122
|
+
const pluginsDir = import_node_path47.default.join(home, ".claude", "plugins");
|
|
66123
|
+
const v22 = import_node_path47.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
66124
|
+
const v1 = import_node_path47.default.join(pluginsDir, "installed_plugins.json");
|
|
66050
66125
|
let raw = null;
|
|
66051
66126
|
for (const candidate of [v22, v1]) {
|
|
66052
66127
|
try {
|
|
66053
|
-
raw =
|
|
66128
|
+
raw = import_node_fs43.default.readFileSync(candidate, "utf8");
|
|
66054
66129
|
break;
|
|
66055
66130
|
} catch {
|
|
66056
66131
|
}
|
|
@@ -66075,19 +66150,19 @@ function readInstalledPlugins2(home) {
|
|
|
66075
66150
|
return out;
|
|
66076
66151
|
}
|
|
66077
66152
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
66078
|
-
let cur =
|
|
66079
|
-
const fsRoot =
|
|
66153
|
+
let cur = import_node_path47.default.resolve(startCwd);
|
|
66154
|
+
const fsRoot = import_node_path47.default.parse(cur).root;
|
|
66080
66155
|
while (true) {
|
|
66081
|
-
scanAgentsDir(
|
|
66156
|
+
scanAgentsDir(import_node_path47.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
66082
66157
|
let hasGit = false;
|
|
66083
66158
|
try {
|
|
66084
|
-
hasGit =
|
|
66159
|
+
hasGit = import_node_fs43.default.existsSync(import_node_path47.default.join(cur, ".git"));
|
|
66085
66160
|
} catch {
|
|
66086
66161
|
}
|
|
66087
66162
|
if (hasGit) return;
|
|
66088
66163
|
if (cur === home) return;
|
|
66089
66164
|
if (cur === fsRoot) return;
|
|
66090
|
-
const parent =
|
|
66165
|
+
const parent = import_node_path47.default.dirname(cur);
|
|
66091
66166
|
if (parent === cur) return;
|
|
66092
66167
|
cur = parent;
|
|
66093
66168
|
}
|
|
@@ -66097,7 +66172,7 @@ var AgentsScanner = class {
|
|
|
66097
66172
|
extraPluginRoots;
|
|
66098
66173
|
policyDir;
|
|
66099
66174
|
constructor(opts = {}) {
|
|
66100
|
-
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ??
|
|
66175
|
+
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os16.default.homedir();
|
|
66101
66176
|
this.extraPluginRoots = opts.extraPluginRoots ?? [];
|
|
66102
66177
|
if (opts.policyDir !== void 0) {
|
|
66103
66178
|
this.policyDir = opts.policyDir;
|
|
@@ -66122,7 +66197,7 @@ var AgentsScanner = class {
|
|
|
66122
66197
|
}
|
|
66123
66198
|
const fsBlock = [];
|
|
66124
66199
|
scanAgentsDir(
|
|
66125
|
-
|
|
66200
|
+
import_node_path47.default.join(this.home, ".claude", "agents"),
|
|
66126
66201
|
"global",
|
|
66127
66202
|
seen,
|
|
66128
66203
|
fsBlock
|
|
@@ -66136,7 +66211,7 @@ var AgentsScanner = class {
|
|
|
66136
66211
|
...this.extraPluginRoots
|
|
66137
66212
|
];
|
|
66138
66213
|
for (const { name, root } of plugins) {
|
|
66139
|
-
const agentsRoot =
|
|
66214
|
+
const agentsRoot = import_node_path47.default.join(root, "agents");
|
|
66140
66215
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
66141
66216
|
}
|
|
66142
66217
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -66144,28 +66219,28 @@ var AgentsScanner = class {
|
|
|
66144
66219
|
};
|
|
66145
66220
|
|
|
66146
66221
|
// src/observer/session-observer.ts
|
|
66147
|
-
var
|
|
66148
|
-
var
|
|
66149
|
-
var
|
|
66222
|
+
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
66223
|
+
var import_node_os18 = __toESM(require("os"), 1);
|
|
66224
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
66150
66225
|
init_claude_history();
|
|
66151
66226
|
|
|
66152
66227
|
// src/observer/subagent-meta-observer.ts
|
|
66153
|
-
var
|
|
66154
|
-
var
|
|
66155
|
-
var
|
|
66228
|
+
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
66229
|
+
var import_node_os17 = __toESM(require("os"), 1);
|
|
66230
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
66156
66231
|
init_claude_history();
|
|
66157
66232
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
66158
66233
|
var SubagentMetaObserver = class {
|
|
66159
66234
|
constructor(opts) {
|
|
66160
66235
|
this.opts = opts;
|
|
66161
|
-
this.home = opts.home ??
|
|
66236
|
+
this.home = opts.home ?? import_node_os17.default.homedir();
|
|
66162
66237
|
}
|
|
66163
66238
|
opts;
|
|
66164
66239
|
home;
|
|
66165
66240
|
watches = /* @__PURE__ */ new Map();
|
|
66166
66241
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
66167
66242
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
66168
|
-
return
|
|
66243
|
+
return import_node_path48.default.join(
|
|
66169
66244
|
this.home,
|
|
66170
66245
|
".claude",
|
|
66171
66246
|
"projects",
|
|
@@ -66195,7 +66270,7 @@ var SubagentMetaObserver = class {
|
|
|
66195
66270
|
attachWatcher(w3) {
|
|
66196
66271
|
if (w3.watcher) return;
|
|
66197
66272
|
try {
|
|
66198
|
-
w3.watcher =
|
|
66273
|
+
w3.watcher = import_node_fs44.default.watch(w3.dirPath, { persistent: false }, (_evt, name) => {
|
|
66199
66274
|
if (!name) return;
|
|
66200
66275
|
const m3 = META_RE.exec(String(name));
|
|
66201
66276
|
if (!m3) return;
|
|
@@ -66207,7 +66282,7 @@ var SubagentMetaObserver = class {
|
|
|
66207
66282
|
scan(w3) {
|
|
66208
66283
|
let entries;
|
|
66209
66284
|
try {
|
|
66210
|
-
entries =
|
|
66285
|
+
entries = import_node_fs44.default.readdirSync(w3.dirPath);
|
|
66211
66286
|
} catch {
|
|
66212
66287
|
return;
|
|
66213
66288
|
}
|
|
@@ -66221,10 +66296,10 @@ var SubagentMetaObserver = class {
|
|
|
66221
66296
|
if (!m3) return;
|
|
66222
66297
|
const agentId = m3[1];
|
|
66223
66298
|
if (w3.emitted.has(agentId)) return;
|
|
66224
|
-
const file =
|
|
66299
|
+
const file = import_node_path48.default.join(w3.dirPath, name);
|
|
66225
66300
|
let raw;
|
|
66226
66301
|
try {
|
|
66227
|
-
raw =
|
|
66302
|
+
raw = import_node_fs44.default.readFileSync(file, "utf8");
|
|
66228
66303
|
} catch {
|
|
66229
66304
|
return;
|
|
66230
66305
|
}
|
|
@@ -66269,7 +66344,7 @@ var SubagentMetaObserver = class {
|
|
|
66269
66344
|
var SessionObserver = class {
|
|
66270
66345
|
constructor(opts) {
|
|
66271
66346
|
this.opts = opts;
|
|
66272
|
-
this.home = opts.home ??
|
|
66347
|
+
this.home = opts.home ?? import_node_os18.default.homedir();
|
|
66273
66348
|
this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
|
|
66274
66349
|
}
|
|
66275
66350
|
opts;
|
|
@@ -66281,14 +66356,14 @@ var SessionObserver = class {
|
|
|
66281
66356
|
metaObserver;
|
|
66282
66357
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
66283
66358
|
if (override) return override;
|
|
66284
|
-
return
|
|
66359
|
+
return import_node_path49.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
66285
66360
|
}
|
|
66286
66361
|
start(args) {
|
|
66287
66362
|
this.stop(args.sessionId);
|
|
66288
66363
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
66289
66364
|
let size = 0;
|
|
66290
66365
|
try {
|
|
66291
|
-
size =
|
|
66366
|
+
size = import_node_fs45.default.statSync(filePath).size;
|
|
66292
66367
|
} catch {
|
|
66293
66368
|
}
|
|
66294
66369
|
const w3 = {
|
|
@@ -66301,16 +66376,16 @@ var SessionObserver = class {
|
|
|
66301
66376
|
adapter: args.adapter,
|
|
66302
66377
|
prevIsRejectSentinel: false,
|
|
66303
66378
|
toolSessionId: args.toolSessionId,
|
|
66304
|
-
sawFile:
|
|
66379
|
+
sawFile: import_node_fs45.default.existsSync(filePath),
|
|
66305
66380
|
lastRelocateScanMs: 0,
|
|
66306
66381
|
pendingCwdDerive: false,
|
|
66307
66382
|
lastDeriveMs: 0
|
|
66308
66383
|
};
|
|
66309
66384
|
try {
|
|
66310
|
-
|
|
66385
|
+
import_node_fs45.default.mkdirSync(import_node_path49.default.dirname(filePath), { recursive: true });
|
|
66311
66386
|
} catch {
|
|
66312
66387
|
}
|
|
66313
|
-
w3.watcher =
|
|
66388
|
+
w3.watcher = import_node_fs45.default.watch(import_node_path49.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
66314
66389
|
if (!changedName || !w3.filePath.endsWith(changedName)) return;
|
|
66315
66390
|
this.poll(w3);
|
|
66316
66391
|
});
|
|
@@ -66333,7 +66408,7 @@ var SessionObserver = class {
|
|
|
66333
66408
|
// 异常静默吞,不阻塞 watcher 启动
|
|
66334
66409
|
hydrateMetaTail(w3, maxLines = 200) {
|
|
66335
66410
|
try {
|
|
66336
|
-
const raw =
|
|
66411
|
+
const raw = import_node_fs45.default.readFileSync(w3.filePath, "utf8");
|
|
66337
66412
|
if (!raw) return;
|
|
66338
66413
|
const allLines = raw.split("\n").filter((l2) => l2.trim().length > 0);
|
|
66339
66414
|
if (allLines.length === 0) return;
|
|
@@ -66357,7 +66432,7 @@ var SessionObserver = class {
|
|
|
66357
66432
|
poll(w3) {
|
|
66358
66433
|
let size = 0;
|
|
66359
66434
|
try {
|
|
66360
|
-
size =
|
|
66435
|
+
size = import_node_fs45.default.statSync(w3.filePath).size;
|
|
66361
66436
|
} catch {
|
|
66362
66437
|
if (w3.sawFile) this.maybeRelocate(w3);
|
|
66363
66438
|
return;
|
|
@@ -66368,11 +66443,11 @@ var SessionObserver = class {
|
|
|
66368
66443
|
w3.buf = "";
|
|
66369
66444
|
}
|
|
66370
66445
|
if (size === w3.lastSize) return;
|
|
66371
|
-
const fd =
|
|
66446
|
+
const fd = import_node_fs45.default.openSync(w3.filePath, "r");
|
|
66372
66447
|
try {
|
|
66373
66448
|
const len = size - w3.lastSize;
|
|
66374
66449
|
const buf = Buffer.alloc(len);
|
|
66375
|
-
|
|
66450
|
+
import_node_fs45.default.readSync(fd, buf, 0, len, w3.lastSize);
|
|
66376
66451
|
w3.lastSize = size;
|
|
66377
66452
|
w3.buf += buf.toString("utf8");
|
|
66378
66453
|
let newlineIndex;
|
|
@@ -66395,7 +66470,7 @@ var SessionObserver = class {
|
|
|
66395
66470
|
}
|
|
66396
66471
|
}
|
|
66397
66472
|
} finally {
|
|
66398
|
-
|
|
66473
|
+
import_node_fs45.default.closeSync(fd);
|
|
66399
66474
|
}
|
|
66400
66475
|
if (w3.pendingCwdDerive) this.maybeDeriveCwd(w3);
|
|
66401
66476
|
}
|
|
@@ -66407,7 +66482,7 @@ var SessionObserver = class {
|
|
|
66407
66482
|
const now = Date.now();
|
|
66408
66483
|
if (now - w3.lastRelocateScanMs < 1e3) return;
|
|
66409
66484
|
w3.lastRelocateScanMs = now;
|
|
66410
|
-
const projectsRoot =
|
|
66485
|
+
const projectsRoot = import_node_path49.default.join(this.home, ".claude", "projects");
|
|
66411
66486
|
const found = findTranscriptByToolSessionId(projectsRoot, w3.toolSessionId);
|
|
66412
66487
|
if (!found || found === w3.filePath) return;
|
|
66413
66488
|
try {
|
|
@@ -66416,7 +66491,7 @@ var SessionObserver = class {
|
|
|
66416
66491
|
}
|
|
66417
66492
|
w3.filePath = found;
|
|
66418
66493
|
try {
|
|
66419
|
-
w3.watcher =
|
|
66494
|
+
w3.watcher = import_node_fs45.default.watch(import_node_path49.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
66420
66495
|
if (!changedName || !w3.filePath.endsWith(changedName)) return;
|
|
66421
66496
|
this.poll(w3);
|
|
66422
66497
|
});
|
|
@@ -66538,9 +66613,9 @@ function listRegistered() {
|
|
|
66538
66613
|
// src/tools/title-generator.ts
|
|
66539
66614
|
var import_node_child_process13 = require("child_process");
|
|
66540
66615
|
init_protocol();
|
|
66541
|
-
var
|
|
66542
|
-
var
|
|
66543
|
-
var
|
|
66616
|
+
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
66617
|
+
var import_node_os19 = __toESM(require("os"), 1);
|
|
66618
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
66544
66619
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
66545
66620
|
var TITLE_INPUT_MAX_CHARS = 400;
|
|
66546
66621
|
var DEFAULT_TITLE_GEN_TIMEOUT_MS = 45e3;
|
|
@@ -66631,21 +66706,21 @@ async function generateSessionTitle(file, firstMessage, deps = {}) {
|
|
|
66631
66706
|
}
|
|
66632
66707
|
let workDir;
|
|
66633
66708
|
try {
|
|
66634
|
-
workDir =
|
|
66709
|
+
workDir = import_node_fs46.default.mkdtempSync(import_node_path50.default.join(import_node_os19.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
66635
66710
|
} catch {
|
|
66636
66711
|
return null;
|
|
66637
66712
|
}
|
|
66638
66713
|
const cleanupWorkDir = () => {
|
|
66639
66714
|
try {
|
|
66640
|
-
|
|
66715
|
+
import_node_fs46.default.rmSync(workDir, { recursive: true, force: true });
|
|
66641
66716
|
} catch {
|
|
66642
66717
|
}
|
|
66643
66718
|
};
|
|
66644
|
-
const outFile =
|
|
66645
|
-
const schemaFile =
|
|
66719
|
+
const outFile = import_node_path50.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
66720
|
+
const schemaFile = import_node_path50.default.join(workDir, "title-schema.json");
|
|
66646
66721
|
if (tool === "codex") {
|
|
66647
66722
|
try {
|
|
66648
|
-
|
|
66723
|
+
import_node_fs46.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
66649
66724
|
} catch {
|
|
66650
66725
|
cleanupWorkDir();
|
|
66651
66726
|
return null;
|
|
@@ -66700,7 +66775,7 @@ async function generateSessionTitle(file, firstMessage, deps = {}) {
|
|
|
66700
66775
|
if (tool === "claude" || tool === "pi") return finish(parseTitleJson(stdout));
|
|
66701
66776
|
let fileText = "";
|
|
66702
66777
|
try {
|
|
66703
|
-
fileText =
|
|
66778
|
+
fileText = import_node_fs46.default.readFileSync(outFile, "utf8");
|
|
66704
66779
|
} catch {
|
|
66705
66780
|
return finish(null);
|
|
66706
66781
|
}
|
|
@@ -67396,8 +67471,8 @@ async function authenticate(token, deps) {
|
|
|
67396
67471
|
}
|
|
67397
67472
|
|
|
67398
67473
|
// src/legacy-cleanup.ts
|
|
67399
|
-
var
|
|
67400
|
-
var
|
|
67474
|
+
var fs57 = __toESM(require("fs/promises"), 1);
|
|
67475
|
+
var path58 = __toESM(require("path"), 1);
|
|
67401
67476
|
var LEGACY_FILES = [
|
|
67402
67477
|
"personal-capability.json",
|
|
67403
67478
|
"received-capabilities.json",
|
|
@@ -67406,9 +67481,9 @@ var LEGACY_FILES = [
|
|
|
67406
67481
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
67407
67482
|
const removed = [];
|
|
67408
67483
|
for (const name of LEGACY_FILES) {
|
|
67409
|
-
const p3 =
|
|
67484
|
+
const p3 = path58.join(dataDir, name);
|
|
67410
67485
|
try {
|
|
67411
|
-
await
|
|
67486
|
+
await fs57.unlink(p3);
|
|
67412
67487
|
removed.push(name);
|
|
67413
67488
|
logger.debug("legacy capability file removed", { file: name });
|
|
67414
67489
|
} catch (err) {
|
|
@@ -67420,13 +67495,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
67420
67495
|
}
|
|
67421
67496
|
|
|
67422
67497
|
// src/inbox/inbox-store.ts
|
|
67423
|
-
var
|
|
67424
|
-
var
|
|
67498
|
+
var fs58 = __toESM(require("fs"), 1);
|
|
67499
|
+
var path59 = __toESM(require("path"), 1);
|
|
67425
67500
|
var INBOX_SUBDIR = "inbox";
|
|
67426
67501
|
var InboxStore = class {
|
|
67427
67502
|
constructor(dataDir) {
|
|
67428
67503
|
this.dataDir = dataDir;
|
|
67429
|
-
|
|
67504
|
+
fs58.mkdirSync(this.dirPath(), { recursive: true });
|
|
67430
67505
|
}
|
|
67431
67506
|
dataDir;
|
|
67432
67507
|
/**
|
|
@@ -67438,7 +67513,7 @@ var InboxStore = class {
|
|
|
67438
67513
|
const file = this.filePath(peerDeviceId);
|
|
67439
67514
|
let raw;
|
|
67440
67515
|
try {
|
|
67441
|
-
raw =
|
|
67516
|
+
raw = fs58.readFileSync(file, "utf8");
|
|
67442
67517
|
} catch (err) {
|
|
67443
67518
|
if (err?.code === "ENOENT") return [];
|
|
67444
67519
|
return [];
|
|
@@ -67454,7 +67529,7 @@ var InboxStore = class {
|
|
|
67454
67529
|
const dir = this.dirPath();
|
|
67455
67530
|
let entries;
|
|
67456
67531
|
try {
|
|
67457
|
-
entries =
|
|
67532
|
+
entries = fs58.readdirSync(dir);
|
|
67458
67533
|
} catch (err) {
|
|
67459
67534
|
if (err?.code === "ENOENT") return [];
|
|
67460
67535
|
return [];
|
|
@@ -67470,9 +67545,9 @@ var InboxStore = class {
|
|
|
67470
67545
|
if (existing.some((m3) => m3.id === message.id)) return;
|
|
67471
67546
|
const file = this.filePath(message.peerDeviceId);
|
|
67472
67547
|
const line = JSON.stringify(message) + "\n";
|
|
67473
|
-
|
|
67548
|
+
fs58.appendFileSync(file, line, { mode: 384 });
|
|
67474
67549
|
try {
|
|
67475
|
-
|
|
67550
|
+
fs58.chmodSync(file, 384);
|
|
67476
67551
|
} catch {
|
|
67477
67552
|
}
|
|
67478
67553
|
}
|
|
@@ -67502,7 +67577,7 @@ var InboxStore = class {
|
|
|
67502
67577
|
removeByPeerDeviceId(peerDeviceId) {
|
|
67503
67578
|
const file = this.filePath(peerDeviceId);
|
|
67504
67579
|
try {
|
|
67505
|
-
|
|
67580
|
+
fs58.unlinkSync(file);
|
|
67506
67581
|
} catch (err) {
|
|
67507
67582
|
if (err?.code === "ENOENT") return;
|
|
67508
67583
|
}
|
|
@@ -67511,18 +67586,18 @@ var InboxStore = class {
|
|
|
67511
67586
|
const file = this.filePath(peerDeviceId);
|
|
67512
67587
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
67513
67588
|
const content = messages.map((m3) => JSON.stringify(m3)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
67514
|
-
|
|
67515
|
-
|
|
67589
|
+
fs58.writeFileSync(tmp, content, { mode: 384 });
|
|
67590
|
+
fs58.renameSync(tmp, file);
|
|
67516
67591
|
try {
|
|
67517
|
-
|
|
67592
|
+
fs58.chmodSync(file, 384);
|
|
67518
67593
|
} catch {
|
|
67519
67594
|
}
|
|
67520
67595
|
}
|
|
67521
67596
|
dirPath() {
|
|
67522
|
-
return
|
|
67597
|
+
return path59.join(this.dataDir, INBOX_SUBDIR);
|
|
67523
67598
|
}
|
|
67524
67599
|
filePath(peerDeviceId) {
|
|
67525
|
-
return
|
|
67600
|
+
return path59.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
67526
67601
|
}
|
|
67527
67602
|
};
|
|
67528
67603
|
function parseAllLines(raw) {
|
|
@@ -67610,8 +67685,8 @@ var InboxManager = class {
|
|
|
67610
67685
|
};
|
|
67611
67686
|
|
|
67612
67687
|
// src/state/contact-store.ts
|
|
67613
|
-
var
|
|
67614
|
-
var
|
|
67688
|
+
var fs59 = __toESM(require("fs"), 1);
|
|
67689
|
+
var path60 = __toESM(require("path"), 1);
|
|
67615
67690
|
var FILE_NAME = "contacts.json";
|
|
67616
67691
|
var ContactStore = class {
|
|
67617
67692
|
constructor(dataDir) {
|
|
@@ -67621,10 +67696,10 @@ var ContactStore = class {
|
|
|
67621
67696
|
contacts = /* @__PURE__ */ new Map();
|
|
67622
67697
|
load() {
|
|
67623
67698
|
this.contacts.clear();
|
|
67624
|
-
const file =
|
|
67699
|
+
const file = path60.join(this.dataDir, FILE_NAME);
|
|
67625
67700
|
let raw;
|
|
67626
67701
|
try {
|
|
67627
|
-
raw =
|
|
67702
|
+
raw = fs59.readFileSync(file, "utf8");
|
|
67628
67703
|
} catch (err) {
|
|
67629
67704
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
67630
67705
|
return;
|
|
@@ -67705,20 +67780,20 @@ var ContactStore = class {
|
|
|
67705
67780
|
return true;
|
|
67706
67781
|
}
|
|
67707
67782
|
flush() {
|
|
67708
|
-
const file =
|
|
67783
|
+
const file = path60.join(this.dataDir, FILE_NAME);
|
|
67709
67784
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
67710
67785
|
const content = JSON.stringify(
|
|
67711
67786
|
{ contacts: Array.from(this.contacts.values()) },
|
|
67712
67787
|
null,
|
|
67713
67788
|
2
|
|
67714
67789
|
);
|
|
67715
|
-
|
|
67716
|
-
|
|
67717
|
-
|
|
67790
|
+
fs59.mkdirSync(this.dataDir, { recursive: true });
|
|
67791
|
+
fs59.writeFileSync(tmp, content, { mode: 384 });
|
|
67792
|
+
fs59.renameSync(tmp, file);
|
|
67718
67793
|
}
|
|
67719
67794
|
renameBak(file) {
|
|
67720
67795
|
try {
|
|
67721
|
-
|
|
67796
|
+
fs59.renameSync(file, `${file}.bak`);
|
|
67722
67797
|
} catch {
|
|
67723
67798
|
}
|
|
67724
67799
|
}
|
|
@@ -67826,61 +67901,61 @@ async function connectRemote(args) {
|
|
|
67826
67901
|
}
|
|
67827
67902
|
|
|
67828
67903
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
67829
|
-
var
|
|
67830
|
-
var
|
|
67904
|
+
var fs60 = __toESM(require("fs"), 1);
|
|
67905
|
+
var path61 = __toESM(require("path"), 1);
|
|
67831
67906
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
67832
67907
|
function migrateFlattenSessions(opts) {
|
|
67833
67908
|
const dataDir = opts.dataDir;
|
|
67834
67909
|
const now = opts.now ?? Date.now;
|
|
67835
|
-
const sessionsDir =
|
|
67836
|
-
const flagPath =
|
|
67910
|
+
const sessionsDir = path61.join(dataDir, "sessions");
|
|
67911
|
+
const flagPath = path61.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
67837
67912
|
if (existsSync3(flagPath)) {
|
|
67838
67913
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
67839
67914
|
}
|
|
67840
67915
|
let movedBare = 0;
|
|
67841
67916
|
let movedVmOwner = 0;
|
|
67842
67917
|
let archivedListener = 0;
|
|
67843
|
-
const defaultDir =
|
|
67918
|
+
const defaultDir = path61.join(sessionsDir, "default");
|
|
67844
67919
|
if (existsSync3(defaultDir)) {
|
|
67845
67920
|
for (const entry of readdirSafe(defaultDir)) {
|
|
67846
67921
|
if (!entry.endsWith(".json")) continue;
|
|
67847
|
-
const src =
|
|
67848
|
-
const dst =
|
|
67849
|
-
|
|
67922
|
+
const src = path61.join(defaultDir, entry);
|
|
67923
|
+
const dst = path61.join(sessionsDir, entry);
|
|
67924
|
+
fs60.renameSync(src, dst);
|
|
67850
67925
|
movedBare += 1;
|
|
67851
67926
|
}
|
|
67852
67927
|
rmdirIfEmpty(defaultDir);
|
|
67853
67928
|
}
|
|
67854
67929
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
67855
|
-
const personaDir =
|
|
67930
|
+
const personaDir = path61.join(sessionsDir, pid);
|
|
67856
67931
|
if (!isDir(personaDir)) continue;
|
|
67857
67932
|
if (pid === "default") continue;
|
|
67858
|
-
const ownerSrc =
|
|
67933
|
+
const ownerSrc = path61.join(personaDir, "owner");
|
|
67859
67934
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
67860
|
-
const ownerDst =
|
|
67861
|
-
|
|
67935
|
+
const ownerDst = path61.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
67936
|
+
fs60.mkdirSync(ownerDst, { recursive: true });
|
|
67862
67937
|
for (const file of readdirSafe(ownerSrc)) {
|
|
67863
67938
|
if (!file.endsWith(".json")) continue;
|
|
67864
|
-
|
|
67939
|
+
fs60.renameSync(path61.join(ownerSrc, file), path61.join(ownerDst, file));
|
|
67865
67940
|
movedVmOwner += 1;
|
|
67866
67941
|
}
|
|
67867
67942
|
rmdirIfEmpty(ownerSrc);
|
|
67868
67943
|
}
|
|
67869
|
-
const listenerSrc =
|
|
67944
|
+
const listenerSrc = path61.join(personaDir, "listener");
|
|
67870
67945
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
67871
|
-
const archiveDst =
|
|
67872
|
-
|
|
67946
|
+
const archiveDst = path61.join(dataDir, ".legacy", `listener-${pid}`);
|
|
67947
|
+
fs60.mkdirSync(archiveDst, { recursive: true });
|
|
67873
67948
|
for (const file of readdirSafe(listenerSrc)) {
|
|
67874
67949
|
if (!file.endsWith(".json")) continue;
|
|
67875
|
-
|
|
67950
|
+
fs60.renameSync(path61.join(listenerSrc, file), path61.join(archiveDst, file));
|
|
67876
67951
|
archivedListener += 1;
|
|
67877
67952
|
}
|
|
67878
67953
|
rmdirIfEmpty(listenerSrc);
|
|
67879
67954
|
}
|
|
67880
67955
|
rmdirIfEmpty(personaDir);
|
|
67881
67956
|
}
|
|
67882
|
-
|
|
67883
|
-
|
|
67957
|
+
fs60.mkdirSync(sessionsDir, { recursive: true });
|
|
67958
|
+
fs60.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
67884
67959
|
return {
|
|
67885
67960
|
skipped: false,
|
|
67886
67961
|
flagWritten: true,
|
|
@@ -67891,7 +67966,7 @@ function migrateFlattenSessions(opts) {
|
|
|
67891
67966
|
}
|
|
67892
67967
|
function existsSync3(p3) {
|
|
67893
67968
|
try {
|
|
67894
|
-
|
|
67969
|
+
fs60.statSync(p3);
|
|
67895
67970
|
return true;
|
|
67896
67971
|
} catch {
|
|
67897
67972
|
return false;
|
|
@@ -67899,62 +67974,62 @@ function existsSync3(p3) {
|
|
|
67899
67974
|
}
|
|
67900
67975
|
function isDir(p3) {
|
|
67901
67976
|
try {
|
|
67902
|
-
return
|
|
67977
|
+
return fs60.statSync(p3).isDirectory();
|
|
67903
67978
|
} catch {
|
|
67904
67979
|
return false;
|
|
67905
67980
|
}
|
|
67906
67981
|
}
|
|
67907
67982
|
function readdirSafe(p3) {
|
|
67908
67983
|
try {
|
|
67909
|
-
return
|
|
67984
|
+
return fs60.readdirSync(p3);
|
|
67910
67985
|
} catch {
|
|
67911
67986
|
return [];
|
|
67912
67987
|
}
|
|
67913
67988
|
}
|
|
67914
67989
|
function rmdirIfEmpty(p3) {
|
|
67915
67990
|
try {
|
|
67916
|
-
|
|
67991
|
+
fs60.rmdirSync(p3);
|
|
67917
67992
|
} catch {
|
|
67918
67993
|
}
|
|
67919
67994
|
}
|
|
67920
67995
|
|
|
67921
67996
|
// src/migrations/2026-08-18-drop-seeded-projects.ts
|
|
67922
|
-
var
|
|
67923
|
-
var
|
|
67997
|
+
var fs61 = __toESM(require("fs"), 1);
|
|
67998
|
+
var path62 = __toESM(require("path"), 1);
|
|
67924
67999
|
var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
|
|
67925
68000
|
function dropSeededProjects(opts) {
|
|
67926
|
-
|
|
67927
|
-
const flag =
|
|
67928
|
-
if (
|
|
67929
|
-
const file =
|
|
68001
|
+
fs61.mkdirSync(opts.dataDir, { recursive: true });
|
|
68002
|
+
const flag = path62.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
|
|
68003
|
+
if (fs61.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
|
|
68004
|
+
const file = path62.join(opts.dataDir, "projects.json");
|
|
67930
68005
|
let raw = null;
|
|
67931
68006
|
let dropped = 0;
|
|
67932
68007
|
try {
|
|
67933
|
-
raw =
|
|
68008
|
+
raw = fs61.readFileSync(file, "utf8");
|
|
67934
68009
|
dropped = JSON.parse(raw).projects?.length ?? 0;
|
|
67935
68010
|
} catch {
|
|
67936
68011
|
}
|
|
67937
68012
|
let backup = null;
|
|
67938
68013
|
if (raw != null && dropped > 0) {
|
|
67939
|
-
const dir =
|
|
67940
|
-
|
|
67941
|
-
backup =
|
|
67942
|
-
|
|
68014
|
+
const dir = path62.join(opts.dataDir, "backups");
|
|
68015
|
+
fs61.mkdirSync(dir, { recursive: true });
|
|
68016
|
+
backup = path62.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
|
|
68017
|
+
fs61.writeFileSync(backup, raw);
|
|
67943
68018
|
}
|
|
67944
68019
|
if (raw != null || dropped > 0) {
|
|
67945
|
-
|
|
68020
|
+
fs61.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
|
|
67946
68021
|
}
|
|
67947
|
-
|
|
68022
|
+
fs61.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
|
|
67948
68023
|
return { skipped: false, dropped, backup };
|
|
67949
68024
|
}
|
|
67950
68025
|
|
|
67951
68026
|
// src/transport/http-router.ts
|
|
67952
|
-
var
|
|
67953
|
-
var
|
|
68027
|
+
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
68028
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
67954
68029
|
|
|
67955
68030
|
// src/attachment/upload.ts
|
|
67956
|
-
var
|
|
67957
|
-
var
|
|
68031
|
+
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
68032
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
67958
68033
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
67959
68034
|
var import_promises8 = require("stream/promises");
|
|
67960
68035
|
var UploadError = class extends Error {
|
|
@@ -67966,22 +68041,22 @@ var UploadError = class extends Error {
|
|
|
67966
68041
|
code;
|
|
67967
68042
|
};
|
|
67968
68043
|
function assertValidFileName(fileName) {
|
|
67969
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
68044
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path51.default.basename(fileName)) {
|
|
67970
68045
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
67971
68046
|
}
|
|
67972
68047
|
}
|
|
67973
68048
|
var HASH_PREFIX_LEN = 16;
|
|
67974
68049
|
async function writeUploadedAttachment(args) {
|
|
67975
68050
|
assertValidFileName(args.fileName);
|
|
67976
|
-
const attachmentsRoot =
|
|
68051
|
+
const attachmentsRoot = import_node_path51.default.join(args.baseDir, ".attachments");
|
|
67977
68052
|
try {
|
|
67978
|
-
|
|
68053
|
+
import_node_fs47.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
67979
68054
|
} catch (err) {
|
|
67980
68055
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
67981
68056
|
}
|
|
67982
68057
|
const hasher = import_node_crypto15.default.createHash("sha256");
|
|
67983
68058
|
let actualSize = 0;
|
|
67984
|
-
const tmpPath =
|
|
68059
|
+
const tmpPath = import_node_path51.default.join(
|
|
67985
68060
|
attachmentsRoot,
|
|
67986
68061
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto15.default.randomBytes(4).toString("hex")}`
|
|
67987
68062
|
);
|
|
@@ -67996,18 +68071,18 @@ async function writeUploadedAttachment(args) {
|
|
|
67996
68071
|
yield buf;
|
|
67997
68072
|
}
|
|
67998
68073
|
},
|
|
67999
|
-
|
|
68074
|
+
import_node_fs47.default.createWriteStream(tmpPath, { mode: 384 })
|
|
68000
68075
|
);
|
|
68001
68076
|
} catch (err) {
|
|
68002
68077
|
try {
|
|
68003
|
-
|
|
68078
|
+
import_node_fs47.default.unlinkSync(tmpPath);
|
|
68004
68079
|
} catch {
|
|
68005
68080
|
}
|
|
68006
68081
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
68007
68082
|
}
|
|
68008
68083
|
if (actualSize !== args.contentLength) {
|
|
68009
68084
|
try {
|
|
68010
|
-
|
|
68085
|
+
import_node_fs47.default.unlinkSync(tmpPath);
|
|
68011
68086
|
} catch {
|
|
68012
68087
|
}
|
|
68013
68088
|
throw new UploadError(
|
|
@@ -68016,34 +68091,34 @@ async function writeUploadedAttachment(args) {
|
|
|
68016
68091
|
);
|
|
68017
68092
|
}
|
|
68018
68093
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
68019
|
-
const hashDir =
|
|
68094
|
+
const hashDir = import_node_path51.default.join(attachmentsRoot, attachmentId);
|
|
68020
68095
|
let finalFileName;
|
|
68021
68096
|
let hashDirExists = false;
|
|
68022
68097
|
try {
|
|
68023
|
-
hashDirExists =
|
|
68098
|
+
hashDirExists = import_node_fs47.default.statSync(hashDir).isDirectory();
|
|
68024
68099
|
} catch {
|
|
68025
68100
|
}
|
|
68026
68101
|
if (hashDirExists) {
|
|
68027
|
-
const existing =
|
|
68102
|
+
const existing = import_node_fs47.default.readdirSync(hashDir).filter((n2) => !n2.startsWith("."));
|
|
68028
68103
|
finalFileName = existing[0] ?? args.fileName;
|
|
68029
68104
|
try {
|
|
68030
|
-
|
|
68105
|
+
import_node_fs47.default.unlinkSync(tmpPath);
|
|
68031
68106
|
} catch {
|
|
68032
68107
|
}
|
|
68033
68108
|
} else {
|
|
68034
68109
|
try {
|
|
68035
|
-
|
|
68110
|
+
import_node_fs47.default.mkdirSync(hashDir, { recursive: true });
|
|
68036
68111
|
finalFileName = args.fileName;
|
|
68037
|
-
|
|
68112
|
+
import_node_fs47.default.renameSync(tmpPath, import_node_path51.default.join(hashDir, finalFileName));
|
|
68038
68113
|
} catch (err) {
|
|
68039
68114
|
try {
|
|
68040
|
-
|
|
68115
|
+
import_node_fs47.default.unlinkSync(tmpPath);
|
|
68041
68116
|
} catch {
|
|
68042
68117
|
}
|
|
68043
68118
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
68044
68119
|
}
|
|
68045
68120
|
}
|
|
68046
|
-
const absPath =
|
|
68121
|
+
const absPath = import_node_path51.default.join(hashDir, finalFileName);
|
|
68047
68122
|
const relPath = absPath;
|
|
68048
68123
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
68049
68124
|
relPath: absPath,
|
|
@@ -68058,8 +68133,8 @@ async function writeUploadedAttachment(args) {
|
|
|
68058
68133
|
|
|
68059
68134
|
// src/extension/import.ts
|
|
68060
68135
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
68061
|
-
var
|
|
68062
|
-
var
|
|
68136
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
68137
|
+
var import_node_os20 = __toESM(require("os"), 1);
|
|
68063
68138
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
68064
68139
|
var ImportError = class extends Error {
|
|
68065
68140
|
constructor(code, message) {
|
|
@@ -68076,7 +68151,7 @@ async function importZip(buf, root) {
|
|
|
68076
68151
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
68077
68152
|
}
|
|
68078
68153
|
for (const name of Object.keys(zip.files)) {
|
|
68079
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
68154
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path52.default.isAbsolute(name)) {
|
|
68080
68155
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
68081
68156
|
}
|
|
68082
68157
|
}
|
|
@@ -68109,7 +68184,7 @@ async function importZip(buf, root) {
|
|
|
68109
68184
|
);
|
|
68110
68185
|
}
|
|
68111
68186
|
}
|
|
68112
|
-
const destDir =
|
|
68187
|
+
const destDir = import_node_path52.default.join(root, manifest.id);
|
|
68113
68188
|
let destExists = false;
|
|
68114
68189
|
try {
|
|
68115
68190
|
await import_promises9.default.access(destDir);
|
|
@@ -68119,15 +68194,15 @@ async function importZip(buf, root) {
|
|
|
68119
68194
|
if (destExists) {
|
|
68120
68195
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
68121
68196
|
}
|
|
68122
|
-
const stage = await import_promises9.default.mkdtemp(
|
|
68197
|
+
const stage = await import_promises9.default.mkdtemp(import_node_path52.default.join(import_node_os20.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
68123
68198
|
try {
|
|
68124
68199
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
68125
|
-
const dest =
|
|
68200
|
+
const dest = import_node_path52.default.join(stage, name);
|
|
68126
68201
|
if (entry.dir) {
|
|
68127
68202
|
await import_promises9.default.mkdir(dest, { recursive: true });
|
|
68128
68203
|
continue;
|
|
68129
68204
|
}
|
|
68130
|
-
await import_promises9.default.mkdir(
|
|
68205
|
+
await import_promises9.default.mkdir(import_node_path52.default.dirname(dest), { recursive: true });
|
|
68131
68206
|
const content = await entry.async("nodebuffer");
|
|
68132
68207
|
await import_promises9.default.writeFile(dest, content);
|
|
68133
68208
|
}
|
|
@@ -68181,7 +68256,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
68181
68256
|
".wasm": "application/wasm"
|
|
68182
68257
|
};
|
|
68183
68258
|
function shareUiAssetMime(filePath) {
|
|
68184
|
-
const ext =
|
|
68259
|
+
const ext = import_node_path53.default.extname(filePath).toLowerCase();
|
|
68185
68260
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
68186
68261
|
}
|
|
68187
68262
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -68280,7 +68355,7 @@ function isValidUploadFileName(fileName) {
|
|
|
68280
68355
|
if (fileName === "." || fileName === "..") return false;
|
|
68281
68356
|
if (fileName.startsWith(".")) return false;
|
|
68282
68357
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
68283
|
-
return fileName ===
|
|
68358
|
+
return fileName === import_node_path53.default.basename(fileName);
|
|
68284
68359
|
}
|
|
68285
68360
|
function createHttpRouter(deps) {
|
|
68286
68361
|
return async (req, res) => {
|
|
@@ -68364,7 +68439,7 @@ function createHttpRouter(deps) {
|
|
|
68364
68439
|
}
|
|
68365
68440
|
let buf;
|
|
68366
68441
|
try {
|
|
68367
|
-
buf = await
|
|
68442
|
+
buf = await import_node_fs48.default.promises.readFile(abs);
|
|
68368
68443
|
} catch {
|
|
68369
68444
|
sendJson2(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
68370
68445
|
return true;
|
|
@@ -68510,7 +68585,7 @@ function createHttpRouter(deps) {
|
|
|
68510
68585
|
sendHtml(res, statusByCode[r2.code], loader.renderErrorHtml(r2.code, msgByCode[r2.code]));
|
|
68511
68586
|
return true;
|
|
68512
68587
|
}
|
|
68513
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
68588
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path53.default.basename(r2.absPath)));
|
|
68514
68589
|
return true;
|
|
68515
68590
|
}
|
|
68516
68591
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -68631,7 +68706,7 @@ function createHttpRouter(deps) {
|
|
|
68631
68706
|
return true;
|
|
68632
68707
|
}
|
|
68633
68708
|
let absPath;
|
|
68634
|
-
if (
|
|
68709
|
+
if (import_node_path53.default.isAbsolute(pathParam)) {
|
|
68635
68710
|
absPath = pathParam;
|
|
68636
68711
|
} else if (deps.sessionStore) {
|
|
68637
68712
|
const file = deps.sessionStore.read(sid);
|
|
@@ -68639,7 +68714,7 @@ function createHttpRouter(deps) {
|
|
|
68639
68714
|
sendJson2(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
68640
68715
|
return true;
|
|
68641
68716
|
}
|
|
68642
|
-
absPath =
|
|
68717
|
+
absPath = import_node_path53.default.join(file.cwd, pathParam);
|
|
68643
68718
|
} else {
|
|
68644
68719
|
sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
68645
68720
|
return true;
|
|
@@ -68723,7 +68798,7 @@ function withCtx(ctx, body) {
|
|
|
68723
68798
|
function streamFile(res, absPath, logger) {
|
|
68724
68799
|
let stat;
|
|
68725
68800
|
try {
|
|
68726
|
-
stat =
|
|
68801
|
+
stat = import_node_fs48.default.statSync(absPath);
|
|
68727
68802
|
} catch (err) {
|
|
68728
68803
|
const code = err?.code;
|
|
68729
68804
|
if (code === "ENOENT") {
|
|
@@ -68738,7 +68813,7 @@ function streamFile(res, absPath, logger) {
|
|
|
68738
68813
|
return;
|
|
68739
68814
|
}
|
|
68740
68815
|
const mime = lookupMime(absPath);
|
|
68741
|
-
const basename2 =
|
|
68816
|
+
const basename2 = import_node_path53.default.basename(absPath);
|
|
68742
68817
|
res.writeHead(200, {
|
|
68743
68818
|
"Content-Type": mime,
|
|
68744
68819
|
"Content-Length": String(stat.size),
|
|
@@ -68746,7 +68821,7 @@ function streamFile(res, absPath, logger) {
|
|
|
68746
68821
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
68747
68822
|
"X-Content-Type-Options": "nosniff"
|
|
68748
68823
|
});
|
|
68749
|
-
const stream =
|
|
68824
|
+
const stream = import_node_fs48.default.createReadStream(absPath);
|
|
68750
68825
|
stream.on("error", (err) => {
|
|
68751
68826
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
68752
68827
|
res.destroy();
|
|
@@ -68755,8 +68830,8 @@ function streamFile(res, absPath, logger) {
|
|
|
68755
68830
|
}
|
|
68756
68831
|
|
|
68757
68832
|
// src/attachment/gc.ts
|
|
68758
|
-
var
|
|
68759
|
-
var
|
|
68833
|
+
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
68834
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
68760
68835
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
68761
68836
|
function runAttachmentGc(args) {
|
|
68762
68837
|
const now = (args.now ?? Date.now)();
|
|
@@ -68765,12 +68840,12 @@ function runAttachmentGc(args) {
|
|
|
68765
68840
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
68766
68841
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
68767
68842
|
if (entry.stale) continue;
|
|
68768
|
-
if (
|
|
68843
|
+
if (import_node_path54.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
68769
68844
|
}
|
|
68770
68845
|
}
|
|
68771
68846
|
const visited = /* @__PURE__ */ new Set();
|
|
68772
68847
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
68773
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
68848
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path54.default.join(
|
|
68774
68849
|
args.dataDir,
|
|
68775
68850
|
"sessions",
|
|
68776
68851
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -68783,28 +68858,28 @@ function runAttachmentGc(args) {
|
|
|
68783
68858
|
return true;
|
|
68784
68859
|
});
|
|
68785
68860
|
for (const rootDir of roots) {
|
|
68786
|
-
const attRoot =
|
|
68861
|
+
const attRoot = import_node_path54.default.join(rootDir, ".attachments");
|
|
68787
68862
|
let hashDirs;
|
|
68788
68863
|
try {
|
|
68789
|
-
hashDirs =
|
|
68864
|
+
hashDirs = import_node_fs49.default.readdirSync(attRoot);
|
|
68790
68865
|
} catch (err) {
|
|
68791
68866
|
if (err.code === "ENOENT") continue;
|
|
68792
68867
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
68793
68868
|
continue;
|
|
68794
68869
|
}
|
|
68795
68870
|
for (const hashDir of hashDirs) {
|
|
68796
|
-
const hashDirAbs =
|
|
68871
|
+
const hashDirAbs = import_node_path54.default.join(attRoot, hashDir);
|
|
68797
68872
|
let files;
|
|
68798
68873
|
try {
|
|
68799
|
-
files =
|
|
68874
|
+
files = import_node_fs49.default.readdirSync(hashDirAbs);
|
|
68800
68875
|
} catch {
|
|
68801
68876
|
continue;
|
|
68802
68877
|
}
|
|
68803
68878
|
for (const name of files) {
|
|
68804
|
-
const file =
|
|
68879
|
+
const file = import_node_path54.default.join(hashDirAbs, name);
|
|
68805
68880
|
let stat;
|
|
68806
68881
|
try {
|
|
68807
|
-
stat =
|
|
68882
|
+
stat = import_node_fs49.default.statSync(file);
|
|
68808
68883
|
} catch {
|
|
68809
68884
|
continue;
|
|
68810
68885
|
}
|
|
@@ -68813,18 +68888,18 @@ function runAttachmentGc(args) {
|
|
|
68813
68888
|
if (age < ttlMs) continue;
|
|
68814
68889
|
if (liveAbs.has(file)) continue;
|
|
68815
68890
|
try {
|
|
68816
|
-
|
|
68891
|
+
import_node_fs49.default.unlinkSync(file);
|
|
68817
68892
|
} catch (err) {
|
|
68818
68893
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
68819
68894
|
}
|
|
68820
68895
|
}
|
|
68821
68896
|
try {
|
|
68822
|
-
if (
|
|
68897
|
+
if (import_node_fs49.default.readdirSync(hashDirAbs).length === 0) import_node_fs49.default.rmdirSync(hashDirAbs);
|
|
68823
68898
|
} catch {
|
|
68824
68899
|
}
|
|
68825
68900
|
}
|
|
68826
68901
|
try {
|
|
68827
|
-
if (
|
|
68902
|
+
if (import_node_fs49.default.readdirSync(attRoot).length === 0) import_node_fs49.default.rmdirSync(attRoot);
|
|
68828
68903
|
} catch {
|
|
68829
68904
|
}
|
|
68830
68905
|
}
|
|
@@ -68832,8 +68907,8 @@ function runAttachmentGc(args) {
|
|
|
68832
68907
|
}
|
|
68833
68908
|
|
|
68834
68909
|
// src/attachment/group.ts
|
|
68835
|
-
var
|
|
68836
|
-
var
|
|
68910
|
+
var import_node_fs50 = __toESM(require("fs"), 1);
|
|
68911
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
68837
68912
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
68838
68913
|
init_protocol();
|
|
68839
68914
|
var GroupFileStore = class {
|
|
@@ -68845,11 +68920,11 @@ var GroupFileStore = class {
|
|
|
68845
68920
|
this.logger = opts.logger;
|
|
68846
68921
|
}
|
|
68847
68922
|
rootForScope(scope) {
|
|
68848
|
-
return
|
|
68923
|
+
return import_node_path55.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
68849
68924
|
}
|
|
68850
68925
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
68851
68926
|
filePath(scope, sessionId) {
|
|
68852
|
-
return
|
|
68927
|
+
return import_node_path55.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
68853
68928
|
}
|
|
68854
68929
|
cacheKey(scope, sessionId) {
|
|
68855
68930
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -68858,7 +68933,7 @@ var GroupFileStore = class {
|
|
|
68858
68933
|
readFile(scope, sessionId) {
|
|
68859
68934
|
const file = this.filePath(scope, sessionId);
|
|
68860
68935
|
try {
|
|
68861
|
-
const raw =
|
|
68936
|
+
const raw = import_node_fs50.default.readFileSync(file, "utf8");
|
|
68862
68937
|
const parsed = JSON.parse(raw);
|
|
68863
68938
|
if (!Array.isArray(parsed)) {
|
|
68864
68939
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -68884,10 +68959,10 @@ var GroupFileStore = class {
|
|
|
68884
68959
|
}
|
|
68885
68960
|
writeFile(scope, sessionId, entries) {
|
|
68886
68961
|
const file = this.filePath(scope, sessionId);
|
|
68887
|
-
|
|
68962
|
+
import_node_fs50.default.mkdirSync(import_node_path55.default.dirname(file), { recursive: true });
|
|
68888
68963
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
68889
|
-
|
|
68890
|
-
|
|
68964
|
+
import_node_fs50.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
68965
|
+
import_node_fs50.default.renameSync(tmp, file);
|
|
68891
68966
|
}
|
|
68892
68967
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
68893
68968
|
list(scope, sessionId) {
|
|
@@ -68979,7 +69054,7 @@ var GroupFileStore = class {
|
|
|
68979
69054
|
*/
|
|
68980
69055
|
deleteSession(scope, sessionId) {
|
|
68981
69056
|
try {
|
|
68982
|
-
|
|
69057
|
+
import_node_fs50.default.unlinkSync(this.filePath(scope, sessionId));
|
|
68983
69058
|
} catch (err) {
|
|
68984
69059
|
if (err?.code !== "ENOENT") throw err;
|
|
68985
69060
|
}
|
|
@@ -68992,7 +69067,7 @@ var GroupFileStore = class {
|
|
|
68992
69067
|
* 不在 persona 目录里(见文件头的路径约定)。没树的 persona 是 noop。
|
|
68993
69068
|
*/
|
|
68994
69069
|
deletePersona(personaId2) {
|
|
68995
|
-
|
|
69070
|
+
import_node_fs50.default.rmSync(import_node_path55.default.join(this.dataDir, "sessions", safeFileName(personaId2)), { recursive: true, force: true });
|
|
68996
69071
|
const prefix = `persona:${personaId2}:`;
|
|
68997
69072
|
for (const key of this.cache.keys()) {
|
|
68998
69073
|
if (key.startsWith(prefix)) this.cache.delete(key);
|
|
@@ -69001,10 +69076,10 @@ var GroupFileStore = class {
|
|
|
69001
69076
|
};
|
|
69002
69077
|
|
|
69003
69078
|
// src/discovery/state-file.ts
|
|
69004
|
-
var
|
|
69005
|
-
var
|
|
69079
|
+
var import_node_fs51 = __toESM(require("fs"), 1);
|
|
69080
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
69006
69081
|
function defaultStateFilePath(dataDir) {
|
|
69007
|
-
return
|
|
69082
|
+
return import_node_path56.default.join(dataDir, "state.json");
|
|
69008
69083
|
}
|
|
69009
69084
|
function isPidAlive(pid) {
|
|
69010
69085
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -69026,7 +69101,7 @@ var StateFileManager = class {
|
|
|
69026
69101
|
}
|
|
69027
69102
|
read() {
|
|
69028
69103
|
try {
|
|
69029
|
-
const raw =
|
|
69104
|
+
const raw = import_node_fs51.default.readFileSync(this.file, "utf8");
|
|
69030
69105
|
const parsed = JSON.parse(raw);
|
|
69031
69106
|
return parsed;
|
|
69032
69107
|
} catch {
|
|
@@ -69040,20 +69115,20 @@ var StateFileManager = class {
|
|
|
69040
69115
|
return { status: "stale", existing };
|
|
69041
69116
|
}
|
|
69042
69117
|
write(state) {
|
|
69043
|
-
|
|
69118
|
+
import_node_fs51.default.mkdirSync(import_node_path56.default.dirname(this.file), { recursive: true });
|
|
69044
69119
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
69045
|
-
|
|
69046
|
-
|
|
69120
|
+
import_node_fs51.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
69121
|
+
import_node_fs51.default.renameSync(tmp, this.file);
|
|
69047
69122
|
if (process.platform !== "win32") {
|
|
69048
69123
|
try {
|
|
69049
|
-
|
|
69124
|
+
import_node_fs51.default.chmodSync(this.file, 384);
|
|
69050
69125
|
} catch {
|
|
69051
69126
|
}
|
|
69052
69127
|
}
|
|
69053
69128
|
}
|
|
69054
69129
|
delete() {
|
|
69055
69130
|
try {
|
|
69056
|
-
|
|
69131
|
+
import_node_fs51.default.unlinkSync(this.file);
|
|
69057
69132
|
} catch {
|
|
69058
69133
|
}
|
|
69059
69134
|
}
|
|
@@ -69067,14 +69142,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
69067
69142
|
}
|
|
69068
69143
|
|
|
69069
69144
|
// src/tunnel/tunnel-manager.ts
|
|
69070
|
-
var
|
|
69071
|
-
var
|
|
69145
|
+
var import_node_fs55 = __toESM(require("fs"), 1);
|
|
69146
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
69072
69147
|
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
69073
69148
|
var import_node_child_process16 = require("child_process");
|
|
69074
69149
|
|
|
69075
69150
|
// src/tunnel/tunnel-store.ts
|
|
69076
|
-
var
|
|
69077
|
-
var
|
|
69151
|
+
var import_node_fs52 = __toESM(require("fs"), 1);
|
|
69152
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
69078
69153
|
var TunnelStore = class {
|
|
69079
69154
|
constructor(filePath) {
|
|
69080
69155
|
this.filePath = filePath;
|
|
@@ -69082,7 +69157,7 @@ var TunnelStore = class {
|
|
|
69082
69157
|
filePath;
|
|
69083
69158
|
async get() {
|
|
69084
69159
|
try {
|
|
69085
|
-
const raw = await
|
|
69160
|
+
const raw = await import_node_fs52.default.promises.readFile(this.filePath, "utf8");
|
|
69086
69161
|
const obj = JSON.parse(raw);
|
|
69087
69162
|
if (!isPersistedTunnel(obj)) return null;
|
|
69088
69163
|
return obj;
|
|
@@ -69093,22 +69168,22 @@ var TunnelStore = class {
|
|
|
69093
69168
|
}
|
|
69094
69169
|
}
|
|
69095
69170
|
async set(v3) {
|
|
69096
|
-
const dir =
|
|
69097
|
-
await
|
|
69171
|
+
const dir = import_node_path57.default.dirname(this.filePath);
|
|
69172
|
+
await import_node_fs52.default.promises.mkdir(dir, { recursive: true });
|
|
69098
69173
|
const data = JSON.stringify(v3, null, 2);
|
|
69099
69174
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
69100
|
-
await
|
|
69175
|
+
await import_node_fs52.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
69101
69176
|
if (process.platform !== "win32") {
|
|
69102
69177
|
try {
|
|
69103
|
-
await
|
|
69178
|
+
await import_node_fs52.default.promises.chmod(tmp, 384);
|
|
69104
69179
|
} catch {
|
|
69105
69180
|
}
|
|
69106
69181
|
}
|
|
69107
|
-
await
|
|
69182
|
+
await import_node_fs52.default.promises.rename(tmp, this.filePath);
|
|
69108
69183
|
}
|
|
69109
69184
|
async clear() {
|
|
69110
69185
|
try {
|
|
69111
|
-
await
|
|
69186
|
+
await import_node_fs52.default.promises.unlink(this.filePath);
|
|
69112
69187
|
} catch (err) {
|
|
69113
69188
|
const code = err?.code;
|
|
69114
69189
|
if (code !== "ENOENT") throw err;
|
|
@@ -69203,9 +69278,9 @@ function escape2(v3) {
|
|
|
69203
69278
|
}
|
|
69204
69279
|
|
|
69205
69280
|
// src/tunnel/frpc-binary.ts
|
|
69206
|
-
var
|
|
69207
|
-
var
|
|
69208
|
-
var
|
|
69281
|
+
var import_node_fs53 = __toESM(require("fs"), 1);
|
|
69282
|
+
var import_node_os21 = __toESM(require("os"), 1);
|
|
69283
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
69209
69284
|
var import_node_child_process14 = require("child_process");
|
|
69210
69285
|
var import_node_stream4 = require("stream");
|
|
69211
69286
|
var import_promises10 = require("stream/promises");
|
|
@@ -69237,20 +69312,20 @@ function frpcDownloadUrl(version2, p3) {
|
|
|
69237
69312
|
}
|
|
69238
69313
|
async function ensureFrpcBinary(opts) {
|
|
69239
69314
|
if (opts.override) {
|
|
69240
|
-
if (!
|
|
69315
|
+
if (!import_node_fs53.default.existsSync(opts.override)) {
|
|
69241
69316
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
69242
69317
|
}
|
|
69243
69318
|
return opts.override;
|
|
69244
69319
|
}
|
|
69245
69320
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
69246
69321
|
const platform = opts.platform ?? detectPlatform();
|
|
69247
|
-
const binDir =
|
|
69248
|
-
|
|
69322
|
+
const binDir = import_node_path58.default.join(opts.dataDir, "bin");
|
|
69323
|
+
import_node_fs53.default.mkdirSync(binDir, { recursive: true });
|
|
69249
69324
|
cleanupStaleArtifacts(binDir);
|
|
69250
|
-
const stableBin =
|
|
69251
|
-
if (
|
|
69325
|
+
const stableBin = import_node_path58.default.join(binDir, "frpc");
|
|
69326
|
+
if (import_node_fs53.default.existsSync(stableBin)) return stableBin;
|
|
69252
69327
|
const partialBin = `${stableBin}.partial`;
|
|
69253
|
-
const tarballPath =
|
|
69328
|
+
const tarballPath = import_node_path58.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
69254
69329
|
try {
|
|
69255
69330
|
const url = frpcDownloadUrl(version2, platform);
|
|
69256
69331
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -69259,8 +69334,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
69259
69334
|
} else {
|
|
69260
69335
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
69261
69336
|
}
|
|
69262
|
-
|
|
69263
|
-
|
|
69337
|
+
import_node_fs53.default.chmodSync(partialBin, 493);
|
|
69338
|
+
import_node_fs53.default.renameSync(partialBin, stableBin);
|
|
69264
69339
|
} finally {
|
|
69265
69340
|
safeUnlink(tarballPath);
|
|
69266
69341
|
safeUnlink(partialBin);
|
|
@@ -69270,15 +69345,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
69270
69345
|
function cleanupStaleArtifacts(binDir) {
|
|
69271
69346
|
let entries;
|
|
69272
69347
|
try {
|
|
69273
|
-
entries =
|
|
69348
|
+
entries = import_node_fs53.default.readdirSync(binDir);
|
|
69274
69349
|
} catch {
|
|
69275
69350
|
return;
|
|
69276
69351
|
}
|
|
69277
69352
|
for (const name of entries) {
|
|
69278
69353
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
69279
|
-
const full =
|
|
69354
|
+
const full = import_node_path58.default.join(binDir, name);
|
|
69280
69355
|
try {
|
|
69281
|
-
|
|
69356
|
+
import_node_fs53.default.rmSync(full, { recursive: true, force: true });
|
|
69282
69357
|
} catch {
|
|
69283
69358
|
}
|
|
69284
69359
|
}
|
|
@@ -69286,7 +69361,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
69286
69361
|
}
|
|
69287
69362
|
function safeUnlink(p3) {
|
|
69288
69363
|
try {
|
|
69289
|
-
|
|
69364
|
+
import_node_fs53.default.unlinkSync(p3);
|
|
69290
69365
|
} catch {
|
|
69291
69366
|
}
|
|
69292
69367
|
}
|
|
@@ -69297,13 +69372,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
69297
69372
|
if (!res.ok || !res.body) {
|
|
69298
69373
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
69299
69374
|
}
|
|
69300
|
-
const out =
|
|
69375
|
+
const out = import_node_fs53.default.createWriteStream(dest);
|
|
69301
69376
|
const nodeStream = import_node_stream4.Readable.fromWeb(res.body);
|
|
69302
69377
|
await (0, import_promises10.pipeline)(nodeStream, out);
|
|
69303
69378
|
}
|
|
69304
69379
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
69305
|
-
const work =
|
|
69306
|
-
|
|
69380
|
+
const work = import_node_path58.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
69381
|
+
import_node_fs53.default.mkdirSync(work, { recursive: true });
|
|
69307
69382
|
try {
|
|
69308
69383
|
await new Promise((resolve9, reject) => {
|
|
69309
69384
|
const proc = (0, import_node_child_process14.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -69311,32 +69386,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
69311
69386
|
proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
|
|
69312
69387
|
});
|
|
69313
69388
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
69314
|
-
const src =
|
|
69315
|
-
if (!
|
|
69389
|
+
const src = import_node_path58.default.join(work, dirName, "frpc");
|
|
69390
|
+
if (!import_node_fs53.default.existsSync(src)) {
|
|
69316
69391
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
69317
69392
|
}
|
|
69318
|
-
|
|
69393
|
+
import_node_fs53.default.copyFileSync(src, destBin);
|
|
69319
69394
|
} finally {
|
|
69320
|
-
|
|
69395
|
+
import_node_fs53.default.rmSync(work, { recursive: true, force: true });
|
|
69321
69396
|
}
|
|
69322
69397
|
}
|
|
69323
69398
|
|
|
69324
69399
|
// src/tunnel/frpc-process.ts
|
|
69325
|
-
var
|
|
69326
|
-
var
|
|
69400
|
+
var import_node_fs54 = __toESM(require("fs"), 1);
|
|
69401
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
69327
69402
|
var import_node_child_process15 = require("child_process");
|
|
69328
69403
|
function frpcPidFilePath(dataDir) {
|
|
69329
|
-
return
|
|
69404
|
+
return import_node_path59.default.join(dataDir, "frpc.pid");
|
|
69330
69405
|
}
|
|
69331
69406
|
function writeFrpcPid(dataDir, pid) {
|
|
69332
69407
|
try {
|
|
69333
|
-
|
|
69408
|
+
import_node_fs54.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
69334
69409
|
} catch {
|
|
69335
69410
|
}
|
|
69336
69411
|
}
|
|
69337
69412
|
function clearFrpcPid(dataDir) {
|
|
69338
69413
|
try {
|
|
69339
|
-
|
|
69414
|
+
import_node_fs54.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
69340
69415
|
} catch {
|
|
69341
69416
|
}
|
|
69342
69417
|
}
|
|
@@ -69352,7 +69427,7 @@ function defaultIsPidAlive(pid) {
|
|
|
69352
69427
|
}
|
|
69353
69428
|
function defaultReadPidFile(file) {
|
|
69354
69429
|
try {
|
|
69355
|
-
return
|
|
69430
|
+
return import_node_fs54.default.readFileSync(file, "utf8");
|
|
69356
69431
|
} catch {
|
|
69357
69432
|
return null;
|
|
69358
69433
|
}
|
|
@@ -69368,7 +69443,7 @@ function defaultSleep2(ms) {
|
|
|
69368
69443
|
}
|
|
69369
69444
|
async function killStaleFrpc(deps) {
|
|
69370
69445
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
69371
|
-
const tomlPath =
|
|
69446
|
+
const tomlPath = import_node_path59.default.join(deps.dataDir, "frpc.toml");
|
|
69372
69447
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
69373
69448
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
69374
69449
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -69392,7 +69467,7 @@ async function killStaleFrpc(deps) {
|
|
|
69392
69467
|
}
|
|
69393
69468
|
if (victims.size === 0) {
|
|
69394
69469
|
try {
|
|
69395
|
-
|
|
69470
|
+
import_node_fs54.default.unlinkSync(pidFile);
|
|
69396
69471
|
} catch {
|
|
69397
69472
|
}
|
|
69398
69473
|
return;
|
|
@@ -69403,7 +69478,7 @@ async function killStaleFrpc(deps) {
|
|
|
69403
69478
|
}
|
|
69404
69479
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
69405
69480
|
try {
|
|
69406
|
-
|
|
69481
|
+
import_node_fs54.default.unlinkSync(pidFile);
|
|
69407
69482
|
} catch {
|
|
69408
69483
|
}
|
|
69409
69484
|
}
|
|
@@ -69440,7 +69515,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
69440
69515
|
var TunnelManager = class {
|
|
69441
69516
|
constructor(deps) {
|
|
69442
69517
|
this.deps = deps;
|
|
69443
|
-
this.store = deps.store ?? new TunnelStore(
|
|
69518
|
+
this.store = deps.store ?? new TunnelStore(import_node_path60.default.join(deps.dataDir, "tunnel.json"));
|
|
69444
69519
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
69445
69520
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
69446
69521
|
}
|
|
@@ -69567,7 +69642,7 @@ var TunnelManager = class {
|
|
|
69567
69642
|
dataDir: this.deps.dataDir,
|
|
69568
69643
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
69569
69644
|
});
|
|
69570
|
-
const tomlPath =
|
|
69645
|
+
const tomlPath = import_node_path60.default.join(this.deps.dataDir, "frpc.toml");
|
|
69571
69646
|
const proxyName = `clawd-${t2.subdomain}-${localPort}-${import_node_crypto17.default.randomBytes(3).toString("hex")}`;
|
|
69572
69647
|
const toml = buildFrpcToml({
|
|
69573
69648
|
serverAddr: t2.frpsHost,
|
|
@@ -69578,14 +69653,14 @@ var TunnelManager = class {
|
|
|
69578
69653
|
localPort,
|
|
69579
69654
|
logLevel: "info"
|
|
69580
69655
|
});
|
|
69581
|
-
await
|
|
69656
|
+
await import_node_fs55.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
69582
69657
|
const proc = (this.deps.spawnImpl ?? import_node_child_process16.spawn)(frpcBin, ["-c", tomlPath], {
|
|
69583
69658
|
stdio: ["ignore", "pipe", "pipe"]
|
|
69584
69659
|
});
|
|
69585
|
-
const logDir =
|
|
69586
|
-
|
|
69587
|
-
const logFilePath =
|
|
69588
|
-
const logStream =
|
|
69660
|
+
const logDir = import_node_path60.default.join(this.deps.dataDir, "log");
|
|
69661
|
+
import_node_fs55.default.mkdirSync(logDir, { recursive: true });
|
|
69662
|
+
const logFilePath = import_node_path60.default.join(logDir, "frpc.log");
|
|
69663
|
+
const logStream = import_node_fs55.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
69589
69664
|
logStream.on("error", () => {
|
|
69590
69665
|
});
|
|
69591
69666
|
const tee = (chunk) => {
|
|
@@ -69667,28 +69742,28 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
69667
69742
|
}
|
|
69668
69743
|
|
|
69669
69744
|
// src/tunnel/device-key.ts
|
|
69670
|
-
var
|
|
69671
|
-
var
|
|
69745
|
+
var import_node_os22 = __toESM(require("os"), 1);
|
|
69746
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
69672
69747
|
var import_node_crypto18 = __toESM(require("crypto"), 1);
|
|
69673
69748
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
69674
69749
|
function deriveStableDeviceKey(opts = {}) {
|
|
69675
|
-
const hostname = opts.hostname ??
|
|
69676
|
-
const uid = opts.uid ?? (typeof
|
|
69677
|
-
const home = opts.home ??
|
|
69678
|
-
const defaultDataDir =
|
|
69679
|
-
const normalizedDataDir = opts.dataDir ?
|
|
69750
|
+
const hostname = opts.hostname ?? import_node_os22.default.hostname();
|
|
69751
|
+
const uid = opts.uid ?? (typeof import_node_os22.default.userInfo === "function" ? import_node_os22.default.userInfo().uid : 0);
|
|
69752
|
+
const home = opts.home ?? import_node_os22.default.homedir();
|
|
69753
|
+
const defaultDataDir = import_node_path61.default.resolve(import_node_path61.default.join(home, ".clawd"));
|
|
69754
|
+
const normalizedDataDir = opts.dataDir ? import_node_path61.default.resolve(opts.dataDir) : null;
|
|
69680
69755
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
69681
69756
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
69682
69757
|
return import_node_crypto18.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
69683
69758
|
}
|
|
69684
69759
|
|
|
69685
69760
|
// src/auth-store.ts
|
|
69686
|
-
var
|
|
69687
|
-
var
|
|
69761
|
+
var import_node_fs56 = __toESM(require("fs"), 1);
|
|
69762
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
69688
69763
|
var import_node_crypto19 = __toESM(require("crypto"), 1);
|
|
69689
69764
|
var AUTH_FILE_NAME = "auth.json";
|
|
69690
69765
|
function authFilePath(dataDir) {
|
|
69691
|
-
return
|
|
69766
|
+
return import_node_path62.default.join(dataDir, AUTH_FILE_NAME);
|
|
69692
69767
|
}
|
|
69693
69768
|
function loadOrCreateAuthFile(opts) {
|
|
69694
69769
|
const file = authFilePath(opts.dataDir);
|
|
@@ -69729,7 +69804,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
69729
69804
|
}
|
|
69730
69805
|
function readAuthFile(file) {
|
|
69731
69806
|
try {
|
|
69732
|
-
const raw =
|
|
69807
|
+
const raw = import_node_fs56.default.readFileSync(file, "utf8");
|
|
69733
69808
|
const parsed = JSON.parse(raw);
|
|
69734
69809
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
69735
69810
|
return null;
|
|
@@ -69750,26 +69825,26 @@ function readAuthFile(file) {
|
|
|
69750
69825
|
}
|
|
69751
69826
|
}
|
|
69752
69827
|
function writeAuthFile(file, content) {
|
|
69753
|
-
|
|
69754
|
-
|
|
69828
|
+
import_node_fs56.default.mkdirSync(import_node_path62.default.dirname(file), { recursive: true });
|
|
69829
|
+
import_node_fs56.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
69755
69830
|
try {
|
|
69756
|
-
|
|
69831
|
+
import_node_fs56.default.chmodSync(file, 384);
|
|
69757
69832
|
} catch {
|
|
69758
69833
|
}
|
|
69759
69834
|
}
|
|
69760
69835
|
|
|
69761
69836
|
// src/owner-profile.ts
|
|
69762
|
-
var
|
|
69763
|
-
var
|
|
69764
|
-
var
|
|
69837
|
+
var import_node_fs57 = __toESM(require("fs"), 1);
|
|
69838
|
+
var import_node_os23 = __toESM(require("os"), 1);
|
|
69839
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
69765
69840
|
var PROFILE_FILENAME = "profile.json";
|
|
69766
69841
|
function profilePath(dataDir) {
|
|
69767
|
-
return
|
|
69842
|
+
return import_node_path63.default.join(dataDir, PROFILE_FILENAME);
|
|
69768
69843
|
}
|
|
69769
69844
|
function loadOwnerProfile(dataDir) {
|
|
69770
69845
|
let raw;
|
|
69771
69846
|
try {
|
|
69772
|
-
raw =
|
|
69847
|
+
raw = import_node_fs57.default.readFileSync(profilePath(dataDir), "utf8");
|
|
69773
69848
|
} catch {
|
|
69774
69849
|
return {};
|
|
69775
69850
|
}
|
|
@@ -69785,11 +69860,11 @@ function loadOwnerProfile(dataDir) {
|
|
|
69785
69860
|
}
|
|
69786
69861
|
function patchOwnerProfile(dataDir, patch) {
|
|
69787
69862
|
const merged = { ...loadOwnerProfile(dataDir), ...patch };
|
|
69788
|
-
|
|
69863
|
+
import_node_fs57.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
|
|
69789
69864
|
return merged;
|
|
69790
69865
|
}
|
|
69791
69866
|
function loadOwnerDisplayName(dataDir) {
|
|
69792
|
-
const fallback =
|
|
69867
|
+
const fallback = import_node_os23.default.userInfo().username;
|
|
69793
69868
|
const displayName = loadOwnerProfile(dataDir).displayName;
|
|
69794
69869
|
if (typeof displayName !== "string" || displayName.length === 0) {
|
|
69795
69870
|
if (displayName !== void 0) {
|
|
@@ -69801,18 +69876,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
69801
69876
|
}
|
|
69802
69877
|
|
|
69803
69878
|
// src/feishu-auth/owner-identity-store.ts
|
|
69804
|
-
var
|
|
69805
|
-
var
|
|
69879
|
+
var import_node_fs58 = __toESM(require("fs"), 1);
|
|
69880
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
69806
69881
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
69807
69882
|
var OwnerIdentityStore = class {
|
|
69808
69883
|
file;
|
|
69809
69884
|
constructor(dataDir) {
|
|
69810
|
-
this.file =
|
|
69885
|
+
this.file = import_node_path64.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
69811
69886
|
}
|
|
69812
69887
|
read() {
|
|
69813
69888
|
let raw;
|
|
69814
69889
|
try {
|
|
69815
|
-
raw =
|
|
69890
|
+
raw = import_node_fs58.default.readFileSync(this.file, "utf8");
|
|
69816
69891
|
} catch {
|
|
69817
69892
|
return null;
|
|
69818
69893
|
}
|
|
@@ -69839,16 +69914,16 @@ var OwnerIdentityStore = class {
|
|
|
69839
69914
|
};
|
|
69840
69915
|
}
|
|
69841
69916
|
write(record4) {
|
|
69842
|
-
|
|
69843
|
-
|
|
69917
|
+
import_node_fs58.default.mkdirSync(import_node_path64.default.dirname(this.file), { recursive: true });
|
|
69918
|
+
import_node_fs58.default.writeFileSync(this.file, JSON.stringify(record4, null, 2), { mode: 384 });
|
|
69844
69919
|
try {
|
|
69845
|
-
|
|
69920
|
+
import_node_fs58.default.chmodSync(this.file, 384);
|
|
69846
69921
|
} catch {
|
|
69847
69922
|
}
|
|
69848
69923
|
}
|
|
69849
69924
|
clear() {
|
|
69850
69925
|
try {
|
|
69851
|
-
|
|
69926
|
+
import_node_fs58.default.unlinkSync(this.file);
|
|
69852
69927
|
} catch (err) {
|
|
69853
69928
|
const code = err?.code;
|
|
69854
69929
|
if (code !== "ENOENT") throw err;
|
|
@@ -70344,8 +70419,8 @@ function verifyConnectToken(args) {
|
|
|
70344
70419
|
}
|
|
70345
70420
|
|
|
70346
70421
|
// src/feishu-auth/server-key.ts
|
|
70347
|
-
var
|
|
70348
|
-
var
|
|
70422
|
+
var fs75 = __toESM(require("fs"), 1);
|
|
70423
|
+
var path77 = __toESM(require("path"), 1);
|
|
70349
70424
|
var FILE_NAME2 = "server-signing-key.json";
|
|
70350
70425
|
var ServerKeyStore = class {
|
|
70351
70426
|
constructor(dataDir) {
|
|
@@ -70353,12 +70428,12 @@ var ServerKeyStore = class {
|
|
|
70353
70428
|
}
|
|
70354
70429
|
dataDir;
|
|
70355
70430
|
filePath() {
|
|
70356
|
-
return
|
|
70431
|
+
return path77.join(this.dataDir, FILE_NAME2);
|
|
70357
70432
|
}
|
|
70358
70433
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
70359
70434
|
read() {
|
|
70360
70435
|
try {
|
|
70361
|
-
const raw =
|
|
70436
|
+
const raw = fs75.readFileSync(this.filePath(), "utf8");
|
|
70362
70437
|
const parsed = JSON.parse(raw);
|
|
70363
70438
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
70364
70439
|
return parsed.publicKeyPem;
|
|
@@ -70373,12 +70448,12 @@ var ServerKeyStore = class {
|
|
|
70373
70448
|
publicKeyPem,
|
|
70374
70449
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
70375
70450
|
};
|
|
70376
|
-
|
|
70377
|
-
|
|
70451
|
+
fs75.mkdirSync(this.dataDir, { recursive: true });
|
|
70452
|
+
fs75.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
70378
70453
|
}
|
|
70379
70454
|
clear() {
|
|
70380
70455
|
try {
|
|
70381
|
-
|
|
70456
|
+
fs75.unlinkSync(this.filePath());
|
|
70382
70457
|
} catch {
|
|
70383
70458
|
}
|
|
70384
70459
|
}
|
|
@@ -70394,13 +70469,13 @@ var import_node_path80 = __toESM(require("path"), 1);
|
|
|
70394
70469
|
init_protocol();
|
|
70395
70470
|
|
|
70396
70471
|
// src/session/fork.ts
|
|
70397
|
-
var
|
|
70398
|
-
var
|
|
70399
|
-
var
|
|
70472
|
+
var import_node_fs59 = __toESM(require("fs"), 1);
|
|
70473
|
+
var import_node_os24 = __toESM(require("os"), 1);
|
|
70474
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
70400
70475
|
var import_node_crypto21 = require("crypto");
|
|
70401
70476
|
init_claude_history();
|
|
70402
70477
|
function readJsonlEntries(file) {
|
|
70403
|
-
const raw =
|
|
70478
|
+
const raw = import_node_fs59.default.readFileSync(file, "utf8");
|
|
70404
70479
|
const out = [];
|
|
70405
70480
|
for (const line of raw.split("\n")) {
|
|
70406
70481
|
const t2 = line.trim();
|
|
@@ -70413,19 +70488,19 @@ function readJsonlEntries(file) {
|
|
|
70413
70488
|
return out;
|
|
70414
70489
|
}
|
|
70415
70490
|
function forkSession(input) {
|
|
70416
|
-
const baseDir = input.baseDir ??
|
|
70417
|
-
let projectDir =
|
|
70418
|
-
let sourceFile =
|
|
70419
|
-
if (!
|
|
70491
|
+
const baseDir = input.baseDir ?? import_node_path65.default.join(import_node_os24.default.homedir(), ".claude");
|
|
70492
|
+
let projectDir = import_node_path65.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
70493
|
+
let sourceFile = import_node_path65.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
70494
|
+
if (!import_node_fs59.default.existsSync(sourceFile)) {
|
|
70420
70495
|
const found = findTranscriptByToolSessionId(
|
|
70421
|
-
|
|
70496
|
+
import_node_path65.default.join(baseDir, "projects"),
|
|
70422
70497
|
input.toolSessionId
|
|
70423
70498
|
);
|
|
70424
70499
|
if (!found) {
|
|
70425
70500
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
70426
70501
|
}
|
|
70427
70502
|
sourceFile = found;
|
|
70428
|
-
projectDir =
|
|
70503
|
+
projectDir = import_node_path65.default.dirname(found);
|
|
70429
70504
|
}
|
|
70430
70505
|
const entries = readJsonlEntries(sourceFile);
|
|
70431
70506
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -70454,17 +70529,17 @@ function forkSession(input) {
|
|
|
70454
70529
|
}
|
|
70455
70530
|
forkedLines.push(JSON.stringify(forked));
|
|
70456
70531
|
}
|
|
70457
|
-
const outDir = input.targetCwd ?
|
|
70458
|
-
const forkedFilePath =
|
|
70459
|
-
|
|
70460
|
-
|
|
70532
|
+
const outDir = input.targetCwd ? import_node_path65.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
70533
|
+
const forkedFilePath = import_node_path65.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
70534
|
+
import_node_fs59.default.mkdirSync(outDir, { recursive: true });
|
|
70535
|
+
import_node_fs59.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
70461
70536
|
return { forkedToolSessionId, forkedFilePath };
|
|
70462
70537
|
}
|
|
70463
70538
|
|
|
70464
70539
|
// src/tools/codex-fork.ts
|
|
70465
70540
|
var import_node_child_process17 = require("child_process");
|
|
70466
|
-
var
|
|
70467
|
-
var
|
|
70541
|
+
var import_node_fs60 = __toESM(require("fs"), 1);
|
|
70542
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
70468
70543
|
function openCodexAppServer(home, cwd) {
|
|
70469
70544
|
const proc = (0, import_node_child_process17.spawn)(process.env.CODEX_BIN ?? "codex", ["app-server", "--listen", "stdio://"], {
|
|
70470
70545
|
cwd,
|
|
@@ -70484,7 +70559,7 @@ function openCodexAppServer(home, cwd) {
|
|
|
70484
70559
|
async function forkCodexThread(input, deps = {}) {
|
|
70485
70560
|
const source = locateCodexThread(input.roots, input.sourceThreadId);
|
|
70486
70561
|
if (!source) throw new Error(`codex fork: source thread not found: ${input.sourceThreadId}`);
|
|
70487
|
-
const rollout = parseCodexRollout(
|
|
70562
|
+
const rollout = parseCodexRollout(import_node_fs60.default.readFileSync(source.file, "utf8"));
|
|
70488
70563
|
if (rollout.meta?.threadId.toLowerCase() !== input.sourceThreadId.toLowerCase()) {
|
|
70489
70564
|
throw new Error(`codex fork: source thread metadata does not match ${input.sourceThreadId}`);
|
|
70490
70565
|
}
|
|
@@ -70514,7 +70589,7 @@ async function forkCodexThread(input, deps = {}) {
|
|
|
70514
70589
|
if (typeof forkedToolSessionId !== "string" || !forkedToolSessionId) {
|
|
70515
70590
|
throw new Error("codex fork: app-server returned no thread id");
|
|
70516
70591
|
}
|
|
70517
|
-
const forked = locateCodexThread([
|
|
70592
|
+
const forked = locateCodexThread([import_node_path66.default.join(source.home, "sessions")], forkedToolSessionId);
|
|
70518
70593
|
if (!forked) throw new Error(`codex fork: rollout not found for forked thread ${forkedToolSessionId}`);
|
|
70519
70594
|
return { forkedToolSessionId, forkedFilePath: forked.file };
|
|
70520
70595
|
})()]);
|
|
@@ -70525,19 +70600,19 @@ async function forkCodexThread(input, deps = {}) {
|
|
|
70525
70600
|
}
|
|
70526
70601
|
|
|
70527
70602
|
// src/session/external-scan.ts
|
|
70528
|
-
var
|
|
70603
|
+
var import_node_fs61 = __toESM(require("fs"), 1);
|
|
70529
70604
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
70530
|
-
var
|
|
70531
|
-
var
|
|
70605
|
+
var import_node_os25 = __toESM(require("os"), 1);
|
|
70606
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
70532
70607
|
var import_node_module = require("module");
|
|
70533
70608
|
var import_node_child_process18 = require("child_process");
|
|
70534
70609
|
var import_meta7 = {};
|
|
70535
70610
|
function defaultRoots() {
|
|
70536
|
-
const home =
|
|
70611
|
+
const home = import_node_os25.default.homedir();
|
|
70537
70612
|
return {
|
|
70538
|
-
claudeProjectsDir:
|
|
70539
|
-
codexDir:
|
|
70540
|
-
clawdDir:
|
|
70613
|
+
claudeProjectsDir: import_node_path67.default.join(home, ".claude", "projects"),
|
|
70614
|
+
codexDir: import_node_path67.default.join(home, ".codex"),
|
|
70615
|
+
clawdDir: import_node_path67.default.join(home, ".clawd")
|
|
70541
70616
|
};
|
|
70542
70617
|
}
|
|
70543
70618
|
function width(s2) {
|
|
@@ -70588,7 +70663,7 @@ function userText(msg) {
|
|
|
70588
70663
|
}
|
|
70589
70664
|
function isDir2(p3) {
|
|
70590
70665
|
try {
|
|
70591
|
-
return
|
|
70666
|
+
return import_node_fs61.default.statSync(p3).isDirectory();
|
|
70592
70667
|
} catch {
|
|
70593
70668
|
return false;
|
|
70594
70669
|
}
|
|
@@ -70597,7 +70672,7 @@ async function scanClaude(roots) {
|
|
|
70597
70672
|
const out = [];
|
|
70598
70673
|
let dirs;
|
|
70599
70674
|
try {
|
|
70600
|
-
dirs =
|
|
70675
|
+
dirs = import_node_fs61.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
|
|
70601
70676
|
} catch {
|
|
70602
70677
|
return out;
|
|
70603
70678
|
}
|
|
@@ -70605,16 +70680,16 @@ async function scanClaude(roots) {
|
|
|
70605
70680
|
if (!d2.isDirectory()) continue;
|
|
70606
70681
|
let files;
|
|
70607
70682
|
try {
|
|
70608
|
-
files =
|
|
70683
|
+
files = import_node_fs61.default.readdirSync(import_node_path67.default.join(roots.claudeProjectsDir, d2.name));
|
|
70609
70684
|
} catch {
|
|
70610
70685
|
continue;
|
|
70611
70686
|
}
|
|
70612
70687
|
for (const name of files) {
|
|
70613
70688
|
if (!name.endsWith(".jsonl")) continue;
|
|
70614
|
-
const file =
|
|
70689
|
+
const file = import_node_path67.default.join(roots.claudeProjectsDir, d2.name, name);
|
|
70615
70690
|
let st2;
|
|
70616
70691
|
try {
|
|
70617
|
-
st2 =
|
|
70692
|
+
st2 = import_node_fs61.default.statSync(file);
|
|
70618
70693
|
} catch {
|
|
70619
70694
|
continue;
|
|
70620
70695
|
}
|
|
@@ -70667,7 +70742,7 @@ async function scanClaude(roots) {
|
|
|
70667
70742
|
return out;
|
|
70668
70743
|
}
|
|
70669
70744
|
async function countCodexTurns(rolloutPath) {
|
|
70670
|
-
if (!rolloutPath || !
|
|
70745
|
+
if (!rolloutPath || !import_node_fs61.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
|
|
70671
70746
|
let turns = 0;
|
|
70672
70747
|
let first = "";
|
|
70673
70748
|
for await (const rec6 of jsonLines(rolloutPath)) {
|
|
@@ -70741,7 +70816,7 @@ async function codexFromRows(rows) {
|
|
|
70741
70816
|
async function scanCodex(roots) {
|
|
70742
70817
|
let dbs = [];
|
|
70743
70818
|
try {
|
|
70744
|
-
dbs =
|
|
70819
|
+
dbs = import_node_fs61.default.readdirSync(roots.codexDir).filter((n2) => /^state_.*\.sqlite$/.test(n2)).sort().map((n2) => import_node_path67.default.join(roots.codexDir, n2));
|
|
70745
70820
|
} catch {
|
|
70746
70821
|
}
|
|
70747
70822
|
if (!dbs.length) return [];
|
|
@@ -70750,14 +70825,14 @@ async function scanCodex(roots) {
|
|
|
70750
70825
|
}
|
|
70751
70826
|
async function scanExternalSessions(rootsIn) {
|
|
70752
70827
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
70753
|
-
const personaRoot =
|
|
70828
|
+
const personaRoot = import_node_path67.default.join(roots.clawdDir, "personas");
|
|
70754
70829
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
70755
70830
|
const out = [];
|
|
70756
70831
|
for (const c2 of all) {
|
|
70757
70832
|
if (c2.skip) continue;
|
|
70758
70833
|
if (c2.turns < 1) continue;
|
|
70759
70834
|
if (!c2.cwd || !isDir2(c2.cwd)) continue;
|
|
70760
|
-
if (c2.cwd === roots.clawdDir || c2.cwd === personaRoot || c2.cwd.startsWith(personaRoot +
|
|
70835
|
+
if (c2.cwd === roots.clawdDir || c2.cwd === personaRoot || c2.cwd.startsWith(personaRoot + import_node_path67.default.sep) || c2.cwd.startsWith(roots.clawdDir + import_node_path67.default.sep)) {
|
|
70761
70836
|
continue;
|
|
70762
70837
|
}
|
|
70763
70838
|
out.push({
|
|
@@ -70774,13 +70849,13 @@ async function scanExternalSessions(rootsIn) {
|
|
|
70774
70849
|
}
|
|
70775
70850
|
|
|
70776
70851
|
// src/session/import-ledger.ts
|
|
70777
|
-
var
|
|
70778
|
-
var
|
|
70852
|
+
var import_node_fs62 = __toESM(require("fs"), 1);
|
|
70853
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
70779
70854
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
70780
70855
|
function readImportLedger(dataDir) {
|
|
70781
70856
|
try {
|
|
70782
70857
|
const parsed = JSON.parse(
|
|
70783
|
-
|
|
70858
|
+
import_node_fs62.default.readFileSync(import_node_path68.default.join(dataDir, LEDGER_FILENAME), "utf8")
|
|
70784
70859
|
);
|
|
70785
70860
|
return Array.isArray(parsed) ? parsed : [];
|
|
70786
70861
|
} catch {
|
|
@@ -70788,15 +70863,15 @@ function readImportLedger(dataDir) {
|
|
|
70788
70863
|
}
|
|
70789
70864
|
}
|
|
70790
70865
|
function appendImportLedger(dataDir, entry) {
|
|
70791
|
-
const file =
|
|
70866
|
+
const file = import_node_path68.default.join(dataDir, LEDGER_FILENAME);
|
|
70792
70867
|
const entries = readImportLedger(dataDir);
|
|
70793
70868
|
entries.push(entry);
|
|
70794
|
-
|
|
70869
|
+
import_node_fs62.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
70795
70870
|
}
|
|
70796
70871
|
|
|
70797
70872
|
// src/handlers/session.ts
|
|
70798
70873
|
init_protocol();
|
|
70799
|
-
var
|
|
70874
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
70800
70875
|
function canReadSearchHit(ctx, file) {
|
|
70801
70876
|
if (!ctx || ctx.principal.kind === "owner") return true;
|
|
70802
70877
|
return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
|
|
@@ -71077,7 +71152,7 @@ ${attribution}` } : args;
|
|
|
71077
71152
|
`principal guest:${ctx.principal.id} cannot fork tool session ${args.toolSessionId}`
|
|
71078
71153
|
);
|
|
71079
71154
|
}
|
|
71080
|
-
if (source?.tool === "codex" && args.targetCwd &&
|
|
71155
|
+
if (source?.tool === "codex" && args.targetCwd && import_node_path69.default.resolve(args.targetCwd) !== import_node_path69.default.resolve(source.cwd)) {
|
|
71081
71156
|
throw new ClawdError(ERROR_CODES.FORBIDDEN, "fork: guest targetCwd must match source cwd");
|
|
71082
71157
|
}
|
|
71083
71158
|
}
|
|
@@ -71354,7 +71429,7 @@ function buildPermissionHandlers(deps) {
|
|
|
71354
71429
|
}
|
|
71355
71430
|
|
|
71356
71431
|
// src/handlers/history.ts
|
|
71357
|
-
var
|
|
71432
|
+
var path84 = __toESM(require("path"), 1);
|
|
71358
71433
|
init_protocol();
|
|
71359
71434
|
|
|
71360
71435
|
// src/session/recent-dirs.ts
|
|
@@ -71372,7 +71447,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
71372
71447
|
}
|
|
71373
71448
|
|
|
71374
71449
|
// src/permission/persona-paths.ts
|
|
71375
|
-
var
|
|
71450
|
+
var path83 = __toESM(require("path"), 1);
|
|
71376
71451
|
function getAllowedPersonaIds(grants, action) {
|
|
71377
71452
|
const ids = /* @__PURE__ */ new Set();
|
|
71378
71453
|
for (const g3 of grants) {
|
|
@@ -71385,42 +71460,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
71385
71460
|
return ids;
|
|
71386
71461
|
}
|
|
71387
71462
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
71388
|
-
const target =
|
|
71463
|
+
const target = path83.resolve(absPath);
|
|
71389
71464
|
if (userWorkDir) {
|
|
71390
|
-
const u2 =
|
|
71391
|
-
const usep = u2.endsWith(
|
|
71465
|
+
const u2 = path83.resolve(userWorkDir);
|
|
71466
|
+
const usep = u2.endsWith(path83.sep) ? "" : path83.sep;
|
|
71392
71467
|
if (target === u2 || target.startsWith(u2 + usep)) return true;
|
|
71393
71468
|
}
|
|
71394
|
-
const root =
|
|
71395
|
-
const sep4 = root.endsWith(
|
|
71469
|
+
const root = path83.resolve(personaRoot);
|
|
71470
|
+
const sep4 = root.endsWith(path83.sep) ? "" : path83.sep;
|
|
71396
71471
|
if (!target.startsWith(root + sep4)) return false;
|
|
71397
|
-
const rel =
|
|
71472
|
+
const rel = path83.relative(root, target);
|
|
71398
71473
|
if (!rel || rel.startsWith("..")) return false;
|
|
71399
|
-
const personaId2 = rel.split(
|
|
71474
|
+
const personaId2 = rel.split(path83.sep)[0];
|
|
71400
71475
|
if (!personaId2) return false;
|
|
71401
71476
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
71402
71477
|
if (allowed === "*") return true;
|
|
71403
71478
|
return allowed.has(personaId2);
|
|
71404
71479
|
}
|
|
71405
71480
|
function personaIdFromPath(absPath, personaRoot) {
|
|
71406
|
-
const root =
|
|
71407
|
-
const target =
|
|
71408
|
-
const sep4 = root.endsWith(
|
|
71481
|
+
const root = path83.resolve(personaRoot);
|
|
71482
|
+
const target = path83.resolve(absPath);
|
|
71483
|
+
const sep4 = root.endsWith(path83.sep) ? "" : path83.sep;
|
|
71409
71484
|
if (!target.startsWith(root + sep4)) return null;
|
|
71410
|
-
const rel =
|
|
71485
|
+
const rel = path83.relative(root, target);
|
|
71411
71486
|
if (!rel || rel.startsWith("..")) return null;
|
|
71412
|
-
const id = rel.split(
|
|
71487
|
+
const id = rel.split(path83.sep)[0];
|
|
71413
71488
|
return id || null;
|
|
71414
71489
|
}
|
|
71415
71490
|
function isPathWithin(dir, absPath) {
|
|
71416
|
-
const d2 =
|
|
71417
|
-
const t2 =
|
|
71418
|
-
const sep4 = d2.endsWith(
|
|
71491
|
+
const d2 = path83.resolve(dir);
|
|
71492
|
+
const t2 = path83.resolve(absPath);
|
|
71493
|
+
const sep4 = d2.endsWith(path83.sep) ? "" : path83.sep;
|
|
71419
71494
|
return t2 === d2 || t2.startsWith(d2 + sep4);
|
|
71420
71495
|
}
|
|
71421
71496
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
71422
71497
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
71423
|
-
return personaIdFromPath(
|
|
71498
|
+
return personaIdFromPath(path83.resolve(absPath), personaRoot) === personaId2;
|
|
71424
71499
|
}
|
|
71425
71500
|
|
|
71426
71501
|
// src/handlers/history.ts
|
|
@@ -71474,7 +71549,7 @@ function buildHistoryHandlers(deps) {
|
|
|
71474
71549
|
if (!pid) return false;
|
|
71475
71550
|
return isGuestPathAllowed(
|
|
71476
71551
|
ctx.grants,
|
|
71477
|
-
|
|
71552
|
+
path84.join(personaRoot, pid),
|
|
71478
71553
|
personaRoot,
|
|
71479
71554
|
"read",
|
|
71480
71555
|
userWorkDir
|
|
@@ -71486,7 +71561,7 @@ function buildHistoryHandlers(deps) {
|
|
|
71486
71561
|
};
|
|
71487
71562
|
const list = async (frame, _client, ctx) => {
|
|
71488
71563
|
const args = HistoryListArgs.parse(frame);
|
|
71489
|
-
assertGuestPath(ctx,
|
|
71564
|
+
assertGuestPath(ctx, path84.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
71490
71565
|
const sessions = await history.listSessions(args);
|
|
71491
71566
|
return { response: { type: "history:list", sessions } };
|
|
71492
71567
|
};
|
|
@@ -71534,14 +71609,14 @@ function buildHistoryHandlers(deps) {
|
|
|
71534
71609
|
};
|
|
71535
71610
|
const subagents = async (frame, _client, ctx) => {
|
|
71536
71611
|
const args = HistorySubagentsArgs.parse(frame);
|
|
71537
|
-
assertGuestPath(ctx,
|
|
71612
|
+
assertGuestPath(ctx, path84.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
71538
71613
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
71539
71614
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
71540
71615
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
71541
71616
|
};
|
|
71542
71617
|
const subagentRead = async (frame, _client, ctx) => {
|
|
71543
71618
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
71544
|
-
assertGuestPath(ctx,
|
|
71619
|
+
assertGuestPath(ctx, path84.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
71545
71620
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
71546
71621
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
71547
71622
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -71551,7 +71626,7 @@ function buildHistoryHandlers(deps) {
|
|
|
71551
71626
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
71552
71627
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
71553
71628
|
const filtered = dirs.filter(
|
|
71554
|
-
(d2) => isGuestPathAllowed(ctx.grants,
|
|
71629
|
+
(d2) => isGuestPathAllowed(ctx.grants, path84.resolve(d2.cwd), personaRoot, "read", userWorkDir)
|
|
71555
71630
|
);
|
|
71556
71631
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
71557
71632
|
}
|
|
@@ -71568,17 +71643,17 @@ function buildHistoryHandlers(deps) {
|
|
|
71568
71643
|
}
|
|
71569
71644
|
|
|
71570
71645
|
// src/handlers/projects.ts
|
|
71571
|
-
var
|
|
71572
|
-
var
|
|
71573
|
-
var
|
|
71646
|
+
var fs80 = __toESM(require("fs"), 1);
|
|
71647
|
+
var os27 = __toESM(require("os"), 1);
|
|
71648
|
+
var path85 = __toESM(require("path"), 1);
|
|
71574
71649
|
var import_node_child_process19 = require("child_process");
|
|
71575
71650
|
init_protocol();
|
|
71576
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
71651
|
+
var DEFAULT_PROJECTS_ROOT = path85.join(os27.homedir(), "Documents", "ChatGPT");
|
|
71577
71652
|
function allocateDir(root, name) {
|
|
71578
|
-
let candidate =
|
|
71653
|
+
let candidate = path85.join(root, name);
|
|
71579
71654
|
let n2 = 2;
|
|
71580
|
-
while (
|
|
71581
|
-
candidate =
|
|
71655
|
+
while (fs80.existsSync(candidate)) {
|
|
71656
|
+
candidate = path85.join(root, `${name} ${n2}`);
|
|
71582
71657
|
n2 += 1;
|
|
71583
71658
|
}
|
|
71584
71659
|
return candidate;
|
|
@@ -71606,7 +71681,7 @@ function buildProjectHandlers(deps) {
|
|
|
71606
71681
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
|
|
71607
71682
|
}
|
|
71608
71683
|
try {
|
|
71609
|
-
if (!
|
|
71684
|
+
if (!fs80.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
71610
71685
|
} catch {
|
|
71611
71686
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
71612
71687
|
}
|
|
@@ -71622,7 +71697,7 @@ function buildProjectHandlers(deps) {
|
|
|
71622
71697
|
let target;
|
|
71623
71698
|
if (args.path) {
|
|
71624
71699
|
try {
|
|
71625
|
-
if (!
|
|
71700
|
+
if (!fs80.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
71626
71701
|
} catch {
|
|
71627
71702
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
71628
71703
|
}
|
|
@@ -71630,15 +71705,15 @@ function buildProjectHandlers(deps) {
|
|
|
71630
71705
|
} else {
|
|
71631
71706
|
const name = args.name;
|
|
71632
71707
|
try {
|
|
71633
|
-
|
|
71708
|
+
fs80.mkdirSync(root, { recursive: true });
|
|
71634
71709
|
target = allocateDir(root, name);
|
|
71635
|
-
|
|
71710
|
+
fs80.mkdirSync(target);
|
|
71636
71711
|
} catch (err) {
|
|
71637
71712
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
|
|
71638
71713
|
}
|
|
71639
71714
|
const git2 = (0, import_node_child_process19.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
|
|
71640
71715
|
if (git2.status !== 0) {
|
|
71641
|
-
|
|
71716
|
+
fs80.rmSync(target, { recursive: true, force: true });
|
|
71642
71717
|
throw new ClawdError(
|
|
71643
71718
|
ERROR_CODES.INVALID_CWD,
|
|
71644
71719
|
`git init \u5931\u8D25\uFF08${git2.error ? String(git2.error) : `exit ${git2.status}`}\uFF09: ${target}`
|
|
@@ -71663,9 +71738,9 @@ function buildProjectHandlers(deps) {
|
|
|
71663
71738
|
}
|
|
71664
71739
|
|
|
71665
71740
|
// src/handlers/workspace.ts
|
|
71666
|
-
var
|
|
71741
|
+
var path86 = __toESM(require("path"), 1);
|
|
71667
71742
|
init_protocol();
|
|
71668
|
-
var
|
|
71743
|
+
var os28 = __toESM(require("os"), 1);
|
|
71669
71744
|
init_protocol();
|
|
71670
71745
|
init_protocol();
|
|
71671
71746
|
function buildEnabledPluginNames(personaManager, personaId2) {
|
|
@@ -71705,23 +71780,23 @@ function buildWorkspaceHandlers(deps) {
|
|
|
71705
71780
|
const list = async (frame, _client, ctx) => {
|
|
71706
71781
|
const args = WorkspaceListArgs.parse(frame);
|
|
71707
71782
|
const isGuest = ctx?.principal.kind === "guest";
|
|
71708
|
-
const fallbackCwd = isGuest && personaRoot ? personaRoot :
|
|
71709
|
-
const resolvedCwd =
|
|
71710
|
-
const target = args.path ?
|
|
71783
|
+
const fallbackCwd = isGuest && personaRoot ? personaRoot : os28.homedir();
|
|
71784
|
+
const resolvedCwd = path86.resolve(args.cwd ?? fallbackCwd);
|
|
71785
|
+
const target = args.path ? path86.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
71711
71786
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
71712
71787
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
71713
71788
|
return { response: { type: "workspace:list", ...res } };
|
|
71714
71789
|
};
|
|
71715
71790
|
const read = async (frame, _client, ctx) => {
|
|
71716
71791
|
const args = WorkspaceReadArgs.parse(frame);
|
|
71717
|
-
const target =
|
|
71792
|
+
const target = path86.isAbsolute(args.path) ? path86.resolve(args.path) : path86.resolve(args.cwd, args.path);
|
|
71718
71793
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
71719
71794
|
const res = workspace.read(args);
|
|
71720
71795
|
return { response: { type: "workspace:read", ...res } };
|
|
71721
71796
|
};
|
|
71722
71797
|
const skillsList = async (frame, _client, ctx) => {
|
|
71723
71798
|
const args = SkillsListArgs.parse(frame);
|
|
71724
|
-
const cwdAbs =
|
|
71799
|
+
const cwdAbs = path86.resolve(args.cwd);
|
|
71725
71800
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
71726
71801
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
71727
71802
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -71733,7 +71808,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
71733
71808
|
};
|
|
71734
71809
|
const agentsList = async (frame, _client, ctx) => {
|
|
71735
71810
|
const args = AgentsListArgs.parse(frame);
|
|
71736
|
-
const cwdAbs =
|
|
71811
|
+
const cwdAbs = path86.resolve(args.cwd);
|
|
71737
71812
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
71738
71813
|
if (isCodexFamily(args.tool) || isPiFamily(args.tool)) {
|
|
71739
71814
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -71755,20 +71830,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
71755
71830
|
}
|
|
71756
71831
|
|
|
71757
71832
|
// src/handlers/git.ts
|
|
71758
|
-
var
|
|
71833
|
+
var path88 = __toESM(require("path"), 1);
|
|
71759
71834
|
init_protocol();
|
|
71760
71835
|
init_protocol();
|
|
71761
71836
|
|
|
71762
71837
|
// src/workspace/git.ts
|
|
71763
71838
|
var import_node_child_process20 = require("child_process");
|
|
71764
|
-
var
|
|
71765
|
-
var
|
|
71839
|
+
var import_node_fs63 = __toESM(require("fs"), 1);
|
|
71840
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
71766
71841
|
var import_node_util2 = require("util");
|
|
71767
71842
|
var pexec = (0, import_node_util2.promisify)(import_node_child_process20.execFile);
|
|
71768
71843
|
function normalizePath(p3) {
|
|
71769
|
-
const resolved =
|
|
71844
|
+
const resolved = import_node_path70.default.resolve(p3);
|
|
71770
71845
|
try {
|
|
71771
|
-
return
|
|
71846
|
+
return import_node_fs63.default.realpathSync(resolved);
|
|
71772
71847
|
} catch {
|
|
71773
71848
|
return resolved;
|
|
71774
71849
|
}
|
|
@@ -71842,7 +71917,7 @@ async function listGitBranches(cwd) {
|
|
|
71842
71917
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
71843
71918
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
71844
71919
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
71845
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
71920
|
+
if (!isGuestPathAllowed(ctx.grants, path88.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
71846
71921
|
throw new ClawdError(
|
|
71847
71922
|
ERROR_CODES.UNAUTHORIZED,
|
|
71848
71923
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -72099,12 +72174,12 @@ async function queryCodexAccount(deps = {}) {
|
|
|
72099
72174
|
}
|
|
72100
72175
|
|
|
72101
72176
|
// src/tools/pi-account.ts
|
|
72102
|
-
var
|
|
72103
|
-
var
|
|
72177
|
+
var import_node_fs64 = __toESM(require("fs"), 1);
|
|
72178
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
72104
72179
|
function readPiCredentials(agentDir) {
|
|
72105
72180
|
let raw;
|
|
72106
72181
|
try {
|
|
72107
|
-
raw = JSON.parse(
|
|
72182
|
+
raw = JSON.parse(import_node_fs64.default.readFileSync(import_node_path71.default.join(agentDir, "auth.json"), "utf8"));
|
|
72108
72183
|
} catch {
|
|
72109
72184
|
return {};
|
|
72110
72185
|
}
|
|
@@ -72187,81 +72262,6 @@ function buildEngineHandlers(deps, overrides = {}) {
|
|
|
72187
72262
|
return { "engine:status": status, "engine:connectPool": connectPool };
|
|
72188
72263
|
}
|
|
72189
72264
|
|
|
72190
|
-
// src/tools/subscription-channels-apply.ts
|
|
72191
|
-
var import_node_fs64 = __toESM(require("fs"), 1);
|
|
72192
|
-
var import_node_os25 = __toESM(require("os"), 1);
|
|
72193
|
-
var import_node_path71 = __toESM(require("path"), 1);
|
|
72194
|
-
var TABLE_HEADER = /^\s*\[\[?\s*([A-Za-z0-9_.-]+)\s*\]\]?\s*(?:#.*)?$/;
|
|
72195
|
-
var KEY_LINE = /^\s*([A-Za-z0-9_.-]+)\s*=/;
|
|
72196
|
-
function stripCodexProvider(text) {
|
|
72197
|
-
const out = [];
|
|
72198
|
-
let inProviderSection = false;
|
|
72199
|
-
for (const line of text.split("\n")) {
|
|
72200
|
-
const headerMatch = TABLE_HEADER.exec(line);
|
|
72201
|
-
if (headerMatch) {
|
|
72202
|
-
const section = headerMatch[1].trim();
|
|
72203
|
-
inProviderSection = section === "model_providers" || section.startsWith("model_providers.");
|
|
72204
|
-
if (inProviderSection) continue;
|
|
72205
|
-
out.push(line);
|
|
72206
|
-
continue;
|
|
72207
|
-
}
|
|
72208
|
-
if (inProviderSection) continue;
|
|
72209
|
-
const keyMatch = KEY_LINE.exec(line);
|
|
72210
|
-
if (keyMatch) {
|
|
72211
|
-
const key = keyMatch[1].trim();
|
|
72212
|
-
if (key === "model_provider" || key.startsWith("model_providers.")) {
|
|
72213
|
-
continue;
|
|
72214
|
-
}
|
|
72215
|
-
}
|
|
72216
|
-
out.push(line);
|
|
72217
|
-
}
|
|
72218
|
-
return out.join("\n").trim();
|
|
72219
|
-
}
|
|
72220
|
-
function applyCodexSubscriptionChannel(opts) {
|
|
72221
|
-
const codexHome = opts.codexHome || process.env.CODEX_HOME || import_node_path71.default.join(import_node_os25.default.homedir(), ".codex");
|
|
72222
|
-
import_node_fs64.default.mkdirSync(codexHome, { recursive: true });
|
|
72223
|
-
const configFile = import_node_path71.default.join(codexHome, "config.toml");
|
|
72224
|
-
const original = import_node_fs64.default.existsSync(configFile) ? import_node_fs64.default.readFileSync(configFile, "utf8") : "";
|
|
72225
|
-
const rest = stripCodexProvider(original);
|
|
72226
|
-
let content;
|
|
72227
|
-
if (opts.channel) {
|
|
72228
|
-
const ch = opts.channel;
|
|
72229
|
-
content = [
|
|
72230
|
-
'model_provider = "cliproxyapi"',
|
|
72231
|
-
...rest ? ["", rest] : [],
|
|
72232
|
-
"",
|
|
72233
|
-
"[model_providers.cliproxyapi]",
|
|
72234
|
-
'name = "cliproxyapi"',
|
|
72235
|
-
`base_url = ${JSON.stringify(ch.baseUrl)}`,
|
|
72236
|
-
'wire_api = "responses"',
|
|
72237
|
-
`auth = { command = "echo", args = [${JSON.stringify(ch.apiKey)}] }`,
|
|
72238
|
-
""
|
|
72239
|
-
].join("\n");
|
|
72240
|
-
} else {
|
|
72241
|
-
content = [
|
|
72242
|
-
'model_provider = "openai"',
|
|
72243
|
-
...rest ? ["", rest] : [],
|
|
72244
|
-
""
|
|
72245
|
-
].join("\n");
|
|
72246
|
-
}
|
|
72247
|
-
const tmpFile = `${configFile}.tmp.${Date.now()}`;
|
|
72248
|
-
import_node_fs64.default.writeFileSync(tmpFile, content, { mode: 384 });
|
|
72249
|
-
import_node_fs64.default.renameSync(tmpFile, configFile);
|
|
72250
|
-
}
|
|
72251
|
-
function applyPiSubscriptionChannel(opts) {
|
|
72252
|
-
const agentDir = opts.agentDir || process.env.PI_CODING_AGENT_DIR || import_node_path71.default.join(import_node_os25.default.homedir(), ".pi", "agent");
|
|
72253
|
-
if (!import_node_fs64.default.existsSync(agentDir)) return false;
|
|
72254
|
-
const configFile = import_node_path71.default.join(agentDir, "cliproxyapi.json");
|
|
72255
|
-
if (opts.channel) {
|
|
72256
|
-
const data = { baseUrl: opts.channel.baseUrl, apiKey: opts.channel.apiKey };
|
|
72257
|
-
const tmp = `${configFile}.tmp.${Date.now()}`;
|
|
72258
|
-
import_node_fs64.default.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
|
|
72259
|
-
import_node_fs64.default.renameSync(tmp, configFile);
|
|
72260
|
-
return true;
|
|
72261
|
-
}
|
|
72262
|
-
return false;
|
|
72263
|
-
}
|
|
72264
|
-
|
|
72265
72265
|
// src/handlers/channels.ts
|
|
72266
72266
|
function buildChannelsHandlers(deps) {
|
|
72267
72267
|
const get = async () => {
|
|
@@ -73264,7 +73264,7 @@ function computeMethodAccess(args) {
|
|
|
73264
73264
|
}
|
|
73265
73265
|
|
|
73266
73266
|
// src/version.ts
|
|
73267
|
-
var version = "0.2.
|
|
73267
|
+
var version = "0.2.604".length > 0 ? "0.2.604" : "dev";
|
|
73268
73268
|
|
|
73269
73269
|
// src/cli-probe/probe.ts
|
|
73270
73270
|
var fs83 = __toESM(require("fs"), 1);
|
|
@@ -75892,6 +75892,8 @@ async function startDaemon(config) {
|
|
|
75892
75892
|
let transport = null;
|
|
75893
75893
|
const personaStore = new PersonaStore(import_node_path84.default.join(config.dataDir, "personas"));
|
|
75894
75894
|
const subscriptionChannelStore = new SubscriptionChannelStore({ dataDir: config.dataDir });
|
|
75895
|
+
const activeSubscriptionChannel = subscriptionChannelStore.getActive();
|
|
75896
|
+
if (activeSubscriptionChannel) applyPiSubscriptionChannel({ channel: activeSubscriptionChannel });
|
|
75895
75897
|
const usersRoot = import_node_path84.default.join(config.dataDir, "users");
|
|
75896
75898
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
75897
75899
|
if (defaultsRoot) {
|