@clawos-dev/clawd 0.2.367 → 0.2.368
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 +1069 -1019
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -11151,7 +11151,7 @@ var require_transport = __commonJS({
|
|
|
11151
11151
|
"use strict";
|
|
11152
11152
|
var { createRequire: createRequire2 } = require("module");
|
|
11153
11153
|
var getCallers = require_caller();
|
|
11154
|
-
var { join: join17, isAbsolute: isAbsolute3, sep:
|
|
11154
|
+
var { join: join17, isAbsolute: isAbsolute3, sep: sep4 } = require("path");
|
|
11155
11155
|
var sleep2 = require_atomic_sleep();
|
|
11156
11156
|
var onExit = require_on_exit_leak_free();
|
|
11157
11157
|
var ThreadStream = require_thread_stream();
|
|
@@ -11259,7 +11259,7 @@ var require_transport = __commonJS({
|
|
|
11259
11259
|
let fixTarget2;
|
|
11260
11260
|
for (const filePath of callers) {
|
|
11261
11261
|
try {
|
|
11262
|
-
const context = filePath === "node:repl" ? process.cwd() +
|
|
11262
|
+
const context = filePath === "node:repl" ? process.cwd() + sep4 : filePath;
|
|
11263
11263
|
fixTarget2 = createRequire2(context).resolve(origin);
|
|
11264
11264
|
break;
|
|
11265
11265
|
} catch (err) {
|
|
@@ -14638,14 +14638,14 @@ var init_claude_history = __esm({
|
|
|
14638
14638
|
// src/tools/claude.ts
|
|
14639
14639
|
function probeViaWhich() {
|
|
14640
14640
|
try {
|
|
14641
|
-
const out = (0,
|
|
14642
|
-
if (out &&
|
|
14641
|
+
const out = (0, import_node_child_process4.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
14642
|
+
if (out && import_node_fs18.default.existsSync(out)) return out;
|
|
14643
14643
|
} catch {
|
|
14644
14644
|
}
|
|
14645
14645
|
return null;
|
|
14646
14646
|
}
|
|
14647
14647
|
async function probeClaude(env = process.env) {
|
|
14648
|
-
if (env.CLAUDE_BIN &&
|
|
14648
|
+
if (env.CLAUDE_BIN && import_node_fs18.default.existsSync(env.CLAUDE_BIN)) {
|
|
14649
14649
|
return { available: true, path: env.CLAUDE_BIN };
|
|
14650
14650
|
}
|
|
14651
14651
|
const w2 = probeViaWhich();
|
|
@@ -15114,13 +15114,13 @@ function encodeClaudeStdin(text) {
|
|
|
15114
15114
|
};
|
|
15115
15115
|
return JSON.stringify(frame) + "\n";
|
|
15116
15116
|
}
|
|
15117
|
-
var
|
|
15117
|
+
var import_node_child_process3, import_node_child_process4, import_node_fs18, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODEL_IDS, CLAUDE_MODELS, _assertModelIdsAligned, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
|
|
15118
15118
|
var init_claude = __esm({
|
|
15119
15119
|
"src/tools/claude.ts"() {
|
|
15120
15120
|
"use strict";
|
|
15121
|
-
|
|
15122
|
-
|
|
15123
|
-
|
|
15121
|
+
import_node_child_process3 = require("child_process");
|
|
15122
|
+
import_node_child_process4 = require("child_process");
|
|
15123
|
+
import_node_fs18 = __toESM(require("fs"), 1);
|
|
15124
15124
|
init_protocol();
|
|
15125
15125
|
init_claude_history();
|
|
15126
15126
|
init_tool_result_extra();
|
|
@@ -15249,7 +15249,7 @@ var init_claude = __esm({
|
|
|
15249
15249
|
spawn(ctx) {
|
|
15250
15250
|
const args = buildSpawnArgs(ctx);
|
|
15251
15251
|
const cmd = process.env.CLAUDE_BIN ?? "claude";
|
|
15252
|
-
const child = (0,
|
|
15252
|
+
const child = (0, import_node_child_process3.spawn)(cmd, args, {
|
|
15253
15253
|
cwd: ctx.cwd,
|
|
15254
15254
|
env: buildSpawnEnv(ctx.env),
|
|
15255
15255
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -23027,7 +23027,7 @@ var require_luxon = __commonJS({
|
|
|
23027
23027
|
}, zone || mergedZone, next];
|
|
23028
23028
|
}, [{}, null, 1]).slice(0, 2);
|
|
23029
23029
|
}
|
|
23030
|
-
function
|
|
23030
|
+
function parse2(s2, ...patterns) {
|
|
23031
23031
|
if (s2 == null) {
|
|
23032
23032
|
return [null, null];
|
|
23033
23033
|
}
|
|
@@ -23170,26 +23170,26 @@ var require_luxon = __commonJS({
|
|
|
23170
23170
|
var extractISOOrdinalDateAndTime = combineExtractors(extractISOOrdinalData, extractISOTime, extractISOOffset, extractIANAZone);
|
|
23171
23171
|
var extractISOTimeAndOffset = combineExtractors(extractISOTime, extractISOOffset, extractIANAZone);
|
|
23172
23172
|
function parseISODate(s2) {
|
|
23173
|
-
return
|
|
23173
|
+
return parse2(s2, [isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset], [isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDateAndTime], [isoTimeCombinedRegex, extractISOTimeAndOffset]);
|
|
23174
23174
|
}
|
|
23175
23175
|
function parseRFC2822Date(s2) {
|
|
23176
|
-
return
|
|
23176
|
+
return parse2(preprocessRFC2822(s2), [rfc2822, extractRFC2822]);
|
|
23177
23177
|
}
|
|
23178
23178
|
function parseHTTPDate(s2) {
|
|
23179
|
-
return
|
|
23179
|
+
return parse2(s2, [rfc1123, extractRFC1123Or850], [rfc850, extractRFC1123Or850], [ascii, extractASCII]);
|
|
23180
23180
|
}
|
|
23181
23181
|
function parseISODuration(s2) {
|
|
23182
|
-
return
|
|
23182
|
+
return parse2(s2, [isoDuration, extractISODuration]);
|
|
23183
23183
|
}
|
|
23184
23184
|
var extractISOTimeOnly = combineExtractors(extractISOTime);
|
|
23185
23185
|
function parseISOTimeOnly(s2) {
|
|
23186
|
-
return
|
|
23186
|
+
return parse2(s2, [isoTimeOnly, extractISOTimeOnly]);
|
|
23187
23187
|
}
|
|
23188
23188
|
var sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex);
|
|
23189
23189
|
var sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex);
|
|
23190
23190
|
var extractISOTimeOffsetAndIANAZone = combineExtractors(extractISOTime, extractISOOffset, extractIANAZone);
|
|
23191
23191
|
function parseSQL(s2) {
|
|
23192
|
-
return
|
|
23192
|
+
return parse2(s2, [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone]);
|
|
23193
23193
|
}
|
|
23194
23194
|
var INVALID$2 = "Invalid Duration";
|
|
23195
23195
|
var lowOrderMatrix = {
|
|
@@ -31541,7 +31541,7 @@ var require_extension = __commonJS({
|
|
|
31541
31541
|
if (dest[name] === void 0) dest[name] = [elem];
|
|
31542
31542
|
else dest[name].push(elem);
|
|
31543
31543
|
}
|
|
31544
|
-
function
|
|
31544
|
+
function parse2(header) {
|
|
31545
31545
|
const offers = /* @__PURE__ */ Object.create(null);
|
|
31546
31546
|
let params = /* @__PURE__ */ Object.create(null);
|
|
31547
31547
|
let mustUnescape = false;
|
|
@@ -31681,7 +31681,7 @@ var require_extension = __commonJS({
|
|
|
31681
31681
|
}).join(", ");
|
|
31682
31682
|
}).join(", ");
|
|
31683
31683
|
}
|
|
31684
|
-
module2.exports = { format, parse };
|
|
31684
|
+
module2.exports = { format, parse: parse2 };
|
|
31685
31685
|
}
|
|
31686
31686
|
});
|
|
31687
31687
|
|
|
@@ -31715,7 +31715,7 @@ var require_websocket = __commonJS({
|
|
|
31715
31715
|
var {
|
|
31716
31716
|
EventTarget: { addEventListener, removeEventListener }
|
|
31717
31717
|
} = require_event_target();
|
|
31718
|
-
var { format, parse } = require_extension();
|
|
31718
|
+
var { format, parse: parse2 } = require_extension();
|
|
31719
31719
|
var { toBuffer } = require_buffer_util();
|
|
31720
31720
|
var kAborted = /* @__PURE__ */ Symbol("kAborted");
|
|
31721
31721
|
var protocolVersions = [8, 13];
|
|
@@ -32384,7 +32384,7 @@ var require_websocket = __commonJS({
|
|
|
32384
32384
|
}
|
|
32385
32385
|
let extensions;
|
|
32386
32386
|
try {
|
|
32387
|
-
extensions =
|
|
32387
|
+
extensions = parse2(secWebSocketExtensions);
|
|
32388
32388
|
} catch (err) {
|
|
32389
32389
|
const message = "Invalid Sec-WebSocket-Extensions header";
|
|
32390
32390
|
abortHandshake(websocket, socket, message);
|
|
@@ -32674,7 +32674,7 @@ var require_subprotocol = __commonJS({
|
|
|
32674
32674
|
"../node_modules/.pnpm/ws@8.20.0/node_modules/ws/lib/subprotocol.js"(exports2, module2) {
|
|
32675
32675
|
"use strict";
|
|
32676
32676
|
var { tokenChars } = require_validation();
|
|
32677
|
-
function
|
|
32677
|
+
function parse2(header) {
|
|
32678
32678
|
const protocols = /* @__PURE__ */ new Set();
|
|
32679
32679
|
let start = -1;
|
|
32680
32680
|
let end = -1;
|
|
@@ -32710,7 +32710,7 @@ var require_subprotocol = __commonJS({
|
|
|
32710
32710
|
protocols.add(protocol);
|
|
32711
32711
|
return protocols;
|
|
32712
32712
|
}
|
|
32713
|
-
module2.exports = { parse };
|
|
32713
|
+
module2.exports = { parse: parse2 };
|
|
32714
32714
|
}
|
|
32715
32715
|
});
|
|
32716
32716
|
|
|
@@ -48181,6 +48181,13 @@ var fs10 = __toESM(require("fs"), 1);
|
|
|
48181
48181
|
var os5 = __toESM(require("os"), 1);
|
|
48182
48182
|
var path12 = __toESM(require("path"), 1);
|
|
48183
48183
|
init_protocol();
|
|
48184
|
+
var DEFAULT_TMP_ROOTS = () => [
|
|
48185
|
+
"/tmp",
|
|
48186
|
+
"/private/tmp",
|
|
48187
|
+
"/var/folders",
|
|
48188
|
+
"/private/var/folders",
|
|
48189
|
+
path12.resolve(os5.tmpdir())
|
|
48190
|
+
];
|
|
48184
48191
|
var ProjectsStore = class {
|
|
48185
48192
|
constructor(opts) {
|
|
48186
48193
|
this.opts = opts;
|
|
@@ -48197,7 +48204,7 @@ var ProjectsStore = class {
|
|
|
48197
48204
|
}
|
|
48198
48205
|
try {
|
|
48199
48206
|
const parsed = JSON.parse(raw);
|
|
48200
|
-
this.entries = (parsed.projects ?? []).map((p2) => ProjectEntry.parse(p2));
|
|
48207
|
+
this.entries = (parsed.projects ?? []).map((p2) => ProjectEntry.parse(p2)).filter((e) => this.isProjectablePath(e.path));
|
|
48201
48208
|
} catch (err) {
|
|
48202
48209
|
this.opts.logger?.warn("projects.json corrupt, rebuilding", { err: String(err) });
|
|
48203
48210
|
this.entries = [];
|
|
@@ -48213,8 +48220,27 @@ var ProjectsStore = class {
|
|
|
48213
48220
|
return path12.resolve(expanded);
|
|
48214
48221
|
}
|
|
48215
48222
|
isProjectablePath(p2) {
|
|
48216
|
-
const
|
|
48217
|
-
|
|
48223
|
+
const abs = this.normalize(p2);
|
|
48224
|
+
const rel = path12.relative(path12.resolve(this.opts.clawdDir), abs);
|
|
48225
|
+
const insideClawd = !(rel.startsWith("..") || path12.isAbsolute(rel));
|
|
48226
|
+
if (insideClawd) return false;
|
|
48227
|
+
if (abs === path12.resolve(os5.homedir()) || abs === path12.parse(abs).root) return false;
|
|
48228
|
+
for (const root of this.tmpRoots()) {
|
|
48229
|
+
if (abs === root || abs.startsWith(root.endsWith(path12.sep) ? root : root + path12.sep)) {
|
|
48230
|
+
return false;
|
|
48231
|
+
}
|
|
48232
|
+
}
|
|
48233
|
+
return true;
|
|
48234
|
+
}
|
|
48235
|
+
/** 层 2 的临时区根(缺省自适应,见构造器 opts.tmpRoots 注释) */
|
|
48236
|
+
tmpRoots() {
|
|
48237
|
+
if (this.opts.tmpRoots) return this.opts.tmpRoots;
|
|
48238
|
+
const defaults = DEFAULT_TMP_ROOTS();
|
|
48239
|
+
const clawd = path12.resolve(this.opts.clawdDir);
|
|
48240
|
+
const clawdItselfInTmp = defaults.some(
|
|
48241
|
+
(r) => clawd === r || clawd.startsWith(r + path12.sep)
|
|
48242
|
+
);
|
|
48243
|
+
return clawdItselfInTmp ? [] : defaults;
|
|
48218
48244
|
}
|
|
48219
48245
|
list() {
|
|
48220
48246
|
return [...this.entries];
|
|
@@ -48238,6 +48264,16 @@ var ProjectsStore = class {
|
|
|
48238
48264
|
this.entries.push(entry);
|
|
48239
48265
|
return entry;
|
|
48240
48266
|
}
|
|
48267
|
+
/**
|
|
48268
|
+
* 从 Codex / CC 全局历史播种(2026-08-18 老板拍板「完全对齐」):让终端里直接用
|
|
48269
|
+
* codex/claude 跑过、但从没在 clawd 建过会话的目录也出现在项目区,两边列表对得上。
|
|
48270
|
+
* 调用方传 session/external-scan 的 scanExternalSessions() 产物(它已过滤空会话与
|
|
48271
|
+
* 已不存在的目录);噪音由本模块的三层判据挡。
|
|
48272
|
+
*/
|
|
48273
|
+
seedFromExternal(candidates) {
|
|
48274
|
+
for (const c of candidates) this.add(c.cwd);
|
|
48275
|
+
this.save();
|
|
48276
|
+
}
|
|
48241
48277
|
seedFromSessions(files) {
|
|
48242
48278
|
for (const f of files) {
|
|
48243
48279
|
if (f.originOwnerPrincipalId) continue;
|
|
@@ -48248,29 +48284,479 @@ var ProjectsStore = class {
|
|
|
48248
48284
|
}
|
|
48249
48285
|
};
|
|
48250
48286
|
|
|
48287
|
+
// src/session/external-scan.ts
|
|
48288
|
+
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
48289
|
+
var import_promises = __toESM(require("fs/promises"), 1);
|
|
48290
|
+
var import_node_os7 = __toESM(require("os"), 1);
|
|
48291
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
48292
|
+
var import_node_module = require("module");
|
|
48293
|
+
|
|
48294
|
+
// src/tools/title-generator.ts
|
|
48295
|
+
var import_node_child_process = require("child_process");
|
|
48296
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
48297
|
+
var import_node_os6 = __toESM(require("os"), 1);
|
|
48298
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
48299
|
+
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
48300
|
+
var TITLE_MODEL_BY_TOOL = {
|
|
48301
|
+
claude: "haiku",
|
|
48302
|
+
codex: "gpt-5.4-mini"
|
|
48303
|
+
};
|
|
48304
|
+
var TITLE_INPUT_MAX_CHARS = 400;
|
|
48305
|
+
var DEFAULT_TITLE_GEN_TIMEOUT_MS = 45e3;
|
|
48306
|
+
var outFileSeq = 0;
|
|
48307
|
+
function buildTitlePrompt(firstMessage) {
|
|
48308
|
+
const text = firstMessage.slice(0, TITLE_INPUT_MAX_CHARS);
|
|
48309
|
+
return `\u4E3A\u4E0B\u9762\u8FD9\u6761\u7528\u6237\u6D88\u606F\u751F\u6210\u4E00\u4E2A\u7B80\u6D01\u7684\u4F1A\u8BDD\u6807\u9898\uFF1A\u4E0D\u8D85\u8FC7 20 \u4E2A\u5B57\uFF08\u82F1\u6587\u5219\u4E0D\u8D85\u8FC7 6 \u4E2A\u5355\u8BCD\uFF09\uFF0C\u4F7F\u7528\u4E0E\u6D88\u606F\u76F8\u540C\u7684\u8BED\u8A00\uFF0C\u53EA\u6982\u62EC\u6D88\u606F\u4E3B\u9898\u3002
|
|
48310
|
+
|
|
48311
|
+
\u7528\u6237\u6D88\u606F\uFF1A
|
|
48312
|
+
${text}`;
|
|
48313
|
+
}
|
|
48314
|
+
function buildClaudeTitlePrompt(firstMessage) {
|
|
48315
|
+
return buildTitlePrompt(firstMessage) + '\n\n\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u683C\u5F0F\uFF1A{"greeting":"\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC","title":"\u4F1A\u8BDD\u6807\u9898"}\uFF0C\u4E0D\u8981\u8F93\u51FA JSON \u4EE5\u5916\u7684\u4EFB\u4F55\u5185\u5BB9\u3002';
|
|
48316
|
+
}
|
|
48317
|
+
function sanitizeTitle(raw) {
|
|
48318
|
+
const line = raw.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
|
|
48319
|
+
if (!line) return null;
|
|
48320
|
+
const stripped = line.replace(/^["'“”‘’「」《》\[\((]+/, "").replace(/["'“”‘’「」《》\]\))]+$/, "").replace(/[。..!!??]+$/, "").replace(/\s+/g, " ").trim();
|
|
48321
|
+
if (!stripped) return null;
|
|
48322
|
+
return stripped.slice(0, 60);
|
|
48323
|
+
}
|
|
48324
|
+
function buildClaudeTitleArgs(prompt) {
|
|
48325
|
+
return ["-p", "--model", TITLE_MODEL_BY_TOOL.claude, prompt];
|
|
48326
|
+
}
|
|
48327
|
+
var CODEX_TITLE_SCHEMA = JSON.stringify({
|
|
48328
|
+
type: "object",
|
|
48329
|
+
properties: {
|
|
48330
|
+
greeting: { type: "string", description: "\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC" },
|
|
48331
|
+
title: { type: "string", description: "\u4F1A\u8BDD\u6807\u9898\uFF1A\u53EA\u542B\u6D88\u606F\u4E3B\u9898" }
|
|
48332
|
+
},
|
|
48333
|
+
required: ["greeting", "title"],
|
|
48334
|
+
additionalProperties: false
|
|
48335
|
+
});
|
|
48336
|
+
function parseTitleJson(raw) {
|
|
48337
|
+
const text = raw.trim().replace(/^```[a-zA-Z]*\s*/, "").replace(/```\s*$/, "").trim();
|
|
48338
|
+
try {
|
|
48339
|
+
const obj = JSON.parse(text);
|
|
48340
|
+
if (typeof obj.title === "string") return sanitizeTitle(obj.title);
|
|
48341
|
+
} catch {
|
|
48342
|
+
}
|
|
48343
|
+
return sanitizeTitle(text);
|
|
48344
|
+
}
|
|
48345
|
+
function buildCodexTitleArgs(prompt, outFile, schemaFile) {
|
|
48346
|
+
return [
|
|
48347
|
+
"exec",
|
|
48348
|
+
"--ephemeral",
|
|
48349
|
+
"--skip-git-repo-check",
|
|
48350
|
+
"--output-schema",
|
|
48351
|
+
schemaFile,
|
|
48352
|
+
"-s",
|
|
48353
|
+
"read-only",
|
|
48354
|
+
"-m",
|
|
48355
|
+
TITLE_MODEL_BY_TOOL.codex,
|
|
48356
|
+
"--color",
|
|
48357
|
+
"never",
|
|
48358
|
+
"-o",
|
|
48359
|
+
outFile,
|
|
48360
|
+
prompt
|
|
48361
|
+
];
|
|
48362
|
+
}
|
|
48363
|
+
async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
48364
|
+
if (tool !== "claude" && tool !== "codex") return null;
|
|
48365
|
+
const text = firstMessage.trim();
|
|
48366
|
+
if (!text) return null;
|
|
48367
|
+
let workDir;
|
|
48368
|
+
try {
|
|
48369
|
+
workDir = import_node_fs10.default.mkdtempSync(import_node_path10.default.join(import_node_os6.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
48370
|
+
} catch {
|
|
48371
|
+
return null;
|
|
48372
|
+
}
|
|
48373
|
+
const cleanupWorkDir = () => {
|
|
48374
|
+
try {
|
|
48375
|
+
import_node_fs10.default.rmSync(workDir, { recursive: true, force: true });
|
|
48376
|
+
} catch {
|
|
48377
|
+
}
|
|
48378
|
+
};
|
|
48379
|
+
const outFile = import_node_path10.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
48380
|
+
const schemaFile = import_node_path10.default.join(workDir, "title-schema.json");
|
|
48381
|
+
if (tool === "codex") {
|
|
48382
|
+
try {
|
|
48383
|
+
import_node_fs10.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
48384
|
+
} catch {
|
|
48385
|
+
cleanupWorkDir();
|
|
48386
|
+
return null;
|
|
48387
|
+
}
|
|
48388
|
+
}
|
|
48389
|
+
const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : process.env.CODEX_BIN ?? "codex";
|
|
48390
|
+
const args = tool === "claude" ? buildClaudeTitleArgs(buildClaudeTitlePrompt(text)) : buildCodexTitleArgs(buildTitlePrompt(text), outFile, schemaFile);
|
|
48391
|
+
const doSpawn = deps.spawnOverride ?? ((c, a, o) => (0, import_node_child_process.spawn)(c, a, { ...o, stdio: ["ignore", "pipe", "pipe"] }));
|
|
48392
|
+
const timeoutMs = deps.timeoutMs ?? DEFAULT_TITLE_GEN_TIMEOUT_MS;
|
|
48393
|
+
return await new Promise((resolve7) => {
|
|
48394
|
+
let proc;
|
|
48395
|
+
try {
|
|
48396
|
+
proc = doSpawn(cmd, args, { cwd: workDir });
|
|
48397
|
+
} catch (err) {
|
|
48398
|
+
deps.logger?.warn("title-gen spawn failed", { tool, message: err.message });
|
|
48399
|
+
cleanupWorkDir();
|
|
48400
|
+
return resolve7(null);
|
|
48401
|
+
}
|
|
48402
|
+
let stdout = "";
|
|
48403
|
+
let settled = false;
|
|
48404
|
+
const finish = (title) => {
|
|
48405
|
+
if (settled) return;
|
|
48406
|
+
settled = true;
|
|
48407
|
+
clearTimeout(timer);
|
|
48408
|
+
if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGKILL");
|
|
48409
|
+
cleanupWorkDir();
|
|
48410
|
+
resolve7(title);
|
|
48411
|
+
};
|
|
48412
|
+
const timer = setTimeout(() => {
|
|
48413
|
+
deps.logger?.warn("title-gen timed out", { tool, timeoutMs });
|
|
48414
|
+
finish(null);
|
|
48415
|
+
}, timeoutMs);
|
|
48416
|
+
proc.stdout?.on("data", (c) => {
|
|
48417
|
+
stdout += c.toString();
|
|
48418
|
+
});
|
|
48419
|
+
proc.stderr?.on("data", () => {
|
|
48420
|
+
});
|
|
48421
|
+
proc.on("error", (err) => {
|
|
48422
|
+
deps.logger?.warn("title-gen proc error", { tool, message: err.message });
|
|
48423
|
+
finish(null);
|
|
48424
|
+
});
|
|
48425
|
+
proc.on("close", (code) => {
|
|
48426
|
+
if (code !== 0) {
|
|
48427
|
+
deps.logger?.warn("title-gen exited non-zero", { tool, code });
|
|
48428
|
+
return finish(null);
|
|
48429
|
+
}
|
|
48430
|
+
if (tool === "claude") return finish(parseTitleJson(stdout));
|
|
48431
|
+
let fileText = "";
|
|
48432
|
+
try {
|
|
48433
|
+
fileText = import_node_fs10.default.readFileSync(outFile, "utf8");
|
|
48434
|
+
} catch {
|
|
48435
|
+
return finish(null);
|
|
48436
|
+
}
|
|
48437
|
+
finish(parseTitleJson(fileText));
|
|
48438
|
+
});
|
|
48439
|
+
});
|
|
48440
|
+
}
|
|
48441
|
+
|
|
48442
|
+
// src/session/external-scan.ts
|
|
48443
|
+
var import_node_child_process2 = require("child_process");
|
|
48444
|
+
var import_meta = {};
|
|
48445
|
+
function defaultRoots() {
|
|
48446
|
+
const home = import_node_os7.default.homedir();
|
|
48447
|
+
return {
|
|
48448
|
+
claudeProjectsDir: import_node_path11.default.join(home, ".claude", "projects"),
|
|
48449
|
+
codexDir: import_node_path11.default.join(home, ".codex"),
|
|
48450
|
+
clawdDir: import_node_path11.default.join(home, ".clawd")
|
|
48451
|
+
};
|
|
48452
|
+
}
|
|
48453
|
+
function width(s) {
|
|
48454
|
+
let w2 = 0;
|
|
48455
|
+
for (const ch of s) w2 += /[ᄀ-ᅟ⺀-가-힣豈-︰-﹏-⦆¢-₩]/.test(ch) ? 2 : 1;
|
|
48456
|
+
return w2;
|
|
48457
|
+
}
|
|
48458
|
+
function clipW(text, n) {
|
|
48459
|
+
const s = String(text ?? "").split(/\s+/).filter(Boolean).join(" ");
|
|
48460
|
+
if (width(s) <= n) return s;
|
|
48461
|
+
let out = "";
|
|
48462
|
+
let w2 = 0;
|
|
48463
|
+
for (const ch of s) {
|
|
48464
|
+
const cw = width(ch);
|
|
48465
|
+
if (w2 + cw > n - 1) break;
|
|
48466
|
+
out += ch;
|
|
48467
|
+
w2 += cw;
|
|
48468
|
+
}
|
|
48469
|
+
return out + "\u2026";
|
|
48470
|
+
}
|
|
48471
|
+
function toMs(v2) {
|
|
48472
|
+
const n = Number(v2 || 0);
|
|
48473
|
+
return n > 1e11 ? Math.round(n) : Math.round(n * 1e3);
|
|
48474
|
+
}
|
|
48475
|
+
function listFiles(dir, depth = 0, maxDepth = 8, out = []) {
|
|
48476
|
+
let entries;
|
|
48477
|
+
try {
|
|
48478
|
+
entries = import_node_fs11.default.readdirSync(dir, { withFileTypes: true });
|
|
48479
|
+
} catch {
|
|
48480
|
+
return out;
|
|
48481
|
+
}
|
|
48482
|
+
for (const e of entries) {
|
|
48483
|
+
const full = import_node_path11.default.join(dir, e.name);
|
|
48484
|
+
if (e.isDirectory()) {
|
|
48485
|
+
if (depth < maxDepth) listFiles(full, depth + 1, maxDepth, out);
|
|
48486
|
+
} else if (e.isFile()) {
|
|
48487
|
+
out.push(full);
|
|
48488
|
+
}
|
|
48489
|
+
}
|
|
48490
|
+
return out;
|
|
48491
|
+
}
|
|
48492
|
+
async function* jsonLines(file) {
|
|
48493
|
+
let raw;
|
|
48494
|
+
try {
|
|
48495
|
+
raw = await import_promises.default.readFile(file, "utf8");
|
|
48496
|
+
} catch {
|
|
48497
|
+
return;
|
|
48498
|
+
}
|
|
48499
|
+
for (const line of raw.split("\n")) {
|
|
48500
|
+
const t = line.trim();
|
|
48501
|
+
if (!t) continue;
|
|
48502
|
+
try {
|
|
48503
|
+
yield JSON.parse(t);
|
|
48504
|
+
} catch {
|
|
48505
|
+
}
|
|
48506
|
+
}
|
|
48507
|
+
}
|
|
48508
|
+
function userText(msg) {
|
|
48509
|
+
const content = msg && typeof msg === "object" ? msg.content : null;
|
|
48510
|
+
if (typeof content === "string") return content;
|
|
48511
|
+
if (Array.isArray(content)) {
|
|
48512
|
+
return content.map((b2) => b2 && b2.type === "text" ? String(b2.text ?? "") : "").join("");
|
|
48513
|
+
}
|
|
48514
|
+
return "";
|
|
48515
|
+
}
|
|
48516
|
+
function isDir(p2) {
|
|
48517
|
+
try {
|
|
48518
|
+
return import_node_fs11.default.statSync(p2).isDirectory();
|
|
48519
|
+
} catch {
|
|
48520
|
+
return false;
|
|
48521
|
+
}
|
|
48522
|
+
}
|
|
48523
|
+
async function scanClaude(roots) {
|
|
48524
|
+
const out = [];
|
|
48525
|
+
let dirs;
|
|
48526
|
+
try {
|
|
48527
|
+
dirs = import_node_fs11.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
|
|
48528
|
+
} catch {
|
|
48529
|
+
return out;
|
|
48530
|
+
}
|
|
48531
|
+
for (const d of dirs) {
|
|
48532
|
+
if (!d.isDirectory()) continue;
|
|
48533
|
+
let files;
|
|
48534
|
+
try {
|
|
48535
|
+
files = import_node_fs11.default.readdirSync(import_node_path11.default.join(roots.claudeProjectsDir, d.name));
|
|
48536
|
+
} catch {
|
|
48537
|
+
continue;
|
|
48538
|
+
}
|
|
48539
|
+
for (const name of files) {
|
|
48540
|
+
if (!name.endsWith(".jsonl")) continue;
|
|
48541
|
+
const file = import_node_path11.default.join(roots.claudeProjectsDir, d.name, name);
|
|
48542
|
+
let st;
|
|
48543
|
+
try {
|
|
48544
|
+
st = import_node_fs11.default.statSync(file);
|
|
48545
|
+
} catch {
|
|
48546
|
+
continue;
|
|
48547
|
+
}
|
|
48548
|
+
let cwd = "";
|
|
48549
|
+
let title = "";
|
|
48550
|
+
let firstUser = "";
|
|
48551
|
+
let turns = 0;
|
|
48552
|
+
let firstTs = 0;
|
|
48553
|
+
let lastTs = 0;
|
|
48554
|
+
let hasMainLine = false;
|
|
48555
|
+
for await (const rec4 of jsonLines(file)) {
|
|
48556
|
+
if (!cwd && typeof rec4.cwd === "string") cwd = rec4.cwd;
|
|
48557
|
+
if (typeof rec4.timestamp === "string") {
|
|
48558
|
+
const t = Date.parse(rec4.timestamp);
|
|
48559
|
+
if (Number.isFinite(t)) {
|
|
48560
|
+
firstTs ||= t;
|
|
48561
|
+
lastTs = t;
|
|
48562
|
+
}
|
|
48563
|
+
}
|
|
48564
|
+
if (rec4.type === "ai-title" && rec4.aiTitle) {
|
|
48565
|
+
title = String(rec4.aiTitle);
|
|
48566
|
+
continue;
|
|
48567
|
+
}
|
|
48568
|
+
if (rec4.type !== "user" && rec4.type !== "assistant") continue;
|
|
48569
|
+
if (!rec4.isSidechain) hasMainLine = true;
|
|
48570
|
+
if (rec4.type !== "user" || rec4.isSidechain || rec4.isMeta) continue;
|
|
48571
|
+
const text = userText(rec4.message || {});
|
|
48572
|
+
if (!text.trim() || text.trimStart().startsWith("<")) continue;
|
|
48573
|
+
turns += 1;
|
|
48574
|
+
firstUser ||= text;
|
|
48575
|
+
}
|
|
48576
|
+
const cand = {
|
|
48577
|
+
tool: "claude",
|
|
48578
|
+
toolSessionId: name.slice(0, -".jsonl".length),
|
|
48579
|
+
cwd,
|
|
48580
|
+
label: clipW(title || firstUser, 56),
|
|
48581
|
+
turns,
|
|
48582
|
+
createdMs: firstTs || st.mtimeMs,
|
|
48583
|
+
updatedMs: lastTs || st.mtimeMs,
|
|
48584
|
+
skip: ""
|
|
48585
|
+
};
|
|
48586
|
+
if (!hasMainLine) cand.skip = "subagent \u652F\u7EBF";
|
|
48587
|
+
else if (!cwd) cand.skip = "\u65E0 cwd";
|
|
48588
|
+
else if (import_node_path11.default.basename(cwd).startsWith(TITLE_GEN_DIR_PREFIX)) cand.skip = "\u6807\u9898\u751F\u6210\u4E34\u65F6\u4F1A\u8BDD";
|
|
48589
|
+
out.push(cand);
|
|
48590
|
+
}
|
|
48591
|
+
}
|
|
48592
|
+
return out;
|
|
48593
|
+
}
|
|
48594
|
+
async function countCodexTurns(rolloutPath) {
|
|
48595
|
+
if (!rolloutPath || !import_node_fs11.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
|
|
48596
|
+
let turns = 0;
|
|
48597
|
+
let first = "";
|
|
48598
|
+
for await (const rec4 of jsonLines(rolloutPath)) {
|
|
48599
|
+
const p2 = rec4.payload || {};
|
|
48600
|
+
if (p2.type !== "message" || p2.role !== "user") continue;
|
|
48601
|
+
const text = (p2.content || []).map((b2) => String(b2 && b2.text || "")).join("");
|
|
48602
|
+
if (!text.trim() || text.trimStart().startsWith("<")) continue;
|
|
48603
|
+
turns += 1;
|
|
48604
|
+
first ||= text;
|
|
48605
|
+
}
|
|
48606
|
+
return { turns, first };
|
|
48607
|
+
}
|
|
48608
|
+
function readCodexThreads(db) {
|
|
48609
|
+
const COLS = ["id", "cwd", "created_at", "updated_at", "name", "title", "preview", "first_user_message", "archived", "rollout_path"];
|
|
48610
|
+
try {
|
|
48611
|
+
const { DatabaseSync } = (0, import_node_module.createRequire)(import_meta.url)("node:sqlite");
|
|
48612
|
+
const conn = new DatabaseSync(db, { readOnly: true });
|
|
48613
|
+
try {
|
|
48614
|
+
const have = new Set(
|
|
48615
|
+
conn.prepare("PRAGMA table_info(threads)").all().map((r) => r.name)
|
|
48616
|
+
);
|
|
48617
|
+
if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
|
|
48618
|
+
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
48619
|
+
return conn.prepare(`SELECT ${sel} FROM threads`).all();
|
|
48620
|
+
} finally {
|
|
48621
|
+
conn.close();
|
|
48622
|
+
}
|
|
48623
|
+
} catch {
|
|
48624
|
+
}
|
|
48625
|
+
try {
|
|
48626
|
+
const info = (0, import_node_child_process2.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
|
|
48627
|
+
if (info.status !== 0) return null;
|
|
48628
|
+
const have = new Set(
|
|
48629
|
+
info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
|
|
48630
|
+
);
|
|
48631
|
+
if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
|
|
48632
|
+
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
48633
|
+
const res = (0, import_node_child_process2.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
|
|
48634
|
+
encoding: "utf8",
|
|
48635
|
+
maxBuffer: 64 * 1024 * 1024
|
|
48636
|
+
});
|
|
48637
|
+
if (res.status !== 0 || !res.stdout.trim()) return null;
|
|
48638
|
+
return JSON.parse(res.stdout);
|
|
48639
|
+
} catch {
|
|
48640
|
+
return null;
|
|
48641
|
+
}
|
|
48642
|
+
}
|
|
48643
|
+
async function codexFromRows(rows) {
|
|
48644
|
+
const out = [];
|
|
48645
|
+
for (const r of rows) {
|
|
48646
|
+
const updatedMs = toMs(r.updated_at);
|
|
48647
|
+
const { turns, first } = await countCodexTurns(String(r.rollout_path || ""));
|
|
48648
|
+
const label = clipW(r.name || r.title || r.preview || r.first_user_message || first, 56);
|
|
48649
|
+
const cand = {
|
|
48650
|
+
tool: "codex",
|
|
48651
|
+
toolSessionId: String(r.id),
|
|
48652
|
+
cwd: String(r.cwd || ""),
|
|
48653
|
+
label,
|
|
48654
|
+
turns,
|
|
48655
|
+
createdMs: toMs(r.created_at) || updatedMs,
|
|
48656
|
+
updatedMs,
|
|
48657
|
+
skip: ""
|
|
48658
|
+
};
|
|
48659
|
+
if (r.archived) cand.skip = "\u5DF2\u5F52\u6863";
|
|
48660
|
+
else if (!label) cand.skip = "\u7A7A\u4F1A\u8BDD";
|
|
48661
|
+
out.push(cand);
|
|
48662
|
+
}
|
|
48663
|
+
return out;
|
|
48664
|
+
}
|
|
48665
|
+
async function scanCodexRollouts(roots) {
|
|
48666
|
+
const out = [];
|
|
48667
|
+
for (const file of listFiles(import_node_path11.default.join(roots.codexDir, "sessions"))) {
|
|
48668
|
+
if (!file.endsWith(".jsonl")) continue;
|
|
48669
|
+
let st;
|
|
48670
|
+
try {
|
|
48671
|
+
st = import_node_fs11.default.statSync(file);
|
|
48672
|
+
} catch {
|
|
48673
|
+
continue;
|
|
48674
|
+
}
|
|
48675
|
+
let meta = null;
|
|
48676
|
+
for await (const rec4 of jsonLines(file)) {
|
|
48677
|
+
if (rec4.type === "session_meta") {
|
|
48678
|
+
meta = rec4.payload || {};
|
|
48679
|
+
break;
|
|
48680
|
+
}
|
|
48681
|
+
}
|
|
48682
|
+
const tid = meta && (meta.session_id || meta.id);
|
|
48683
|
+
if (!tid) continue;
|
|
48684
|
+
const { turns, first } = await countCodexTurns(file);
|
|
48685
|
+
const cand = {
|
|
48686
|
+
tool: "codex",
|
|
48687
|
+
toolSessionId: String(tid),
|
|
48688
|
+
cwd: String(meta?.cwd || ""),
|
|
48689
|
+
label: clipW(first, 56),
|
|
48690
|
+
turns,
|
|
48691
|
+
createdMs: st.mtimeMs,
|
|
48692
|
+
updatedMs: st.mtimeMs,
|
|
48693
|
+
skip: ""
|
|
48694
|
+
};
|
|
48695
|
+
if (!cand.cwd) cand.skip = "\u65E0 cwd";
|
|
48696
|
+
out.push(cand);
|
|
48697
|
+
}
|
|
48698
|
+
return out;
|
|
48699
|
+
}
|
|
48700
|
+
async function scanCodex(roots) {
|
|
48701
|
+
let dbs = [];
|
|
48702
|
+
try {
|
|
48703
|
+
dbs = import_node_fs11.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path11.default.join(roots.codexDir, n));
|
|
48704
|
+
} catch {
|
|
48705
|
+
}
|
|
48706
|
+
if (dbs.length) {
|
|
48707
|
+
const rows = readCodexThreads(dbs[dbs.length - 1]);
|
|
48708
|
+
if (rows) return codexFromRows(rows);
|
|
48709
|
+
}
|
|
48710
|
+
return scanCodexRollouts(roots);
|
|
48711
|
+
}
|
|
48712
|
+
async function scanExternalSessions(rootsIn) {
|
|
48713
|
+
const roots = { ...defaultRoots(), ...rootsIn };
|
|
48714
|
+
const personaRoot = import_node_path11.default.join(roots.clawdDir, "personas");
|
|
48715
|
+
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
48716
|
+
const out = [];
|
|
48717
|
+
for (const c of all) {
|
|
48718
|
+
if (c.skip) continue;
|
|
48719
|
+
if (c.turns < 1) continue;
|
|
48720
|
+
if (!c.cwd || !isDir(c.cwd)) continue;
|
|
48721
|
+
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path11.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path11.default.sep)) {
|
|
48722
|
+
continue;
|
|
48723
|
+
}
|
|
48724
|
+
out.push({
|
|
48725
|
+
tool: c.tool,
|
|
48726
|
+
cwd: c.cwd,
|
|
48727
|
+
toolSessionId: c.toolSessionId,
|
|
48728
|
+
...c.label ? { label: c.label } : {},
|
|
48729
|
+
createdAt: new Date(c.createdMs).toISOString(),
|
|
48730
|
+
updatedAt: new Date(c.updatedMs).toISOString(),
|
|
48731
|
+
turns: c.turns
|
|
48732
|
+
});
|
|
48733
|
+
}
|
|
48734
|
+
return out;
|
|
48735
|
+
}
|
|
48736
|
+
|
|
48251
48737
|
// src/persona/store.ts
|
|
48252
|
-
var
|
|
48253
|
-
var
|
|
48738
|
+
var fs13 = __toESM(require("fs"), 1);
|
|
48739
|
+
var path15 = __toESM(require("path"), 1);
|
|
48254
48740
|
init_protocol();
|
|
48255
48741
|
var PersonaStore = class {
|
|
48256
48742
|
constructor(root) {
|
|
48257
48743
|
this.root = root;
|
|
48258
|
-
|
|
48744
|
+
fs13.mkdirSync(root, { recursive: true });
|
|
48259
48745
|
}
|
|
48260
48746
|
root;
|
|
48261
48747
|
personaDir(personaId2) {
|
|
48262
|
-
return
|
|
48748
|
+
return path15.join(this.root, safeFileName(personaId2));
|
|
48263
48749
|
}
|
|
48264
48750
|
metaPath(personaId2) {
|
|
48265
|
-
return
|
|
48751
|
+
return path15.join(this.personaDir(personaId2), ".clawd", "persona.json");
|
|
48266
48752
|
}
|
|
48267
48753
|
claudeMdPath(personaId2) {
|
|
48268
|
-
return
|
|
48754
|
+
return path15.join(this.personaDir(personaId2), "CLAUDE.md");
|
|
48269
48755
|
}
|
|
48270
48756
|
// codex 原生读 cwd 的 AGENTS.md。人格双写镜像:claude 读 CLAUDE.md、codex 读 AGENTS.md,
|
|
48271
48757
|
// 两份内容恒一致,persona 切 tool 零迁移。
|
|
48272
48758
|
agentsMdPath(personaId2) {
|
|
48273
|
-
return
|
|
48759
|
+
return path15.join(this.personaDir(personaId2), "AGENTS.md");
|
|
48274
48760
|
}
|
|
48275
48761
|
/**
|
|
48276
48762
|
* persona 级 sandbox base 落盘路径 —— 故意放 `.clawd/` 而非 `.claude/`,让 CC 的 project
|
|
@@ -48279,11 +48765,11 @@ var PersonaStore = class {
|
|
|
48279
48765
|
* spawn 前 per-guest 动态拼到各自 session 目录的那份(base + 强制底座 + 本 guest userWorkDir carve)。
|
|
48280
48766
|
*/
|
|
48281
48767
|
sandboxSettingsPath(personaId2) {
|
|
48282
|
-
return
|
|
48768
|
+
return path15.join(this.personaDir(personaId2), ".clawd", "sandbox-settings.json");
|
|
48283
48769
|
}
|
|
48284
48770
|
write(persona, personality) {
|
|
48285
48771
|
const dir = this.personaDir(persona.personaId);
|
|
48286
|
-
|
|
48772
|
+
fs13.mkdirSync(path15.join(dir, ".clawd"), { recursive: true });
|
|
48287
48773
|
this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
|
|
48288
48774
|
this.atomicWrite(this.agentsMdPath(persona.personaId), personality);
|
|
48289
48775
|
this.writeSandboxSettings(persona.personaId, buildGuestSettingsV1());
|
|
@@ -48302,9 +48788,9 @@ var PersonaStore = class {
|
|
|
48302
48788
|
ensureAgentsMirror(personaId2) {
|
|
48303
48789
|
const claudeMd = this.claudeMdPath(personaId2);
|
|
48304
48790
|
const agentsMd = this.agentsMdPath(personaId2);
|
|
48305
|
-
if (!
|
|
48306
|
-
if (
|
|
48307
|
-
this.atomicWrite(agentsMd,
|
|
48791
|
+
if (!fs13.existsSync(claudeMd)) return false;
|
|
48792
|
+
if (fs13.existsSync(agentsMd)) return false;
|
|
48793
|
+
this.atomicWrite(agentsMd, fs13.readFileSync(claudeMd, "utf8"));
|
|
48308
48794
|
return true;
|
|
48309
48795
|
}
|
|
48310
48796
|
/**
|
|
@@ -48354,22 +48840,22 @@ var PersonaStore = class {
|
|
|
48354
48840
|
};
|
|
48355
48841
|
}
|
|
48356
48842
|
codexSandboxSettingsPath(personaId2) {
|
|
48357
|
-
return
|
|
48843
|
+
return path15.join(this.personaDir(personaId2), ".clawd", "codex-sandbox.json");
|
|
48358
48844
|
}
|
|
48359
48845
|
/** 读 codex-sandbox.json;不存在/损坏 → null。 */
|
|
48360
48846
|
readCodexSandboxSettings(personaId2) {
|
|
48361
48847
|
const p2 = this.codexSandboxSettingsPath(personaId2);
|
|
48362
|
-
if (!
|
|
48848
|
+
if (!fs13.existsSync(p2)) return null;
|
|
48363
48849
|
try {
|
|
48364
|
-
return CodexSandboxSettingsSchema.parse(JSON.parse(
|
|
48850
|
+
return CodexSandboxSettingsSchema.parse(JSON.parse(fs13.readFileSync(p2, "utf8")));
|
|
48365
48851
|
} catch {
|
|
48366
48852
|
return null;
|
|
48367
48853
|
}
|
|
48368
48854
|
}
|
|
48369
48855
|
/** 覆盖写 codex-sandbox.json(seed/migrate 用)。 */
|
|
48370
48856
|
writeCodexSandboxSettings(personaId2, settings) {
|
|
48371
|
-
const dir =
|
|
48372
|
-
|
|
48857
|
+
const dir = path15.join(this.personaDir(personaId2), ".clawd");
|
|
48858
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
48373
48859
|
this.atomicWrite(this.codexSandboxSettingsPath(personaId2), JSON.stringify(settings, null, 2));
|
|
48374
48860
|
}
|
|
48375
48861
|
writeMeta(persona) {
|
|
@@ -48377,8 +48863,8 @@ var PersonaStore = class {
|
|
|
48377
48863
|
}
|
|
48378
48864
|
read(personaId2) {
|
|
48379
48865
|
const p2 = this.metaPath(personaId2);
|
|
48380
|
-
if (!
|
|
48381
|
-
const raw = JSON.parse(
|
|
48866
|
+
if (!fs13.existsSync(p2)) return null;
|
|
48867
|
+
const raw = JSON.parse(fs13.readFileSync(p2, "utf8"));
|
|
48382
48868
|
if (raw && typeof raw === "object" && "tokenMap" in raw) {
|
|
48383
48869
|
delete raw.tokenMap;
|
|
48384
48870
|
this.atomicWrite(p2, JSON.stringify(raw, null, 2));
|
|
@@ -48386,13 +48872,13 @@ var PersonaStore = class {
|
|
|
48386
48872
|
return PersonaFileSchema.parse(raw);
|
|
48387
48873
|
}
|
|
48388
48874
|
has(personaId2) {
|
|
48389
|
-
return
|
|
48875
|
+
return fs13.existsSync(this.metaPath(personaId2));
|
|
48390
48876
|
}
|
|
48391
48877
|
readPersonality(personaId2) {
|
|
48392
48878
|
const claudeMd = this.claudeMdPath(personaId2);
|
|
48393
|
-
if (
|
|
48879
|
+
if (fs13.existsSync(claudeMd)) return fs13.readFileSync(claudeMd, "utf8");
|
|
48394
48880
|
const agentsMd = this.agentsMdPath(personaId2);
|
|
48395
|
-
if (
|
|
48881
|
+
if (fs13.existsSync(agentsMd)) return fs13.readFileSync(agentsMd, "utf8");
|
|
48396
48882
|
return null;
|
|
48397
48883
|
}
|
|
48398
48884
|
/**
|
|
@@ -48401,23 +48887,23 @@ var PersonaStore = class {
|
|
|
48401
48887
|
*/
|
|
48402
48888
|
readSandboxSettings(personaId2) {
|
|
48403
48889
|
const p2 = this.sandboxSettingsPath(personaId2);
|
|
48404
|
-
if (!
|
|
48890
|
+
if (!fs13.existsSync(p2)) return null;
|
|
48405
48891
|
try {
|
|
48406
|
-
return JSON.parse(
|
|
48892
|
+
return JSON.parse(fs13.readFileSync(p2, "utf8"));
|
|
48407
48893
|
} catch {
|
|
48408
48894
|
return null;
|
|
48409
48895
|
}
|
|
48410
48896
|
}
|
|
48411
48897
|
/** Persona 私有 skills 目录路径:<personaDir>/.claude/skills */
|
|
48412
48898
|
skillsDir(personaId2) {
|
|
48413
|
-
return
|
|
48899
|
+
return path15.join(this.personaDir(personaId2), ".claude", "skills");
|
|
48414
48900
|
}
|
|
48415
48901
|
/**
|
|
48416
48902
|
* Claude Code 项目级 settings 路径:`<personaDir>/.claude/settings.json`。
|
|
48417
48903
|
* 这里只读 `enabledPlugins` 字段,由 owner 通过 CC `/plugin` 之类命令维护,daemon 不写。
|
|
48418
48904
|
*/
|
|
48419
48905
|
claudeSettingsPath(personaId2) {
|
|
48420
|
-
return
|
|
48906
|
+
return path15.join(this.personaDir(personaId2), ".claude", "settings.json");
|
|
48421
48907
|
}
|
|
48422
48908
|
/**
|
|
48423
48909
|
* 读取 persona 的 `.claude/settings.json` 中 `enabledPlugins` map,把 value === true
|
|
@@ -48432,10 +48918,10 @@ var PersonaStore = class {
|
|
|
48432
48918
|
*/
|
|
48433
48919
|
readEnabledPlugins(personaId2) {
|
|
48434
48920
|
const p2 = this.claudeSettingsPath(personaId2);
|
|
48435
|
-
if (!
|
|
48921
|
+
if (!fs13.existsSync(p2)) return [];
|
|
48436
48922
|
let raw;
|
|
48437
48923
|
try {
|
|
48438
|
-
raw = JSON.parse(
|
|
48924
|
+
raw = JSON.parse(fs13.readFileSync(p2, "utf8"));
|
|
48439
48925
|
} catch {
|
|
48440
48926
|
return [];
|
|
48441
48927
|
}
|
|
@@ -48449,22 +48935,22 @@ var PersonaStore = class {
|
|
|
48449
48935
|
return out;
|
|
48450
48936
|
}
|
|
48451
48937
|
list() {
|
|
48452
|
-
if (!
|
|
48453
|
-
return
|
|
48454
|
-
return
|
|
48938
|
+
if (!fs13.existsSync(this.root)) return [];
|
|
48939
|
+
return fs13.readdirSync(this.root).filter((name) => {
|
|
48940
|
+
return fs13.existsSync(path15.join(this.root, name, ".clawd", "persona.json"));
|
|
48455
48941
|
});
|
|
48456
48942
|
}
|
|
48457
48943
|
remove(personaId2) {
|
|
48458
48944
|
const dir = this.personaDir(personaId2);
|
|
48459
|
-
if (
|
|
48945
|
+
if (fs13.existsSync(dir)) fs13.rmSync(dir, { recursive: true, force: true });
|
|
48460
48946
|
}
|
|
48461
48947
|
personaDirPath(personaId2) {
|
|
48462
48948
|
return this.personaDir(personaId2);
|
|
48463
48949
|
}
|
|
48464
48950
|
atomicWrite(file, content) {
|
|
48465
48951
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
48466
|
-
|
|
48467
|
-
|
|
48952
|
+
fs13.writeFileSync(tmp, content, { mode: 384 });
|
|
48953
|
+
fs13.renameSync(tmp, file);
|
|
48468
48954
|
}
|
|
48469
48955
|
};
|
|
48470
48956
|
|
|
@@ -48507,9 +48993,9 @@ var PersonaRegistry = class {
|
|
|
48507
48993
|
};
|
|
48508
48994
|
|
|
48509
48995
|
// src/skills/scanner.ts
|
|
48510
|
-
var
|
|
48511
|
-
var
|
|
48512
|
-
var
|
|
48996
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
48997
|
+
var import_node_os8 = __toESM(require("os"), 1);
|
|
48998
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
48513
48999
|
|
|
48514
49000
|
// src/skills/frontmatter.ts
|
|
48515
49001
|
var STRIP_QUOTES = /^["']|["']$/g;
|
|
@@ -48618,7 +49104,7 @@ function parseDescription(content) {
|
|
|
48618
49104
|
}
|
|
48619
49105
|
function isDirLikeSync(p2) {
|
|
48620
49106
|
try {
|
|
48621
|
-
return
|
|
49107
|
+
return import_node_fs12.default.statSync(p2).isDirectory();
|
|
48622
49108
|
} catch {
|
|
48623
49109
|
return false;
|
|
48624
49110
|
}
|
|
@@ -48626,19 +49112,19 @@ function isDirLikeSync(p2) {
|
|
|
48626
49112
|
function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
48627
49113
|
let entries;
|
|
48628
49114
|
try {
|
|
48629
|
-
entries =
|
|
49115
|
+
entries = import_node_fs12.default.readdirSync(dir, { withFileTypes: true });
|
|
48630
49116
|
} catch {
|
|
48631
49117
|
return;
|
|
48632
49118
|
}
|
|
48633
49119
|
for (const ent of entries) {
|
|
48634
|
-
const entryPath =
|
|
49120
|
+
const entryPath = import_node_path12.default.join(dir, ent.name);
|
|
48635
49121
|
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
48636
49122
|
let content;
|
|
48637
49123
|
try {
|
|
48638
|
-
content =
|
|
49124
|
+
content = import_node_fs12.default.readFileSync(import_node_path12.default.join(entryPath, "SKILL.md"), "utf8");
|
|
48639
49125
|
} catch {
|
|
48640
49126
|
try {
|
|
48641
|
-
content =
|
|
49127
|
+
content = import_node_fs12.default.readFileSync(import_node_path12.default.join(entryPath, "skill.md"), "utf8");
|
|
48642
49128
|
} catch {
|
|
48643
49129
|
continue;
|
|
48644
49130
|
}
|
|
@@ -48662,26 +49148,26 @@ function listSkillsForDir(dir, source) {
|
|
|
48662
49148
|
function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
48663
49149
|
let entries;
|
|
48664
49150
|
try {
|
|
48665
|
-
entries =
|
|
49151
|
+
entries = import_node_fs12.default.readdirSync(dir, { withFileTypes: true });
|
|
48666
49152
|
} catch {
|
|
48667
49153
|
return;
|
|
48668
49154
|
}
|
|
48669
49155
|
for (const ent of entries) {
|
|
48670
|
-
const entryPath =
|
|
49156
|
+
const entryPath = import_node_path12.default.join(dir, ent.name);
|
|
48671
49157
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
48672
49158
|
const ns = ent.name;
|
|
48673
49159
|
let subEntries;
|
|
48674
49160
|
try {
|
|
48675
|
-
subEntries =
|
|
49161
|
+
subEntries = import_node_fs12.default.readdirSync(entryPath, { withFileTypes: true });
|
|
48676
49162
|
} catch {
|
|
48677
49163
|
continue;
|
|
48678
49164
|
}
|
|
48679
49165
|
for (const se of subEntries) {
|
|
48680
49166
|
if (!se.name.endsWith(".md")) continue;
|
|
48681
|
-
const sePath =
|
|
49167
|
+
const sePath = import_node_path12.default.join(entryPath, se.name);
|
|
48682
49168
|
let content;
|
|
48683
49169
|
try {
|
|
48684
|
-
content =
|
|
49170
|
+
content = import_node_fs12.default.readFileSync(sePath, "utf8");
|
|
48685
49171
|
} catch {
|
|
48686
49172
|
continue;
|
|
48687
49173
|
}
|
|
@@ -48698,7 +49184,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
48698
49184
|
} else if (ent.name.endsWith(".md")) {
|
|
48699
49185
|
let content;
|
|
48700
49186
|
try {
|
|
48701
|
-
content =
|
|
49187
|
+
content = import_node_fs12.default.readFileSync(entryPath, "utf8");
|
|
48702
49188
|
} catch {
|
|
48703
49189
|
continue;
|
|
48704
49190
|
}
|
|
@@ -48714,10 +49200,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
48714
49200
|
}
|
|
48715
49201
|
}
|
|
48716
49202
|
function readInstalledPlugins(home) {
|
|
48717
|
-
const file =
|
|
49203
|
+
const file = import_node_path12.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
48718
49204
|
let raw;
|
|
48719
49205
|
try {
|
|
48720
|
-
raw =
|
|
49206
|
+
raw = import_node_fs12.default.readFileSync(file, "utf8");
|
|
48721
49207
|
} catch {
|
|
48722
49208
|
return [];
|
|
48723
49209
|
}
|
|
@@ -48742,7 +49228,7 @@ var SkillsScanner = class {
|
|
|
48742
49228
|
home;
|
|
48743
49229
|
extraPluginRoots;
|
|
48744
49230
|
constructor(opts = {}) {
|
|
48745
|
-
this.home = opts.home ??
|
|
49231
|
+
this.home = opts.home ?? import_node_os8.default.homedir();
|
|
48746
49232
|
this.extraPluginRoots = opts.extraPluginRoots ?? [];
|
|
48747
49233
|
}
|
|
48748
49234
|
/**
|
|
@@ -48765,14 +49251,14 @@ var SkillsScanner = class {
|
|
|
48765
49251
|
});
|
|
48766
49252
|
}
|
|
48767
49253
|
const fsBlock = [];
|
|
48768
|
-
scanSkillDir(
|
|
48769
|
-
scanCommandDir(
|
|
48770
|
-
scanSkillDir(
|
|
48771
|
-
scanCommandDir(
|
|
49254
|
+
scanSkillDir(import_node_path12.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
|
|
49255
|
+
scanCommandDir(import_node_path12.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
|
|
49256
|
+
scanSkillDir(import_node_path12.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
|
|
49257
|
+
scanCommandDir(import_node_path12.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
|
|
48772
49258
|
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
48773
49259
|
for (const { name, root } of plugins) {
|
|
48774
|
-
scanSkillDir(
|
|
48775
|
-
scanCommandDir(
|
|
49260
|
+
scanSkillDir(import_node_path12.default.join(root, "skills"), "plugin", seen, fsBlock, name);
|
|
49261
|
+
scanCommandDir(import_node_path12.default.join(root, "commands"), "plugin", seen, fsBlock, name);
|
|
48776
49262
|
}
|
|
48777
49263
|
fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
|
|
48778
49264
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -48876,10 +49362,10 @@ var PersonaManager = class {
|
|
|
48876
49362
|
};
|
|
48877
49363
|
|
|
48878
49364
|
// src/persona/seed.ts
|
|
48879
|
-
var
|
|
48880
|
-
var
|
|
49365
|
+
var fs15 = __toESM(require("fs"), 1);
|
|
49366
|
+
var path17 = __toESM(require("path"), 1);
|
|
48881
49367
|
var import_node_url = require("url");
|
|
48882
|
-
var
|
|
49368
|
+
var import_meta2 = {};
|
|
48883
49369
|
var DEFAULT_BYPASS_PROFILE = {
|
|
48884
49370
|
permissions: { defaultMode: "bypassPermissions" }
|
|
48885
49371
|
};
|
|
@@ -49053,24 +49539,24 @@ function bundleSiblingFromArgv(argv1, sibling) {
|
|
|
49053
49539
|
if (!argv1) return null;
|
|
49054
49540
|
let real = argv1;
|
|
49055
49541
|
try {
|
|
49056
|
-
real =
|
|
49542
|
+
real = fs15.realpathSync(argv1);
|
|
49057
49543
|
} catch {
|
|
49058
49544
|
}
|
|
49059
|
-
return
|
|
49545
|
+
return path17.resolve(path17.dirname(real), sibling);
|
|
49060
49546
|
}
|
|
49061
49547
|
function findDefaultsRoot(logger) {
|
|
49062
49548
|
const candidates = [];
|
|
49063
49549
|
try {
|
|
49064
|
-
const here =
|
|
49065
|
-
candidates.push(
|
|
49066
|
-
candidates.push(
|
|
49550
|
+
const here = path17.dirname((0, import_node_url.fileURLToPath)(import_meta2.url));
|
|
49551
|
+
candidates.push(path17.resolve(here, "defaults"));
|
|
49552
|
+
candidates.push(path17.resolve(here, "persona-defaults"));
|
|
49067
49553
|
} catch {
|
|
49068
49554
|
}
|
|
49069
49555
|
const fromArgv = bundleSiblingFromArgv(process.argv[1], "persona-defaults");
|
|
49070
49556
|
if (fromArgv) candidates.push(fromArgv);
|
|
49071
49557
|
for (const c of candidates) {
|
|
49072
49558
|
try {
|
|
49073
|
-
if (
|
|
49559
|
+
if (fs15.statSync(c).isDirectory()) {
|
|
49074
49560
|
logger?.info("persona.defaults-root.resolved", { root: c });
|
|
49075
49561
|
return c;
|
|
49076
49562
|
}
|
|
@@ -49087,8 +49573,8 @@ function seedDefaultPersonas(args) {
|
|
|
49087
49573
|
args.logger.info("persona.seed.skip", { personaId: entry.personaId, reason: "exists" });
|
|
49088
49574
|
continue;
|
|
49089
49575
|
}
|
|
49090
|
-
const bundleDir =
|
|
49091
|
-
if (!
|
|
49576
|
+
const bundleDir = path17.join(args.defaultsRoot, entry.personaId);
|
|
49577
|
+
if (!fs15.existsSync(bundleDir)) {
|
|
49092
49578
|
args.logger.warn("persona.seed.skip", {
|
|
49093
49579
|
personaId: entry.personaId,
|
|
49094
49580
|
reason: "bundle-missing",
|
|
@@ -49096,8 +49582,8 @@ function seedDefaultPersonas(args) {
|
|
|
49096
49582
|
});
|
|
49097
49583
|
continue;
|
|
49098
49584
|
}
|
|
49099
|
-
const claudeMdPath =
|
|
49100
|
-
if (!
|
|
49585
|
+
const claudeMdPath = path17.join(bundleDir, "CLAUDE.md");
|
|
49586
|
+
if (!fs15.existsSync(claudeMdPath)) {
|
|
49101
49587
|
args.logger.warn("persona.seed.skip", {
|
|
49102
49588
|
personaId: entry.personaId,
|
|
49103
49589
|
reason: "no-CLAUDE.md",
|
|
@@ -49105,7 +49591,7 @@ function seedDefaultPersonas(args) {
|
|
|
49105
49591
|
});
|
|
49106
49592
|
continue;
|
|
49107
49593
|
}
|
|
49108
|
-
const personality =
|
|
49594
|
+
const personality = fs15.readFileSync(claudeMdPath, "utf8");
|
|
49109
49595
|
const now = Date.now();
|
|
49110
49596
|
const persona = {
|
|
49111
49597
|
personaId: entry.personaId,
|
|
@@ -49132,51 +49618,51 @@ function seedDefaultPersonas(args) {
|
|
|
49132
49618
|
}
|
|
49133
49619
|
}
|
|
49134
49620
|
function skipNodeModulesUnder(srcRoot) {
|
|
49135
|
-
return (src) => !
|
|
49621
|
+
return (src) => !path17.relative(srcRoot, src).split(path17.sep).includes("node_modules");
|
|
49136
49622
|
}
|
|
49137
49623
|
function copyBundleExtras(srcDir, dstDir) {
|
|
49138
|
-
for (const entry of
|
|
49624
|
+
for (const entry of fs15.readdirSync(srcDir, { withFileTypes: true })) {
|
|
49139
49625
|
if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
|
|
49140
|
-
const srcPath =
|
|
49141
|
-
const dstPath =
|
|
49626
|
+
const srcPath = path17.join(srcDir, entry.name);
|
|
49627
|
+
const dstPath = path17.join(dstDir, entry.name);
|
|
49142
49628
|
if (entry.isDirectory()) {
|
|
49143
|
-
|
|
49629
|
+
fs15.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
|
|
49144
49630
|
} else if (entry.isFile()) {
|
|
49145
|
-
|
|
49631
|
+
fs15.copyFileSync(srcPath, dstPath);
|
|
49146
49632
|
}
|
|
49147
49633
|
}
|
|
49148
49634
|
}
|
|
49149
49635
|
var DAEMON_MANAGED_PATHS = ["extension-kit", "CLAUDE.md", ".mcp.json", ".claude/skills"];
|
|
49150
49636
|
function replaceManagedPath(src, dst) {
|
|
49151
|
-
if (!
|
|
49152
|
-
|
|
49153
|
-
|
|
49154
|
-
|
|
49637
|
+
if (!fs15.statSync(src).isDirectory()) {
|
|
49638
|
+
fs15.mkdirSync(path17.dirname(dst), { recursive: true });
|
|
49639
|
+
fs15.rmSync(dst, { recursive: true, force: true });
|
|
49640
|
+
fs15.cpSync(src, dst, { dereference: true });
|
|
49155
49641
|
return;
|
|
49156
49642
|
}
|
|
49157
|
-
|
|
49158
|
-
for (const e of
|
|
49643
|
+
fs15.mkdirSync(dst, { recursive: true });
|
|
49644
|
+
for (const e of fs15.readdirSync(src, { withFileTypes: true })) {
|
|
49159
49645
|
if (e.name === "node_modules") continue;
|
|
49160
|
-
const child =
|
|
49161
|
-
|
|
49162
|
-
|
|
49646
|
+
const child = path17.join(dst, e.name);
|
|
49647
|
+
fs15.rmSync(child, { recursive: true, force: true });
|
|
49648
|
+
fs15.cpSync(path17.join(src, e.name), child, { recursive: true, dereference: true });
|
|
49163
49649
|
}
|
|
49164
49650
|
}
|
|
49165
49651
|
function refreshDaemonManagedDirs(args) {
|
|
49166
49652
|
const entries = args.entries ?? DEFAULT_PERSONAS;
|
|
49167
49653
|
for (const entry of entries) {
|
|
49168
|
-
const bundleDir =
|
|
49169
|
-
if (!
|
|
49654
|
+
const bundleDir = path17.join(args.defaultsRoot, entry.personaId);
|
|
49655
|
+
if (!fs15.existsSync(bundleDir)) continue;
|
|
49170
49656
|
const personaDir = args.store.personaDirPath(entry.personaId);
|
|
49171
|
-
if (!
|
|
49657
|
+
if (!fs15.existsSync(personaDir)) continue;
|
|
49172
49658
|
for (const relPath of DAEMON_MANAGED_PATHS) {
|
|
49173
|
-
const srcPath =
|
|
49174
|
-
if (!
|
|
49175
|
-
const dstPath =
|
|
49659
|
+
const srcPath = path17.join(bundleDir, relPath);
|
|
49660
|
+
if (!fs15.existsSync(srcPath)) continue;
|
|
49661
|
+
const dstPath = path17.join(personaDir, relPath);
|
|
49176
49662
|
try {
|
|
49177
49663
|
replaceManagedPath(srcPath, dstPath);
|
|
49178
49664
|
if (relPath === "CLAUDE.md") {
|
|
49179
|
-
replaceManagedPath(srcPath,
|
|
49665
|
+
replaceManagedPath(srcPath, path17.join(personaDir, "AGENTS.md"));
|
|
49180
49666
|
}
|
|
49181
49667
|
args.logger.info("persona.refresh.synced", {
|
|
49182
49668
|
personaId: entry.personaId,
|
|
@@ -49276,7 +49762,7 @@ function migrateSandboxAllowRead(args) {
|
|
|
49276
49762
|
for (const personaId2 of args.store.list()) {
|
|
49277
49763
|
try {
|
|
49278
49764
|
const readPath = tildePath(args.store.personaDirPath(personaId2));
|
|
49279
|
-
if (!
|
|
49765
|
+
if (!fs15.existsSync(args.store.sandboxSettingsPath(personaId2))) {
|
|
49280
49766
|
args.store.writeSandboxSettings(personaId2, buildGuestSettingsV1());
|
|
49281
49767
|
n++;
|
|
49282
49768
|
continue;
|
|
@@ -49319,13 +49805,13 @@ var PERSONA_BUILDER_TOMBSTONE = `${PERSONA_BUILDER_TOMBSTONE_MARKER}
|
|
|
49319
49805
|
function containsAnyFile(dir) {
|
|
49320
49806
|
let entries;
|
|
49321
49807
|
try {
|
|
49322
|
-
entries =
|
|
49808
|
+
entries = fs15.readdirSync(dir, { withFileTypes: true });
|
|
49323
49809
|
} catch {
|
|
49324
49810
|
return false;
|
|
49325
49811
|
}
|
|
49326
49812
|
for (const e of entries) {
|
|
49327
49813
|
if (e.isDirectory()) {
|
|
49328
|
-
if (containsAnyFile(
|
|
49814
|
+
if (containsAnyFile(path17.join(dir, e.name))) return true;
|
|
49329
49815
|
} else {
|
|
49330
49816
|
return true;
|
|
49331
49817
|
}
|
|
@@ -49334,9 +49820,9 @@ function containsAnyFile(dir) {
|
|
|
49334
49820
|
}
|
|
49335
49821
|
function retirePersonaBuilder(args) {
|
|
49336
49822
|
const dir = args.store.personaDirPath(PERSONA_BUILDER_ID);
|
|
49337
|
-
if (!
|
|
49823
|
+
if (!fs15.existsSync(dir)) return;
|
|
49338
49824
|
try {
|
|
49339
|
-
const used = containsAnyFile(
|
|
49825
|
+
const used = containsAnyFile(path17.join(dir, ".clawd", "sessions")) || containsAnyFile(path17.join(dir, ".claude", "skills")) || containsAnyFile(path17.join(dir, "projects"));
|
|
49340
49826
|
if (!used) {
|
|
49341
49827
|
args.store.remove(PERSONA_BUILDER_ID);
|
|
49342
49828
|
args.logger.info("persona.retire-builder.removed", { personaId: PERSONA_BUILDER_ID });
|
|
@@ -49344,10 +49830,10 @@ function retirePersonaBuilder(args) {
|
|
|
49344
49830
|
}
|
|
49345
49831
|
let wrote = false;
|
|
49346
49832
|
for (const name of ["CLAUDE.md", "AGENTS.md"]) {
|
|
49347
|
-
const p2 =
|
|
49348
|
-
const cur =
|
|
49833
|
+
const p2 = path17.join(dir, name);
|
|
49834
|
+
const cur = fs15.existsSync(p2) ? fs15.readFileSync(p2, "utf8") : null;
|
|
49349
49835
|
if (cur?.startsWith(PERSONA_BUILDER_TOMBSTONE_MARKER)) continue;
|
|
49350
|
-
|
|
49836
|
+
fs15.writeFileSync(p2, PERSONA_BUILDER_TOMBSTONE);
|
|
49351
49837
|
wrote = true;
|
|
49352
49838
|
}
|
|
49353
49839
|
if (wrote) args.logger.info("persona.retire-builder.tombstoned", { personaId: PERSONA_BUILDER_ID });
|
|
@@ -49361,15 +49847,15 @@ function retirePersonaBuilder(args) {
|
|
|
49361
49847
|
function findDeployKitRoot(logger) {
|
|
49362
49848
|
const candidates = [];
|
|
49363
49849
|
try {
|
|
49364
|
-
const here =
|
|
49365
|
-
candidates.push(
|
|
49850
|
+
const here = path17.dirname((0, import_node_url.fileURLToPath)(import_meta2.url));
|
|
49851
|
+
candidates.push(path17.resolve(here, "..", "deploy-kit"));
|
|
49366
49852
|
} catch {
|
|
49367
49853
|
}
|
|
49368
49854
|
const fromArgv = bundleSiblingFromArgv(process.argv[1], "deploy-kit");
|
|
49369
49855
|
if (fromArgv) candidates.push(fromArgv);
|
|
49370
49856
|
for (const c of candidates) {
|
|
49371
49857
|
try {
|
|
49372
|
-
if (
|
|
49858
|
+
if (fs15.statSync(c).isDirectory()) {
|
|
49373
49859
|
logger?.info("persona.deploy-kit-root.resolved", { root: c });
|
|
49374
49860
|
return c;
|
|
49375
49861
|
}
|
|
@@ -49380,8 +49866,8 @@ function findDeployKitRoot(logger) {
|
|
|
49380
49866
|
return null;
|
|
49381
49867
|
}
|
|
49382
49868
|
function seedDeployKit(args) {
|
|
49383
|
-
const dst =
|
|
49384
|
-
|
|
49869
|
+
const dst = path17.join(args.dataDir, "deploy-kit");
|
|
49870
|
+
fs15.cpSync(args.deployKitBundleRoot, dst, {
|
|
49385
49871
|
recursive: true,
|
|
49386
49872
|
dereference: true,
|
|
49387
49873
|
force: false,
|
|
@@ -49390,35 +49876,35 @@ function seedDeployKit(args) {
|
|
|
49390
49876
|
args.logger.info("deploy-kit.seed.done", { dst });
|
|
49391
49877
|
}
|
|
49392
49878
|
function refreshDeployKit(args) {
|
|
49393
|
-
const dst =
|
|
49394
|
-
if (!
|
|
49879
|
+
const dst = path17.join(args.dataDir, "deploy-kit");
|
|
49880
|
+
if (!fs15.existsSync(dst)) {
|
|
49395
49881
|
seedDeployKit(args);
|
|
49396
49882
|
return;
|
|
49397
49883
|
}
|
|
49398
49884
|
for (const sub of ["scripts", "contract"]) {
|
|
49399
|
-
const s =
|
|
49400
|
-
if (
|
|
49401
|
-
|
|
49885
|
+
const s = path17.join(args.deployKitBundleRoot, sub);
|
|
49886
|
+
if (fs15.existsSync(s)) {
|
|
49887
|
+
fs15.cpSync(s, path17.join(dst, sub), { recursive: true, force: true, dereference: true });
|
|
49402
49888
|
}
|
|
49403
49889
|
}
|
|
49404
|
-
const secretsSrc =
|
|
49405
|
-
if (
|
|
49406
|
-
|
|
49407
|
-
for (const f of
|
|
49890
|
+
const secretsSrc = path17.join(args.deployKitBundleRoot, ".secrets");
|
|
49891
|
+
if (fs15.existsSync(secretsSrc)) {
|
|
49892
|
+
fs15.mkdirSync(path17.join(dst, ".secrets"), { recursive: true });
|
|
49893
|
+
for (const f of fs15.readdirSync(secretsSrc)) {
|
|
49408
49894
|
if (f.endsWith(".local")) continue;
|
|
49409
|
-
|
|
49895
|
+
fs15.copyFileSync(path17.join(secretsSrc, f), path17.join(dst, ".secrets", f));
|
|
49410
49896
|
}
|
|
49411
49897
|
}
|
|
49412
49898
|
args.logger.info("deploy-kit.refresh.done", { dst });
|
|
49413
49899
|
}
|
|
49414
49900
|
|
|
49415
49901
|
// src/share-md-viewer/load.ts
|
|
49416
|
-
var
|
|
49417
|
-
var
|
|
49902
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
49903
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
49418
49904
|
var import_node_url2 = require("url");
|
|
49419
49905
|
|
|
49420
49906
|
// src/share-md-viewer/asset-loader.ts
|
|
49421
|
-
var
|
|
49907
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
49422
49908
|
function htmlEscape(s) {
|
|
49423
49909
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
49424
49910
|
}
|
|
@@ -49426,12 +49912,12 @@ function createViewerAssetLoader(opts) {
|
|
|
49426
49912
|
let viewerTemplate;
|
|
49427
49913
|
let errorTemplate;
|
|
49428
49914
|
try {
|
|
49429
|
-
viewerTemplate =
|
|
49915
|
+
viewerTemplate = import_node_fs13.default.readFileSync(opts.viewerHtmlPath, "utf8");
|
|
49430
49916
|
} catch (err) {
|
|
49431
49917
|
throw new Error(`viewer asset not found at ${opts.viewerHtmlPath}: ${err.message}`);
|
|
49432
49918
|
}
|
|
49433
49919
|
try {
|
|
49434
|
-
errorTemplate =
|
|
49920
|
+
errorTemplate = import_node_fs13.default.readFileSync(opts.errorHtmlPath, "utf8");
|
|
49435
49921
|
} catch (err) {
|
|
49436
49922
|
throw new Error(`viewer error asset not found at ${opts.errorHtmlPath}: ${err.message}`);
|
|
49437
49923
|
}
|
|
@@ -49446,29 +49932,29 @@ function createViewerAssetLoader(opts) {
|
|
|
49446
49932
|
}
|
|
49447
49933
|
|
|
49448
49934
|
// src/share-md-viewer/load.ts
|
|
49449
|
-
var
|
|
49935
|
+
var import_meta3 = {};
|
|
49450
49936
|
function tryLoadViewerAssets(logger) {
|
|
49451
49937
|
const candidates = [];
|
|
49452
49938
|
try {
|
|
49453
|
-
const here =
|
|
49939
|
+
const here = import_node_path13.default.dirname((0, import_node_url2.fileURLToPath)(import_meta3.url));
|
|
49454
49940
|
candidates.push(here);
|
|
49455
|
-
candidates.push(
|
|
49456
|
-
candidates.push(
|
|
49941
|
+
candidates.push(import_node_path13.default.resolve(here, ".."));
|
|
49942
|
+
candidates.push(import_node_path13.default.resolve(here, "..", "..", "dist"));
|
|
49457
49943
|
} catch {
|
|
49458
49944
|
}
|
|
49459
49945
|
if (process.argv[1]) {
|
|
49460
49946
|
let real = process.argv[1];
|
|
49461
49947
|
try {
|
|
49462
|
-
real =
|
|
49948
|
+
real = import_node_fs14.default.realpathSync(process.argv[1]);
|
|
49463
49949
|
} catch {
|
|
49464
49950
|
}
|
|
49465
|
-
candidates.push(
|
|
49951
|
+
candidates.push(import_node_path13.default.dirname(real));
|
|
49466
49952
|
}
|
|
49467
49953
|
for (const root of candidates) {
|
|
49468
|
-
const viewerHtmlPath =
|
|
49469
|
-
const errorHtmlPath =
|
|
49954
|
+
const viewerHtmlPath = import_node_path13.default.join(root, "share-md-viewer.html");
|
|
49955
|
+
const errorHtmlPath = import_node_path13.default.join(root, "share-md-viewer-error.html");
|
|
49470
49956
|
try {
|
|
49471
|
-
if (
|
|
49957
|
+
if (import_node_fs14.default.statSync(viewerHtmlPath).isFile() && import_node_fs14.default.statSync(errorHtmlPath).isFile()) {
|
|
49472
49958
|
logger?.info("share-md-viewer.assets-root.resolved", { root });
|
|
49473
49959
|
return createViewerAssetLoader({ viewerHtmlPath, errorHtmlPath });
|
|
49474
49960
|
}
|
|
@@ -49483,30 +49969,30 @@ function tryLoadViewerAssets(logger) {
|
|
|
49483
49969
|
}
|
|
49484
49970
|
|
|
49485
49971
|
// src/share-ui/load.ts
|
|
49486
|
-
var
|
|
49487
|
-
var
|
|
49972
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
49973
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
49488
49974
|
var import_node_url3 = require("url");
|
|
49489
49975
|
|
|
49490
49976
|
// src/share-ui/asset-loader.ts
|
|
49491
|
-
var
|
|
49492
|
-
var
|
|
49977
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
49978
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
49493
49979
|
function createShareUiAssetLoader(opts) {
|
|
49494
49980
|
let indexHtml;
|
|
49495
49981
|
try {
|
|
49496
|
-
indexHtml =
|
|
49982
|
+
indexHtml = import_node_fs15.default.readFileSync(opts.indexHtmlPath, "utf8");
|
|
49497
49983
|
} catch (err) {
|
|
49498
49984
|
throw new Error(`share-ui index.html not found at ${opts.indexHtmlPath}: ${err.message}`);
|
|
49499
49985
|
}
|
|
49500
|
-
const assetsDir =
|
|
49986
|
+
const assetsDir = import_node_path14.default.resolve(opts.assetsDir);
|
|
49501
49987
|
return {
|
|
49502
49988
|
renderIndexHtml() {
|
|
49503
49989
|
return indexHtml;
|
|
49504
49990
|
},
|
|
49505
49991
|
resolveAssetPath(rel) {
|
|
49506
|
-
const resolved =
|
|
49507
|
-
if (resolved !== assetsDir && !resolved.startsWith(assetsDir +
|
|
49992
|
+
const resolved = import_node_path14.default.resolve(assetsDir, rel);
|
|
49993
|
+
if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path14.default.sep)) return null;
|
|
49508
49994
|
try {
|
|
49509
|
-
if (
|
|
49995
|
+
if (import_node_fs15.default.statSync(resolved).isFile()) return resolved;
|
|
49510
49996
|
} catch {
|
|
49511
49997
|
}
|
|
49512
49998
|
return null;
|
|
@@ -49515,33 +50001,33 @@ function createShareUiAssetLoader(opts) {
|
|
|
49515
50001
|
}
|
|
49516
50002
|
|
|
49517
50003
|
// src/share-ui/load.ts
|
|
49518
|
-
var
|
|
50004
|
+
var import_meta4 = {};
|
|
49519
50005
|
function bundleDirFromArgv(argv1) {
|
|
49520
50006
|
if (!argv1) return null;
|
|
49521
50007
|
let real = argv1;
|
|
49522
50008
|
try {
|
|
49523
|
-
real =
|
|
50009
|
+
real = import_node_fs16.default.realpathSync(argv1);
|
|
49524
50010
|
} catch {
|
|
49525
50011
|
}
|
|
49526
|
-
return
|
|
50012
|
+
return import_node_path15.default.dirname(real);
|
|
49527
50013
|
}
|
|
49528
50014
|
function tryLoadShareUi(logger) {
|
|
49529
50015
|
const candidates = [];
|
|
49530
50016
|
try {
|
|
49531
|
-
const here =
|
|
50017
|
+
const here = import_node_path15.default.dirname((0, import_node_url3.fileURLToPath)(import_meta4.url));
|
|
49532
50018
|
candidates.push(here);
|
|
49533
|
-
candidates.push(
|
|
49534
|
-
candidates.push(
|
|
50019
|
+
candidates.push(import_node_path15.default.resolve(here, ".."));
|
|
50020
|
+
candidates.push(import_node_path15.default.resolve(here, "..", "..", "dist"));
|
|
49535
50021
|
} catch {
|
|
49536
50022
|
}
|
|
49537
50023
|
const argvDir = bundleDirFromArgv(process.argv[1]);
|
|
49538
50024
|
if (argvDir) candidates.push(argvDir);
|
|
49539
50025
|
for (const root of candidates) {
|
|
49540
|
-
const shareUiDir =
|
|
49541
|
-
const indexHtmlPath =
|
|
49542
|
-
const assetsDir =
|
|
50026
|
+
const shareUiDir = import_node_path15.default.join(root, "share-ui");
|
|
50027
|
+
const indexHtmlPath = import_node_path15.default.join(shareUiDir, "guest.html");
|
|
50028
|
+
const assetsDir = import_node_path15.default.join(shareUiDir, "assets");
|
|
49543
50029
|
try {
|
|
49544
|
-
if (
|
|
50030
|
+
if (import_node_fs16.default.statSync(indexHtmlPath).isFile() && import_node_fs16.default.statSync(assetsDir).isDirectory()) {
|
|
49545
50031
|
logger?.info("share-ui.assets-root.resolved", { root: shareUiDir });
|
|
49546
50032
|
return createShareUiAssetLoader({ indexHtmlPath, assetsDir });
|
|
49547
50033
|
}
|
|
@@ -49624,20 +50110,20 @@ function buildVisitorLogin(deps) {
|
|
|
49624
50110
|
}
|
|
49625
50111
|
|
|
49626
50112
|
// src/visitor/visitor-store.ts
|
|
49627
|
-
var
|
|
49628
|
-
var
|
|
50113
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
50114
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
49629
50115
|
function createVisitorStore(opts) {
|
|
49630
|
-
const file =
|
|
50116
|
+
const file = import_node_path16.default.join(opts.dir, "visitors.json");
|
|
49631
50117
|
const read = () => {
|
|
49632
50118
|
try {
|
|
49633
|
-
return JSON.parse(
|
|
50119
|
+
return JSON.parse(import_node_fs17.default.readFileSync(file, "utf8"));
|
|
49634
50120
|
} catch {
|
|
49635
50121
|
return [];
|
|
49636
50122
|
}
|
|
49637
50123
|
};
|
|
49638
50124
|
const write = (rows) => {
|
|
49639
|
-
|
|
49640
|
-
|
|
50125
|
+
import_node_fs17.default.mkdirSync(opts.dir, { recursive: true });
|
|
50126
|
+
import_node_fs17.default.writeFileSync(file, JSON.stringify(rows, null, 2));
|
|
49641
50127
|
};
|
|
49642
50128
|
return {
|
|
49643
50129
|
upsert(r) {
|
|
@@ -49670,12 +50156,12 @@ function createVisitorStore(opts) {
|
|
|
49670
50156
|
init_claude();
|
|
49671
50157
|
|
|
49672
50158
|
// src/tools/codex.ts
|
|
49673
|
-
var
|
|
49674
|
-
var
|
|
50159
|
+
var import_node_child_process8 = require("child_process");
|
|
50160
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
49675
50161
|
|
|
49676
50162
|
// src/tools/codex-session.ts
|
|
49677
|
-
var
|
|
49678
|
-
var
|
|
50163
|
+
var import_node_child_process6 = require("child_process");
|
|
50164
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
49679
50165
|
|
|
49680
50166
|
// src/tools/codex-app-server-client.ts
|
|
49681
50167
|
var import_node_readline = require("readline");
|
|
@@ -50148,16 +50634,16 @@ function turnStartInput(text) {
|
|
|
50148
50634
|
}
|
|
50149
50635
|
|
|
50150
50636
|
// src/tools/codex-mcp-config.ts
|
|
50151
|
-
var
|
|
50152
|
-
var
|
|
50637
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
50638
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
50153
50639
|
function loadCodexMcpServerDefs(args) {
|
|
50154
50640
|
const out = [];
|
|
50155
50641
|
const seen = /* @__PURE__ */ new Set();
|
|
50156
|
-
const sources = [...args.mcpConfigPaths,
|
|
50642
|
+
const sources = [...args.mcpConfigPaths, import_node_path17.default.join(args.cwd, ".mcp.json")];
|
|
50157
50643
|
for (const file of sources) {
|
|
50158
50644
|
let parsed;
|
|
50159
50645
|
try {
|
|
50160
|
-
parsed = JSON.parse(
|
|
50646
|
+
parsed = JSON.parse(import_node_fs19.default.readFileSync(file, "utf8"));
|
|
50161
50647
|
} catch (e) {
|
|
50162
50648
|
const code = e.code;
|
|
50163
50649
|
if (code !== "ENOENT") {
|
|
@@ -50201,12 +50687,12 @@ function loadCodexMcpServerDefs(args) {
|
|
|
50201
50687
|
}
|
|
50202
50688
|
|
|
50203
50689
|
// src/tools/codex-features.ts
|
|
50204
|
-
var
|
|
50690
|
+
var import_node_child_process5 = require("child_process");
|
|
50205
50691
|
var cachedNetworkProxy;
|
|
50206
50692
|
function hasNetworkProxyFeature(deps = {}) {
|
|
50207
50693
|
if (cachedNetworkProxy !== void 0) return cachedNetworkProxy;
|
|
50208
50694
|
try {
|
|
50209
|
-
const out = deps.execOverride ? deps.execOverride() : (0,
|
|
50695
|
+
const out = deps.execOverride ? deps.execOverride() : (0, import_node_child_process5.execFileSync)(process.env.CODEX_BIN ?? "codex", ["features", "list"], {
|
|
50210
50696
|
encoding: "utf8",
|
|
50211
50697
|
timeout: 3e3
|
|
50212
50698
|
});
|
|
@@ -50221,7 +50707,7 @@ var warming = false;
|
|
|
50221
50707
|
function warmCodexFeatureCache() {
|
|
50222
50708
|
if (cachedNetworkProxy !== void 0 || warming) return;
|
|
50223
50709
|
warming = true;
|
|
50224
|
-
(0,
|
|
50710
|
+
(0, import_node_child_process5.execFile)(
|
|
50225
50711
|
process.env.CODEX_BIN ?? "codex",
|
|
50226
50712
|
["features", "list"],
|
|
50227
50713
|
{ encoding: "utf8", timeout: 3e3 },
|
|
@@ -50262,7 +50748,7 @@ function createCodexSession(ctx, sink, deps = {}) {
|
|
|
50262
50748
|
)
|
|
50263
50749
|
);
|
|
50264
50750
|
const env = { ...process.env, ...ctx.env };
|
|
50265
|
-
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0,
|
|
50751
|
+
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0, import_node_child_process6.spawn)(cmd, args, { cwd: ctx.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
|
|
50266
50752
|
let threadId = ctx.toolSessionId;
|
|
50267
50753
|
let turnId;
|
|
50268
50754
|
const approvalIds = /* @__PURE__ */ new Map();
|
|
@@ -50335,7 +50821,7 @@ function createCodexSession(ctx, sink, deps = {}) {
|
|
|
50335
50821
|
capabilities: null
|
|
50336
50822
|
});
|
|
50337
50823
|
client.notify("initialized", {});
|
|
50338
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
50824
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path18.default.join(ctx.cwd, ".claude", "skills")] }).catch((e) => deps.logger?.warn("codex skills/extraRoots/set failed", { message: e.message }));
|
|
50339
50825
|
if (threadId) {
|
|
50340
50826
|
await client.request("thread/resume", { threadId, ...threadStartParams(ctx) });
|
|
50341
50827
|
} else {
|
|
@@ -50388,12 +50874,12 @@ function stringValue2(value) {
|
|
|
50388
50874
|
}
|
|
50389
50875
|
|
|
50390
50876
|
// src/tools/codex-app-server-query.ts
|
|
50391
|
-
var
|
|
50877
|
+
var import_node_child_process7 = require("child_process");
|
|
50392
50878
|
var DEFAULT_CODEX_QUERY_TIMEOUT_MS = 8e3;
|
|
50393
50879
|
async function queryCodexAppServer(cwd, method, params, deps = {}) {
|
|
50394
50880
|
const cmd = process.env.CODEX_BIN ?? "codex";
|
|
50395
50881
|
const args = ["app-server", "--listen", "stdio://"];
|
|
50396
|
-
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0,
|
|
50882
|
+
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process7.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
|
|
50397
50883
|
const client = new CodexAppServerClient(proc, {});
|
|
50398
50884
|
const timeoutMs = deps.timeoutMs ?? DEFAULT_CODEX_QUERY_TIMEOUT_MS;
|
|
50399
50885
|
let timer;
|
|
@@ -50545,10 +51031,10 @@ function sanitizeCodexModel(model) {
|
|
|
50545
51031
|
return model;
|
|
50546
51032
|
}
|
|
50547
51033
|
async function probeCodex(env = process.env) {
|
|
50548
|
-
if (env.CODEX_BIN &&
|
|
51034
|
+
if (env.CODEX_BIN && import_node_fs20.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
|
|
50549
51035
|
try {
|
|
50550
|
-
const out = (0,
|
|
50551
|
-
if (out &&
|
|
51036
|
+
const out = (0, import_node_child_process8.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
|
|
51037
|
+
if (out && import_node_fs20.default.existsSync(out)) return { available: true, path: out };
|
|
50552
51038
|
} catch {
|
|
50553
51039
|
}
|
|
50554
51040
|
return { available: false };
|
|
@@ -50615,9 +51101,9 @@ var CodexAdapter = class {
|
|
|
50615
51101
|
|
|
50616
51102
|
// src/tools/claude-tui.ts
|
|
50617
51103
|
var import_node_crypto5 = require("crypto");
|
|
50618
|
-
var
|
|
50619
|
-
var
|
|
50620
|
-
var
|
|
51104
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
51105
|
+
var import_node_os9 = __toESM(require("os"), 1);
|
|
51106
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
50621
51107
|
var import_headless = __toESM(require_xterm_headless(), 1);
|
|
50622
51108
|
|
|
50623
51109
|
// ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
|
|
@@ -51851,10 +52337,10 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
51851
52337
|
}
|
|
51852
52338
|
function jsonlExistsForCtx(ctx) {
|
|
51853
52339
|
if (!ctx.toolSessionId) return false;
|
|
51854
|
-
const home =
|
|
51855
|
-
const file =
|
|
52340
|
+
const home = import_node_os9.default.homedir();
|
|
52341
|
+
const file = import_node_path19.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
|
|
51856
52342
|
try {
|
|
51857
|
-
return
|
|
52343
|
+
return import_node_fs21.default.statSync(file).isFile();
|
|
51858
52344
|
} catch {
|
|
51859
52345
|
return false;
|
|
51860
52346
|
}
|
|
@@ -51931,8 +52417,8 @@ var PersonaDispatchManager = class {
|
|
|
51931
52417
|
};
|
|
51932
52418
|
|
|
51933
52419
|
// src/dispatch/store.ts
|
|
51934
|
-
var
|
|
51935
|
-
var
|
|
52420
|
+
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
52421
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
51936
52422
|
|
|
51937
52423
|
// src/shift/constants.ts
|
|
51938
52424
|
var MAX_RUNS_PER_SHIFT = 30;
|
|
@@ -51950,7 +52436,7 @@ function createDispatchStore(deps) {
|
|
|
51950
52436
|
async function load() {
|
|
51951
52437
|
let raw;
|
|
51952
52438
|
try {
|
|
51953
|
-
raw = await
|
|
52439
|
+
raw = await import_promises2.default.readFile(deps.filePath, "utf8");
|
|
51954
52440
|
} catch (e) {
|
|
51955
52441
|
if (e.code === "ENOENT") {
|
|
51956
52442
|
records = [];
|
|
@@ -51970,10 +52456,10 @@ function createDispatchStore(deps) {
|
|
|
51970
52456
|
flushTimer = null;
|
|
51971
52457
|
}
|
|
51972
52458
|
const content = { version: 1, records };
|
|
51973
|
-
await
|
|
52459
|
+
await import_promises2.default.mkdir(import_node_path20.default.dirname(deps.filePath), { recursive: true });
|
|
51974
52460
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
51975
|
-
await
|
|
51976
|
-
await
|
|
52461
|
+
await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
52462
|
+
await import_promises2.default.rename(tmp, deps.filePath);
|
|
51977
52463
|
}
|
|
51978
52464
|
function scheduleFlush() {
|
|
51979
52465
|
if (flushTimer) return;
|
|
@@ -52032,10 +52518,10 @@ function createDispatchStore(deps) {
|
|
|
52032
52518
|
}
|
|
52033
52519
|
|
|
52034
52520
|
// src/dispatch/mcp-config.ts
|
|
52035
|
-
var
|
|
52036
|
-
var
|
|
52521
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
52522
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
52037
52523
|
function dispatchMcpConfigPath(dataDir) {
|
|
52038
|
-
return
|
|
52524
|
+
return import_node_path21.default.join(dataDir, "dispatch.mcp.json");
|
|
52039
52525
|
}
|
|
52040
52526
|
function writeDispatchMcpConfig(args) {
|
|
52041
52527
|
const cfgPath = dispatchMcpConfigPath(args.dataDir);
|
|
@@ -52054,16 +52540,16 @@ function writeDispatchMcpConfig(args) {
|
|
|
52054
52540
|
}
|
|
52055
52541
|
}
|
|
52056
52542
|
};
|
|
52057
|
-
|
|
52058
|
-
|
|
52543
|
+
import_node_fs22.default.mkdirSync(args.dataDir, { recursive: true });
|
|
52544
|
+
import_node_fs22.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52059
52545
|
return cfgPath;
|
|
52060
52546
|
}
|
|
52061
52547
|
|
|
52062
52548
|
// src/ticket/mcp-config.ts
|
|
52063
|
-
var
|
|
52064
|
-
var
|
|
52549
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
52550
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
52065
52551
|
function ticketMcpConfigPath(dataDir) {
|
|
52066
|
-
return
|
|
52552
|
+
return import_node_path22.default.join(dataDir, "ticket.mcp.json");
|
|
52067
52553
|
}
|
|
52068
52554
|
function writeTicketMcpConfig(args) {
|
|
52069
52555
|
const cfgPath = ticketMcpConfigPath(args.dataDir);
|
|
@@ -52085,16 +52571,16 @@ function writeTicketMcpConfig(args) {
|
|
|
52085
52571
|
}
|
|
52086
52572
|
}
|
|
52087
52573
|
};
|
|
52088
|
-
|
|
52089
|
-
|
|
52574
|
+
import_node_fs23.default.mkdirSync(args.dataDir, { recursive: true });
|
|
52575
|
+
import_node_fs23.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52090
52576
|
return cfgPath;
|
|
52091
52577
|
}
|
|
52092
52578
|
|
|
52093
52579
|
// src/shift/mcp-config.ts
|
|
52094
|
-
var
|
|
52095
|
-
var
|
|
52580
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
52581
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
52096
52582
|
function shiftMcpConfigPath(dataDir) {
|
|
52097
|
-
return
|
|
52583
|
+
return import_node_path23.default.join(dataDir, "shift.mcp.json");
|
|
52098
52584
|
}
|
|
52099
52585
|
async function writeShiftMcpConfig(args) {
|
|
52100
52586
|
const cfgPath = shiftMcpConfigPath(args.dataDir);
|
|
@@ -52113,16 +52599,16 @@ async function writeShiftMcpConfig(args) {
|
|
|
52113
52599
|
}
|
|
52114
52600
|
}
|
|
52115
52601
|
};
|
|
52116
|
-
await
|
|
52117
|
-
await
|
|
52602
|
+
await import_node_fs24.default.promises.mkdir(args.dataDir, { recursive: true });
|
|
52603
|
+
await import_node_fs24.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52118
52604
|
return cfgPath;
|
|
52119
52605
|
}
|
|
52120
52606
|
|
|
52121
52607
|
// src/inbox/mcp-config.ts
|
|
52122
|
-
var
|
|
52123
|
-
var
|
|
52608
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
52609
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
52124
52610
|
function inboxMcpConfigPath(dataDir) {
|
|
52125
|
-
return
|
|
52611
|
+
return import_node_path24.default.join(dataDir, "inbox.mcp.json");
|
|
52126
52612
|
}
|
|
52127
52613
|
async function writeInboxMcpConfig(args) {
|
|
52128
52614
|
const cfgPath = inboxMcpConfigPath(args.dataDir);
|
|
@@ -52141,16 +52627,16 @@ async function writeInboxMcpConfig(args) {
|
|
|
52141
52627
|
}
|
|
52142
52628
|
}
|
|
52143
52629
|
};
|
|
52144
|
-
await
|
|
52145
|
-
await
|
|
52630
|
+
await import_node_fs25.default.promises.mkdir(args.dataDir, { recursive: true });
|
|
52631
|
+
await import_node_fs25.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52146
52632
|
return cfgPath;
|
|
52147
52633
|
}
|
|
52148
52634
|
|
|
52149
52635
|
// src/peer-ops/mcp-config.ts
|
|
52150
|
-
var
|
|
52151
|
-
var
|
|
52636
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
52637
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
52152
52638
|
function peerOpsMcpConfigPath(dataDir) {
|
|
52153
|
-
return
|
|
52639
|
+
return import_node_path25.default.join(dataDir, "peer-ops.mcp.json");
|
|
52154
52640
|
}
|
|
52155
52641
|
function writePeerOpsMcpConfig(args) {
|
|
52156
52642
|
const cfgPath = peerOpsMcpConfigPath(args.dataDir);
|
|
@@ -52167,16 +52653,16 @@ function writePeerOpsMcpConfig(args) {
|
|
|
52167
52653
|
}
|
|
52168
52654
|
}
|
|
52169
52655
|
};
|
|
52170
|
-
|
|
52171
|
-
|
|
52656
|
+
import_node_fs26.default.mkdirSync(args.dataDir, { recursive: true });
|
|
52657
|
+
import_node_fs26.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
|
|
52172
52658
|
return cfgPath;
|
|
52173
52659
|
}
|
|
52174
52660
|
|
|
52175
52661
|
// src/rpc-tool/mcp-config.ts
|
|
52176
|
-
var
|
|
52177
|
-
var
|
|
52662
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
52663
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
52178
52664
|
function rpcToolMcpConfigPath(dataDir) {
|
|
52179
|
-
return
|
|
52665
|
+
return import_node_path26.default.join(dataDir, "rpc-tool.mcp.json");
|
|
52180
52666
|
}
|
|
52181
52667
|
function writeRpcToolMcpConfig(args) {
|
|
52182
52668
|
const cfgPath = rpcToolMcpConfigPath(args.dataDir);
|
|
@@ -52195,18 +52681,18 @@ function writeRpcToolMcpConfig(args) {
|
|
|
52195
52681
|
}
|
|
52196
52682
|
}
|
|
52197
52683
|
};
|
|
52198
|
-
|
|
52199
|
-
|
|
52684
|
+
import_node_fs27.default.mkdirSync(args.dataDir, { recursive: true });
|
|
52685
|
+
import_node_fs27.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52200
52686
|
return cfgPath;
|
|
52201
52687
|
}
|
|
52202
52688
|
|
|
52203
52689
|
// src/dispatch/source-transcript.ts
|
|
52204
|
-
var
|
|
52690
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
52205
52691
|
init_claude_history();
|
|
52206
52692
|
var NO_SOURCE_TRANSCRIPT = "(no transcript yet \u2014 operate from the task description alone)";
|
|
52207
52693
|
function resolveSourceJsonlPath(sourceFile, home) {
|
|
52208
52694
|
if (!sourceFile?.toolSessionId) return NO_SOURCE_TRANSCRIPT;
|
|
52209
|
-
return
|
|
52695
|
+
return import_node_path27.default.join(
|
|
52210
52696
|
home,
|
|
52211
52697
|
".claude",
|
|
52212
52698
|
"projects",
|
|
@@ -52216,8 +52702,8 @@ function resolveSourceJsonlPath(sourceFile, home) {
|
|
|
52216
52702
|
}
|
|
52217
52703
|
|
|
52218
52704
|
// src/shift/store.ts
|
|
52219
|
-
var
|
|
52220
|
-
var
|
|
52705
|
+
var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
52706
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
52221
52707
|
var import_node_crypto6 = require("crypto");
|
|
52222
52708
|
|
|
52223
52709
|
// src/shift/schedule.ts
|
|
@@ -52264,7 +52750,7 @@ function createShiftStore(deps) {
|
|
|
52264
52750
|
async function load() {
|
|
52265
52751
|
let raw;
|
|
52266
52752
|
try {
|
|
52267
|
-
raw = await
|
|
52753
|
+
raw = await import_promises3.default.readFile(deps.filePath, "utf8");
|
|
52268
52754
|
} catch (e) {
|
|
52269
52755
|
if (e.code === "ENOENT") {
|
|
52270
52756
|
shifts = [];
|
|
@@ -52292,10 +52778,10 @@ function createShiftStore(deps) {
|
|
|
52292
52778
|
flushTimer = null;
|
|
52293
52779
|
}
|
|
52294
52780
|
const content = { version: 1, shifts };
|
|
52295
|
-
await
|
|
52781
|
+
await import_promises3.default.mkdir(import_node_path28.default.dirname(deps.filePath), { recursive: true });
|
|
52296
52782
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
52297
|
-
await
|
|
52298
|
-
await
|
|
52783
|
+
await import_promises3.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
52784
|
+
await import_promises3.default.rename(tmp, deps.filePath);
|
|
52299
52785
|
}
|
|
52300
52786
|
function scheduleFlush() {
|
|
52301
52787
|
if (flushTimer) return;
|
|
@@ -52375,7 +52861,7 @@ function createShiftStore(deps) {
|
|
|
52375
52861
|
}
|
|
52376
52862
|
|
|
52377
52863
|
// src/github/gh.ts
|
|
52378
|
-
var
|
|
52864
|
+
var import_node_child_process9 = require("child_process");
|
|
52379
52865
|
var GhError = class extends Error {
|
|
52380
52866
|
constructor(kind, message, stderr) {
|
|
52381
52867
|
super(message);
|
|
@@ -52393,7 +52879,7 @@ function createGhRunner(defaults) {
|
|
|
52393
52879
|
return {
|
|
52394
52880
|
run(args, opts) {
|
|
52395
52881
|
return new Promise((resolve7, reject) => {
|
|
52396
|
-
(0,
|
|
52882
|
+
(0, import_node_child_process9.execFile)(
|
|
52397
52883
|
"gh",
|
|
52398
52884
|
args,
|
|
52399
52885
|
{ timeout: opts?.timeoutMs ?? baseTimeoutMs, maxBuffer: MAX_BUFFER },
|
|
@@ -52960,15 +53446,15 @@ async function refreshTunnelUrlOnStartup(deps) {
|
|
|
52960
53446
|
}
|
|
52961
53447
|
|
|
52962
53448
|
// src/lark-bot-connector/binding-store.ts
|
|
52963
|
-
var
|
|
52964
|
-
var
|
|
53449
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
53450
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
52965
53451
|
function createLarkBotBindingStore(personaRoot) {
|
|
52966
|
-
const filePath = (personaId2) =>
|
|
53452
|
+
const filePath = (personaId2) => import_node_path29.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
|
|
52967
53453
|
const read = (personaId2) => {
|
|
52968
53454
|
const file = filePath(personaId2);
|
|
52969
|
-
if (!
|
|
53455
|
+
if (!import_node_fs28.default.existsSync(file)) return null;
|
|
52970
53456
|
try {
|
|
52971
|
-
const raw = JSON.parse(
|
|
53457
|
+
const raw = JSON.parse(import_node_fs28.default.readFileSync(file, "utf8"));
|
|
52972
53458
|
if (typeof raw?.appId !== "string" || raw.appId.length === 0) return null;
|
|
52973
53459
|
return raw;
|
|
52974
53460
|
} catch {
|
|
@@ -52977,16 +53463,16 @@ function createLarkBotBindingStore(personaRoot) {
|
|
|
52977
53463
|
};
|
|
52978
53464
|
const write = (personaId2, meta) => {
|
|
52979
53465
|
const file = filePath(personaId2);
|
|
52980
|
-
|
|
53466
|
+
import_node_fs28.default.mkdirSync(import_node_path29.default.dirname(file), { recursive: true });
|
|
52981
53467
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
52982
|
-
|
|
52983
|
-
|
|
53468
|
+
import_node_fs28.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
53469
|
+
import_node_fs28.default.renameSync(tmp, file);
|
|
52984
53470
|
};
|
|
52985
53471
|
return {
|
|
52986
53472
|
read,
|
|
52987
53473
|
write,
|
|
52988
53474
|
remove(personaId2) {
|
|
52989
|
-
|
|
53475
|
+
import_node_fs28.default.rmSync(filePath(personaId2), { force: true });
|
|
52990
53476
|
},
|
|
52991
53477
|
addRemovedChat(personaId2, chatId) {
|
|
52992
53478
|
const meta = read(personaId2);
|
|
@@ -53140,8 +53626,8 @@ function createLarkBotCloudClient(opts) {
|
|
|
53140
53626
|
}
|
|
53141
53627
|
|
|
53142
53628
|
// src/lark-bot-connector/chat-router.ts
|
|
53143
|
-
var
|
|
53144
|
-
var
|
|
53629
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
53630
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
53145
53631
|
init_protocol();
|
|
53146
53632
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
53147
53633
|
var LOCAL_TURN_RETRIES = 2;
|
|
@@ -53206,9 +53692,9 @@ function createLarkChatRouter(deps) {
|
|
|
53206
53692
|
continue;
|
|
53207
53693
|
}
|
|
53208
53694
|
const dir = deps.mediaRootFor(env.chatId);
|
|
53209
|
-
|
|
53210
|
-
const p2 =
|
|
53211
|
-
|
|
53695
|
+
import_node_fs29.default.mkdirSync(dir, { recursive: true });
|
|
53696
|
+
const p2 = import_node_path30.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
|
|
53697
|
+
import_node_fs29.default.writeFileSync(p2, r.data);
|
|
53212
53698
|
lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
53213
53699
|
} catch (err) {
|
|
53214
53700
|
deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
|
|
@@ -53229,9 +53715,9 @@ function createLarkChatRouter(deps) {
|
|
|
53229
53715
|
continue;
|
|
53230
53716
|
}
|
|
53231
53717
|
const dir = deps.mediaRootFor(env.chatId);
|
|
53232
|
-
|
|
53233
|
-
const p2 =
|
|
53234
|
-
|
|
53718
|
+
import_node_fs29.default.mkdirSync(dir, { recursive: true });
|
|
53719
|
+
const p2 = import_node_path30.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
|
|
53720
|
+
import_node_fs29.default.writeFileSync(p2, r.data);
|
|
53235
53721
|
lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
53236
53722
|
} catch (err) {
|
|
53237
53723
|
deps.logger?.warn(`larkBot file fetch failed ${f.key}: ${err.message}`);
|
|
@@ -54160,7 +54646,7 @@ var CodexHistoryReader = class {
|
|
|
54160
54646
|
};
|
|
54161
54647
|
|
|
54162
54648
|
// src/tools/codex-skills.ts
|
|
54163
|
-
var
|
|
54649
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
54164
54650
|
function str3(v2) {
|
|
54165
54651
|
return typeof v2 === "string" ? v2 : void 0;
|
|
54166
54652
|
}
|
|
@@ -54197,14 +54683,14 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
54197
54683
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
54198
54684
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
54199
54685
|
beforeRequest: (client) => {
|
|
54200
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
54686
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path31.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
54201
54687
|
}
|
|
54202
54688
|
});
|
|
54203
54689
|
return mapSkillsListResponse(res);
|
|
54204
54690
|
}
|
|
54205
54691
|
|
|
54206
54692
|
// src/tools/codex-turn-context.ts
|
|
54207
|
-
var
|
|
54693
|
+
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
54208
54694
|
function parseTurnContextFromRollout(raw) {
|
|
54209
54695
|
const lines = raw.split("\n");
|
|
54210
54696
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -54239,7 +54725,7 @@ async function readCodexTurnContext(args, deps = {}) {
|
|
|
54239
54725
|
);
|
|
54240
54726
|
const rolloutPath = str4(rec3(res?.thread)?.path);
|
|
54241
54727
|
if (!rolloutPath) return null;
|
|
54242
|
-
return parseTurnContextFromRollout(await
|
|
54728
|
+
return parseTurnContextFromRollout(await import_promises4.default.readFile(rolloutPath, "utf8"));
|
|
54243
54729
|
}
|
|
54244
54730
|
function createCodexResolvedMetaHydrator(deps) {
|
|
54245
54731
|
const fetchedThreadIds = /* @__PURE__ */ new Set();
|
|
@@ -54282,23 +54768,23 @@ function str4(v2) {
|
|
|
54282
54768
|
}
|
|
54283
54769
|
|
|
54284
54770
|
// src/workspace/browser.ts
|
|
54285
|
-
var
|
|
54286
|
-
var
|
|
54287
|
-
var
|
|
54771
|
+
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
54772
|
+
var import_node_os10 = __toESM(require("os"), 1);
|
|
54773
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
54288
54774
|
init_protocol();
|
|
54289
54775
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
54290
54776
|
function resolveInsideCwd(cwd, subpath) {
|
|
54291
|
-
const absCwd =
|
|
54292
|
-
const joined =
|
|
54293
|
-
const rel =
|
|
54294
|
-
if (rel.startsWith("..") ||
|
|
54777
|
+
const absCwd = import_node_path32.default.resolve(cwd);
|
|
54778
|
+
const joined = import_node_path32.default.resolve(absCwd, subpath ?? ".");
|
|
54779
|
+
const rel = import_node_path32.default.relative(absCwd, joined);
|
|
54780
|
+
if (rel.startsWith("..") || import_node_path32.default.isAbsolute(rel)) {
|
|
54295
54781
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
54296
54782
|
}
|
|
54297
54783
|
return joined;
|
|
54298
54784
|
}
|
|
54299
54785
|
function ensureCwd(cwd) {
|
|
54300
54786
|
try {
|
|
54301
|
-
const stat =
|
|
54787
|
+
const stat = import_node_fs30.default.statSync(cwd);
|
|
54302
54788
|
if (!stat.isDirectory()) {
|
|
54303
54789
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
54304
54790
|
}
|
|
@@ -54309,10 +54795,10 @@ function ensureCwd(cwd) {
|
|
|
54309
54795
|
}
|
|
54310
54796
|
var WorkspaceBrowser = class {
|
|
54311
54797
|
list(args) {
|
|
54312
|
-
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd :
|
|
54798
|
+
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os10.default.homedir();
|
|
54313
54799
|
ensureCwd(cwd);
|
|
54314
54800
|
const full = resolveInsideCwd(cwd, args.path);
|
|
54315
|
-
const dirents =
|
|
54801
|
+
const dirents = import_node_fs30.default.readdirSync(full, { withFileTypes: true });
|
|
54316
54802
|
const entries = [];
|
|
54317
54803
|
for (const d of dirents) {
|
|
54318
54804
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -54322,7 +54808,7 @@ var WorkspaceBrowser = class {
|
|
|
54322
54808
|
mtime: ""
|
|
54323
54809
|
};
|
|
54324
54810
|
try {
|
|
54325
|
-
const st =
|
|
54811
|
+
const st = import_node_fs30.default.statSync(import_node_path32.default.join(full, d.name));
|
|
54326
54812
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
54327
54813
|
if (d.isFile()) entry.size = st.size;
|
|
54328
54814
|
} catch {
|
|
@@ -54338,14 +54824,14 @@ var WorkspaceBrowser = class {
|
|
|
54338
54824
|
read(args) {
|
|
54339
54825
|
ensureCwd(args.cwd);
|
|
54340
54826
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
54341
|
-
const st =
|
|
54827
|
+
const st = import_node_fs30.default.statSync(full);
|
|
54342
54828
|
if (!st.isFile()) {
|
|
54343
54829
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
54344
54830
|
}
|
|
54345
54831
|
if (st.size > MAX_FILE_BYTES2) {
|
|
54346
54832
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
|
|
54347
54833
|
}
|
|
54348
|
-
const buf =
|
|
54834
|
+
const buf = import_node_fs30.default.readFileSync(full);
|
|
54349
54835
|
const isBinary = buf.includes(0);
|
|
54350
54836
|
if (isBinary) {
|
|
54351
54837
|
return {
|
|
@@ -54367,20 +54853,20 @@ var WorkspaceBrowser = class {
|
|
|
54367
54853
|
};
|
|
54368
54854
|
|
|
54369
54855
|
// src/skills/agents-scanner.ts
|
|
54370
|
-
var
|
|
54371
|
-
var
|
|
54372
|
-
var
|
|
54856
|
+
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
54857
|
+
var import_node_os11 = __toESM(require("os"), 1);
|
|
54858
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
54373
54859
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
54374
54860
|
function isDirLikeSync2(p2) {
|
|
54375
54861
|
try {
|
|
54376
|
-
return
|
|
54862
|
+
return import_node_fs31.default.statSync(p2).isDirectory();
|
|
54377
54863
|
} catch {
|
|
54378
54864
|
return false;
|
|
54379
54865
|
}
|
|
54380
54866
|
}
|
|
54381
54867
|
function fileExistsSync(p2) {
|
|
54382
54868
|
try {
|
|
54383
|
-
return
|
|
54869
|
+
return import_node_fs31.default.statSync(p2).isFile();
|
|
54384
54870
|
} catch {
|
|
54385
54871
|
return false;
|
|
54386
54872
|
}
|
|
@@ -54388,7 +54874,7 @@ function fileExistsSync(p2) {
|
|
|
54388
54874
|
function parseAgentFile(filePath) {
|
|
54389
54875
|
let content;
|
|
54390
54876
|
try {
|
|
54391
|
-
content =
|
|
54877
|
+
content = import_node_fs31.default.readFileSync(filePath, "utf8");
|
|
54392
54878
|
} catch {
|
|
54393
54879
|
return {};
|
|
54394
54880
|
}
|
|
@@ -54401,16 +54887,16 @@ function parseAgentFile(filePath) {
|
|
|
54401
54887
|
function scanAgentsDir(dir, source, seen, out) {
|
|
54402
54888
|
let entries;
|
|
54403
54889
|
try {
|
|
54404
|
-
entries =
|
|
54890
|
+
entries = import_node_fs31.default.readdirSync(dir, { withFileTypes: true });
|
|
54405
54891
|
} catch {
|
|
54406
54892
|
return;
|
|
54407
54893
|
}
|
|
54408
54894
|
for (const ent of entries) {
|
|
54409
54895
|
if (!ent.name.endsWith(".md")) continue;
|
|
54410
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
54896
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path33.default.join(dir, ent.name)))) {
|
|
54411
54897
|
continue;
|
|
54412
54898
|
}
|
|
54413
|
-
const filePath =
|
|
54899
|
+
const filePath = import_node_path33.default.join(dir, ent.name);
|
|
54414
54900
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
54415
54901
|
if (seen.has(baseName)) continue;
|
|
54416
54902
|
seen.add(baseName);
|
|
@@ -54428,12 +54914,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
54428
54914
|
function walk2(dir, namespaces) {
|
|
54429
54915
|
let entries;
|
|
54430
54916
|
try {
|
|
54431
|
-
entries =
|
|
54917
|
+
entries = import_node_fs31.default.readdirSync(dir, { withFileTypes: true });
|
|
54432
54918
|
} catch {
|
|
54433
54919
|
return;
|
|
54434
54920
|
}
|
|
54435
54921
|
for (const ent of entries) {
|
|
54436
|
-
const childPath =
|
|
54922
|
+
const childPath = import_node_path33.default.join(dir, ent.name);
|
|
54437
54923
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
54438
54924
|
walk2(childPath, [...namespaces, ent.name]);
|
|
54439
54925
|
continue;
|
|
@@ -54458,13 +54944,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
54458
54944
|
walk2(root, []);
|
|
54459
54945
|
}
|
|
54460
54946
|
function readInstalledPlugins2(home) {
|
|
54461
|
-
const pluginsDir =
|
|
54462
|
-
const v2 =
|
|
54463
|
-
const v1 =
|
|
54947
|
+
const pluginsDir = import_node_path33.default.join(home, ".claude", "plugins");
|
|
54948
|
+
const v2 = import_node_path33.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
54949
|
+
const v1 = import_node_path33.default.join(pluginsDir, "installed_plugins.json");
|
|
54464
54950
|
let raw = null;
|
|
54465
54951
|
for (const candidate of [v2, v1]) {
|
|
54466
54952
|
try {
|
|
54467
|
-
raw =
|
|
54953
|
+
raw = import_node_fs31.default.readFileSync(candidate, "utf8");
|
|
54468
54954
|
break;
|
|
54469
54955
|
} catch {
|
|
54470
54956
|
}
|
|
@@ -54489,19 +54975,19 @@ function readInstalledPlugins2(home) {
|
|
|
54489
54975
|
return out;
|
|
54490
54976
|
}
|
|
54491
54977
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
54492
|
-
let cur =
|
|
54493
|
-
const fsRoot =
|
|
54978
|
+
let cur = import_node_path33.default.resolve(startCwd);
|
|
54979
|
+
const fsRoot = import_node_path33.default.parse(cur).root;
|
|
54494
54980
|
while (true) {
|
|
54495
|
-
scanAgentsDir(
|
|
54981
|
+
scanAgentsDir(import_node_path33.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
54496
54982
|
let hasGit = false;
|
|
54497
54983
|
try {
|
|
54498
|
-
hasGit =
|
|
54984
|
+
hasGit = import_node_fs31.default.existsSync(import_node_path33.default.join(cur, ".git"));
|
|
54499
54985
|
} catch {
|
|
54500
54986
|
}
|
|
54501
54987
|
if (hasGit) return;
|
|
54502
54988
|
if (cur === home) return;
|
|
54503
54989
|
if (cur === fsRoot) return;
|
|
54504
|
-
const parent =
|
|
54990
|
+
const parent = import_node_path33.default.dirname(cur);
|
|
54505
54991
|
if (parent === cur) return;
|
|
54506
54992
|
cur = parent;
|
|
54507
54993
|
}
|
|
@@ -54511,7 +54997,7 @@ var AgentsScanner = class {
|
|
|
54511
54997
|
extraPluginRoots;
|
|
54512
54998
|
policyDir;
|
|
54513
54999
|
constructor(opts = {}) {
|
|
54514
|
-
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ??
|
|
55000
|
+
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os11.default.homedir();
|
|
54515
55001
|
this.extraPluginRoots = opts.extraPluginRoots ?? [];
|
|
54516
55002
|
if (opts.policyDir !== void 0) {
|
|
54517
55003
|
this.policyDir = opts.policyDir;
|
|
@@ -54536,7 +55022,7 @@ var AgentsScanner = class {
|
|
|
54536
55022
|
}
|
|
54537
55023
|
const fsBlock = [];
|
|
54538
55024
|
scanAgentsDir(
|
|
54539
|
-
|
|
55025
|
+
import_node_path33.default.join(this.home, ".claude", "agents"),
|
|
54540
55026
|
"global",
|
|
54541
55027
|
seen,
|
|
54542
55028
|
fsBlock
|
|
@@ -54550,7 +55036,7 @@ var AgentsScanner = class {
|
|
|
54550
55036
|
...this.extraPluginRoots
|
|
54551
55037
|
];
|
|
54552
55038
|
for (const { name, root } of plugins) {
|
|
54553
|
-
const agentsRoot =
|
|
55039
|
+
const agentsRoot = import_node_path33.default.join(root, "agents");
|
|
54554
55040
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
54555
55041
|
}
|
|
54556
55042
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -54558,28 +55044,28 @@ var AgentsScanner = class {
|
|
|
54558
55044
|
};
|
|
54559
55045
|
|
|
54560
55046
|
// src/observer/session-observer.ts
|
|
54561
|
-
var
|
|
54562
|
-
var
|
|
54563
|
-
var
|
|
55047
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
55048
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
55049
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
54564
55050
|
init_claude_history();
|
|
54565
55051
|
|
|
54566
55052
|
// src/observer/subagent-meta-observer.ts
|
|
54567
|
-
var
|
|
54568
|
-
var
|
|
54569
|
-
var
|
|
55053
|
+
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
55054
|
+
var import_node_os12 = __toESM(require("os"), 1);
|
|
55055
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
54570
55056
|
init_claude_history();
|
|
54571
55057
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
54572
55058
|
var SubagentMetaObserver = class {
|
|
54573
55059
|
constructor(opts) {
|
|
54574
55060
|
this.opts = opts;
|
|
54575
|
-
this.home = opts.home ??
|
|
55061
|
+
this.home = opts.home ?? import_node_os12.default.homedir();
|
|
54576
55062
|
}
|
|
54577
55063
|
opts;
|
|
54578
55064
|
home;
|
|
54579
55065
|
watches = /* @__PURE__ */ new Map();
|
|
54580
55066
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
54581
55067
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
54582
|
-
return
|
|
55068
|
+
return import_node_path34.default.join(
|
|
54583
55069
|
this.home,
|
|
54584
55070
|
".claude",
|
|
54585
55071
|
"projects",
|
|
@@ -54609,7 +55095,7 @@ var SubagentMetaObserver = class {
|
|
|
54609
55095
|
attachWatcher(w2) {
|
|
54610
55096
|
if (w2.watcher) return;
|
|
54611
55097
|
try {
|
|
54612
|
-
w2.watcher =
|
|
55098
|
+
w2.watcher = import_node_fs32.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
54613
55099
|
if (!name) return;
|
|
54614
55100
|
const m2 = META_RE.exec(String(name));
|
|
54615
55101
|
if (!m2) return;
|
|
@@ -54621,7 +55107,7 @@ var SubagentMetaObserver = class {
|
|
|
54621
55107
|
scan(w2) {
|
|
54622
55108
|
let entries;
|
|
54623
55109
|
try {
|
|
54624
|
-
entries =
|
|
55110
|
+
entries = import_node_fs32.default.readdirSync(w2.dirPath);
|
|
54625
55111
|
} catch {
|
|
54626
55112
|
return;
|
|
54627
55113
|
}
|
|
@@ -54635,10 +55121,10 @@ var SubagentMetaObserver = class {
|
|
|
54635
55121
|
if (!m2) return;
|
|
54636
55122
|
const agentId = m2[1];
|
|
54637
55123
|
if (w2.emitted.has(agentId)) return;
|
|
54638
|
-
const file =
|
|
55124
|
+
const file = import_node_path34.default.join(w2.dirPath, name);
|
|
54639
55125
|
let raw;
|
|
54640
55126
|
try {
|
|
54641
|
-
raw =
|
|
55127
|
+
raw = import_node_fs32.default.readFileSync(file, "utf8");
|
|
54642
55128
|
} catch {
|
|
54643
55129
|
return;
|
|
54644
55130
|
}
|
|
@@ -54683,7 +55169,7 @@ var SubagentMetaObserver = class {
|
|
|
54683
55169
|
var SessionObserver = class {
|
|
54684
55170
|
constructor(opts) {
|
|
54685
55171
|
this.opts = opts;
|
|
54686
|
-
this.home = opts.home ??
|
|
55172
|
+
this.home = opts.home ?? import_node_os13.default.homedir();
|
|
54687
55173
|
this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
|
|
54688
55174
|
}
|
|
54689
55175
|
opts;
|
|
@@ -54695,14 +55181,14 @@ var SessionObserver = class {
|
|
|
54695
55181
|
metaObserver;
|
|
54696
55182
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
54697
55183
|
if (override) return override;
|
|
54698
|
-
return
|
|
55184
|
+
return import_node_path35.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
54699
55185
|
}
|
|
54700
55186
|
start(args) {
|
|
54701
55187
|
this.stop(args.sessionId);
|
|
54702
55188
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
54703
55189
|
let size = 0;
|
|
54704
55190
|
try {
|
|
54705
|
-
size =
|
|
55191
|
+
size = import_node_fs33.default.statSync(filePath).size;
|
|
54706
55192
|
} catch {
|
|
54707
55193
|
}
|
|
54708
55194
|
const w2 = {
|
|
@@ -54715,16 +55201,16 @@ var SessionObserver = class {
|
|
|
54715
55201
|
adapter: args.adapter,
|
|
54716
55202
|
prevIsRejectSentinel: false,
|
|
54717
55203
|
toolSessionId: args.toolSessionId,
|
|
54718
|
-
sawFile:
|
|
55204
|
+
sawFile: import_node_fs33.default.existsSync(filePath),
|
|
54719
55205
|
lastRelocateScanMs: 0,
|
|
54720
55206
|
pendingCwdDerive: false,
|
|
54721
55207
|
lastDeriveMs: 0
|
|
54722
55208
|
};
|
|
54723
55209
|
try {
|
|
54724
|
-
|
|
55210
|
+
import_node_fs33.default.mkdirSync(import_node_path35.default.dirname(filePath), { recursive: true });
|
|
54725
55211
|
} catch {
|
|
54726
55212
|
}
|
|
54727
|
-
w2.watcher =
|
|
55213
|
+
w2.watcher = import_node_fs33.default.watch(import_node_path35.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
54728
55214
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
54729
55215
|
this.poll(w2);
|
|
54730
55216
|
});
|
|
@@ -54747,7 +55233,7 @@ var SessionObserver = class {
|
|
|
54747
55233
|
// 异常静默吞,不阻塞 watcher 启动
|
|
54748
55234
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
54749
55235
|
try {
|
|
54750
|
-
const raw =
|
|
55236
|
+
const raw = import_node_fs33.default.readFileSync(w2.filePath, "utf8");
|
|
54751
55237
|
if (!raw) return;
|
|
54752
55238
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
54753
55239
|
if (allLines.length === 0) return;
|
|
@@ -54771,7 +55257,7 @@ var SessionObserver = class {
|
|
|
54771
55257
|
poll(w2) {
|
|
54772
55258
|
let size = 0;
|
|
54773
55259
|
try {
|
|
54774
|
-
size =
|
|
55260
|
+
size = import_node_fs33.default.statSync(w2.filePath).size;
|
|
54775
55261
|
} catch {
|
|
54776
55262
|
if (w2.sawFile) this.maybeRelocate(w2);
|
|
54777
55263
|
return;
|
|
@@ -54782,11 +55268,11 @@ var SessionObserver = class {
|
|
|
54782
55268
|
w2.buf = "";
|
|
54783
55269
|
}
|
|
54784
55270
|
if (size === w2.lastSize) return;
|
|
54785
|
-
const fd =
|
|
55271
|
+
const fd = import_node_fs33.default.openSync(w2.filePath, "r");
|
|
54786
55272
|
try {
|
|
54787
55273
|
const len = size - w2.lastSize;
|
|
54788
55274
|
const buf = Buffer.alloc(len);
|
|
54789
|
-
|
|
55275
|
+
import_node_fs33.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
54790
55276
|
w2.lastSize = size;
|
|
54791
55277
|
w2.buf += buf.toString("utf8");
|
|
54792
55278
|
let newlineIndex;
|
|
@@ -54809,7 +55295,7 @@ var SessionObserver = class {
|
|
|
54809
55295
|
}
|
|
54810
55296
|
}
|
|
54811
55297
|
} finally {
|
|
54812
|
-
|
|
55298
|
+
import_node_fs33.default.closeSync(fd);
|
|
54813
55299
|
}
|
|
54814
55300
|
if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
|
|
54815
55301
|
}
|
|
@@ -54821,7 +55307,7 @@ var SessionObserver = class {
|
|
|
54821
55307
|
const now = Date.now();
|
|
54822
55308
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
54823
55309
|
w2.lastRelocateScanMs = now;
|
|
54824
|
-
const projectsRoot =
|
|
55310
|
+
const projectsRoot = import_node_path35.default.join(this.home, ".claude", "projects");
|
|
54825
55311
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
54826
55312
|
if (!found || found === w2.filePath) return;
|
|
54827
55313
|
try {
|
|
@@ -54830,7 +55316,7 @@ var SessionObserver = class {
|
|
|
54830
55316
|
}
|
|
54831
55317
|
w2.filePath = found;
|
|
54832
55318
|
try {
|
|
54833
|
-
w2.watcher =
|
|
55319
|
+
w2.watcher = import_node_fs33.default.watch(import_node_path35.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
54834
55320
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
54835
55321
|
this.poll(w2);
|
|
54836
55322
|
});
|
|
@@ -54949,149 +55435,6 @@ function listRegistered() {
|
|
|
54949
55435
|
return [...registry.keys()];
|
|
54950
55436
|
}
|
|
54951
55437
|
|
|
54952
|
-
// src/tools/title-generator.ts
|
|
54953
|
-
var import_node_child_process8 = require("child_process");
|
|
54954
|
-
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
54955
|
-
var import_node_os12 = __toESM(require("os"), 1);
|
|
54956
|
-
var import_node_path34 = __toESM(require("path"), 1);
|
|
54957
|
-
var TITLE_GEN_DIR_NAME = "clawd-title-gen";
|
|
54958
|
-
var TITLE_MODEL_BY_TOOL = {
|
|
54959
|
-
claude: "haiku",
|
|
54960
|
-
codex: "gpt-5.4-mini"
|
|
54961
|
-
};
|
|
54962
|
-
var TITLE_INPUT_MAX_CHARS = 400;
|
|
54963
|
-
var DEFAULT_TITLE_GEN_TIMEOUT_MS = 45e3;
|
|
54964
|
-
var outFileSeq = 0;
|
|
54965
|
-
function buildTitlePrompt(firstMessage) {
|
|
54966
|
-
const text = firstMessage.slice(0, TITLE_INPUT_MAX_CHARS);
|
|
54967
|
-
return `\u4E3A\u4E0B\u9762\u8FD9\u6761\u7528\u6237\u6D88\u606F\u751F\u6210\u4E00\u4E2A\u7B80\u6D01\u7684\u4F1A\u8BDD\u6807\u9898\uFF1A\u4E0D\u8D85\u8FC7 20 \u4E2A\u5B57\uFF08\u82F1\u6587\u5219\u4E0D\u8D85\u8FC7 6 \u4E2A\u5355\u8BCD\uFF09\uFF0C\u4F7F\u7528\u4E0E\u6D88\u606F\u76F8\u540C\u7684\u8BED\u8A00\uFF0C\u53EA\u6982\u62EC\u6D88\u606F\u4E3B\u9898\u3002
|
|
54968
|
-
|
|
54969
|
-
\u7528\u6237\u6D88\u606F\uFF1A
|
|
54970
|
-
${text}`;
|
|
54971
|
-
}
|
|
54972
|
-
function buildClaudeTitlePrompt(firstMessage) {
|
|
54973
|
-
return buildTitlePrompt(firstMessage) + '\n\n\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u683C\u5F0F\uFF1A{"greeting":"\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC","title":"\u4F1A\u8BDD\u6807\u9898"}\uFF0C\u4E0D\u8981\u8F93\u51FA JSON \u4EE5\u5916\u7684\u4EFB\u4F55\u5185\u5BB9\u3002';
|
|
54974
|
-
}
|
|
54975
|
-
function sanitizeTitle(raw) {
|
|
54976
|
-
const line = raw.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
|
|
54977
|
-
if (!line) return null;
|
|
54978
|
-
const stripped = line.replace(/^["'“”‘’「」《》\[\((]+/, "").replace(/["'“”‘’「」《》\]\))]+$/, "").replace(/[。..!!??]+$/, "").replace(/\s+/g, " ").trim();
|
|
54979
|
-
if (!stripped) return null;
|
|
54980
|
-
return stripped.slice(0, 60);
|
|
54981
|
-
}
|
|
54982
|
-
function buildClaudeTitleArgs(prompt) {
|
|
54983
|
-
return ["-p", "--model", TITLE_MODEL_BY_TOOL.claude, prompt];
|
|
54984
|
-
}
|
|
54985
|
-
var CODEX_TITLE_SCHEMA = JSON.stringify({
|
|
54986
|
-
type: "object",
|
|
54987
|
-
properties: {
|
|
54988
|
-
greeting: { type: "string", description: "\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC" },
|
|
54989
|
-
title: { type: "string", description: "\u4F1A\u8BDD\u6807\u9898\uFF1A\u53EA\u542B\u6D88\u606F\u4E3B\u9898" }
|
|
54990
|
-
},
|
|
54991
|
-
required: ["greeting", "title"],
|
|
54992
|
-
additionalProperties: false
|
|
54993
|
-
});
|
|
54994
|
-
function parseTitleJson(raw) {
|
|
54995
|
-
const text = raw.trim().replace(/^```[a-zA-Z]*\s*/, "").replace(/```\s*$/, "").trim();
|
|
54996
|
-
try {
|
|
54997
|
-
const obj = JSON.parse(text);
|
|
54998
|
-
if (typeof obj.title === "string") return sanitizeTitle(obj.title);
|
|
54999
|
-
} catch {
|
|
55000
|
-
}
|
|
55001
|
-
return sanitizeTitle(text);
|
|
55002
|
-
}
|
|
55003
|
-
function buildCodexTitleArgs(prompt, outFile, schemaFile) {
|
|
55004
|
-
return [
|
|
55005
|
-
"exec",
|
|
55006
|
-
"--ephemeral",
|
|
55007
|
-
"--skip-git-repo-check",
|
|
55008
|
-
"--output-schema",
|
|
55009
|
-
schemaFile,
|
|
55010
|
-
"-s",
|
|
55011
|
-
"read-only",
|
|
55012
|
-
"-m",
|
|
55013
|
-
TITLE_MODEL_BY_TOOL.codex,
|
|
55014
|
-
"--color",
|
|
55015
|
-
"never",
|
|
55016
|
-
"-o",
|
|
55017
|
-
outFile,
|
|
55018
|
-
prompt
|
|
55019
|
-
];
|
|
55020
|
-
}
|
|
55021
|
-
async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
55022
|
-
if (tool !== "claude" && tool !== "codex") return null;
|
|
55023
|
-
const text = firstMessage.trim();
|
|
55024
|
-
if (!text) return null;
|
|
55025
|
-
const workDir = import_node_path34.default.join(import_node_os12.default.tmpdir(), TITLE_GEN_DIR_NAME);
|
|
55026
|
-
try {
|
|
55027
|
-
import_node_fs32.default.mkdirSync(workDir, { recursive: true });
|
|
55028
|
-
} catch {
|
|
55029
|
-
return null;
|
|
55030
|
-
}
|
|
55031
|
-
const outFile = import_node_path34.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
55032
|
-
const schemaFile = import_node_path34.default.join(workDir, "title-schema.json");
|
|
55033
|
-
if (tool === "codex") {
|
|
55034
|
-
try {
|
|
55035
|
-
import_node_fs32.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA, { flag: "wx" });
|
|
55036
|
-
} catch (err) {
|
|
55037
|
-
if (err.code !== "EEXIST") return null;
|
|
55038
|
-
}
|
|
55039
|
-
}
|
|
55040
|
-
const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : process.env.CODEX_BIN ?? "codex";
|
|
55041
|
-
const args = tool === "claude" ? buildClaudeTitleArgs(buildClaudeTitlePrompt(text)) : buildCodexTitleArgs(buildTitlePrompt(text), outFile, schemaFile);
|
|
55042
|
-
const doSpawn = deps.spawnOverride ?? ((c, a, o) => (0, import_node_child_process8.spawn)(c, a, { ...o, stdio: ["ignore", "pipe", "pipe"] }));
|
|
55043
|
-
const timeoutMs = deps.timeoutMs ?? DEFAULT_TITLE_GEN_TIMEOUT_MS;
|
|
55044
|
-
return await new Promise((resolve7) => {
|
|
55045
|
-
let proc;
|
|
55046
|
-
try {
|
|
55047
|
-
proc = doSpawn(cmd, args, { cwd: workDir });
|
|
55048
|
-
} catch (err) {
|
|
55049
|
-
deps.logger?.warn("title-gen spawn failed", { tool, message: err.message });
|
|
55050
|
-
return resolve7(null);
|
|
55051
|
-
}
|
|
55052
|
-
let stdout = "";
|
|
55053
|
-
let settled = false;
|
|
55054
|
-
const finish = (title) => {
|
|
55055
|
-
if (settled) return;
|
|
55056
|
-
settled = true;
|
|
55057
|
-
clearTimeout(timer);
|
|
55058
|
-
if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGKILL");
|
|
55059
|
-
try {
|
|
55060
|
-
import_node_fs32.default.rmSync(outFile, { force: true });
|
|
55061
|
-
} catch {
|
|
55062
|
-
}
|
|
55063
|
-
resolve7(title);
|
|
55064
|
-
};
|
|
55065
|
-
const timer = setTimeout(() => {
|
|
55066
|
-
deps.logger?.warn("title-gen timed out", { tool, timeoutMs });
|
|
55067
|
-
finish(null);
|
|
55068
|
-
}, timeoutMs);
|
|
55069
|
-
proc.stdout?.on("data", (c) => {
|
|
55070
|
-
stdout += c.toString();
|
|
55071
|
-
});
|
|
55072
|
-
proc.stderr?.on("data", () => {
|
|
55073
|
-
});
|
|
55074
|
-
proc.on("error", (err) => {
|
|
55075
|
-
deps.logger?.warn("title-gen proc error", { tool, message: err.message });
|
|
55076
|
-
finish(null);
|
|
55077
|
-
});
|
|
55078
|
-
proc.on("close", (code) => {
|
|
55079
|
-
if (code !== 0) {
|
|
55080
|
-
deps.logger?.warn("title-gen exited non-zero", { tool, code });
|
|
55081
|
-
return finish(null);
|
|
55082
|
-
}
|
|
55083
|
-
if (tool === "claude") return finish(parseTitleJson(stdout));
|
|
55084
|
-
let fileText = "";
|
|
55085
|
-
try {
|
|
55086
|
-
fileText = import_node_fs32.default.readFileSync(outFile, "utf8");
|
|
55087
|
-
} catch {
|
|
55088
|
-
return finish(null);
|
|
55089
|
-
}
|
|
55090
|
-
finish(parseTitleJson(fileText));
|
|
55091
|
-
});
|
|
55092
|
-
});
|
|
55093
|
-
}
|
|
55094
|
-
|
|
55095
55438
|
// ../node_modules/.pnpm/ws@8.20.0/node_modules/ws/wrapper.mjs
|
|
55096
55439
|
var import_stream = __toESM(require_stream(), 1);
|
|
55097
55440
|
var import_extension2 = __toESM(require_extension(), 1);
|
|
@@ -55768,8 +56111,8 @@ async function authenticate(token, deps) {
|
|
|
55768
56111
|
}
|
|
55769
56112
|
|
|
55770
56113
|
// src/legacy-cleanup.ts
|
|
55771
|
-
var
|
|
55772
|
-
var
|
|
56114
|
+
var fs40 = __toESM(require("fs/promises"), 1);
|
|
56115
|
+
var path41 = __toESM(require("path"), 1);
|
|
55773
56116
|
var LEGACY_FILES = [
|
|
55774
56117
|
"personal-capability.json",
|
|
55775
56118
|
"received-capabilities.json",
|
|
@@ -55778,9 +56121,9 @@ var LEGACY_FILES = [
|
|
|
55778
56121
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
55779
56122
|
const removed = [];
|
|
55780
56123
|
for (const name of LEGACY_FILES) {
|
|
55781
|
-
const p2 =
|
|
56124
|
+
const p2 = path41.join(dataDir, name);
|
|
55782
56125
|
try {
|
|
55783
|
-
await
|
|
56126
|
+
await fs40.unlink(p2);
|
|
55784
56127
|
removed.push(name);
|
|
55785
56128
|
logger.debug("legacy capability file removed", { file: name });
|
|
55786
56129
|
} catch (err) {
|
|
@@ -55792,13 +56135,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
55792
56135
|
}
|
|
55793
56136
|
|
|
55794
56137
|
// src/inbox/inbox-store.ts
|
|
55795
|
-
var
|
|
55796
|
-
var
|
|
56138
|
+
var fs41 = __toESM(require("fs"), 1);
|
|
56139
|
+
var path42 = __toESM(require("path"), 1);
|
|
55797
56140
|
var INBOX_SUBDIR = "inbox";
|
|
55798
56141
|
var InboxStore = class {
|
|
55799
56142
|
constructor(dataDir) {
|
|
55800
56143
|
this.dataDir = dataDir;
|
|
55801
|
-
|
|
56144
|
+
fs41.mkdirSync(this.dirPath(), { recursive: true });
|
|
55802
56145
|
}
|
|
55803
56146
|
dataDir;
|
|
55804
56147
|
/**
|
|
@@ -55810,7 +56153,7 @@ var InboxStore = class {
|
|
|
55810
56153
|
const file = this.filePath(peerDeviceId);
|
|
55811
56154
|
let raw;
|
|
55812
56155
|
try {
|
|
55813
|
-
raw =
|
|
56156
|
+
raw = fs41.readFileSync(file, "utf8");
|
|
55814
56157
|
} catch (err) {
|
|
55815
56158
|
if (err?.code === "ENOENT") return [];
|
|
55816
56159
|
return [];
|
|
@@ -55826,7 +56169,7 @@ var InboxStore = class {
|
|
|
55826
56169
|
const dir = this.dirPath();
|
|
55827
56170
|
let entries;
|
|
55828
56171
|
try {
|
|
55829
|
-
entries =
|
|
56172
|
+
entries = fs41.readdirSync(dir);
|
|
55830
56173
|
} catch (err) {
|
|
55831
56174
|
if (err?.code === "ENOENT") return [];
|
|
55832
56175
|
return [];
|
|
@@ -55842,9 +56185,9 @@ var InboxStore = class {
|
|
|
55842
56185
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
55843
56186
|
const file = this.filePath(message.peerDeviceId);
|
|
55844
56187
|
const line = JSON.stringify(message) + "\n";
|
|
55845
|
-
|
|
56188
|
+
fs41.appendFileSync(file, line, { mode: 384 });
|
|
55846
56189
|
try {
|
|
55847
|
-
|
|
56190
|
+
fs41.chmodSync(file, 384);
|
|
55848
56191
|
} catch {
|
|
55849
56192
|
}
|
|
55850
56193
|
}
|
|
@@ -55874,7 +56217,7 @@ var InboxStore = class {
|
|
|
55874
56217
|
removeByPeerDeviceId(peerDeviceId) {
|
|
55875
56218
|
const file = this.filePath(peerDeviceId);
|
|
55876
56219
|
try {
|
|
55877
|
-
|
|
56220
|
+
fs41.unlinkSync(file);
|
|
55878
56221
|
} catch (err) {
|
|
55879
56222
|
if (err?.code === "ENOENT") return;
|
|
55880
56223
|
}
|
|
@@ -55883,18 +56226,18 @@ var InboxStore = class {
|
|
|
55883
56226
|
const file = this.filePath(peerDeviceId);
|
|
55884
56227
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
55885
56228
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
55886
|
-
|
|
55887
|
-
|
|
56229
|
+
fs41.writeFileSync(tmp, content, { mode: 384 });
|
|
56230
|
+
fs41.renameSync(tmp, file);
|
|
55888
56231
|
try {
|
|
55889
|
-
|
|
56232
|
+
fs41.chmodSync(file, 384);
|
|
55890
56233
|
} catch {
|
|
55891
56234
|
}
|
|
55892
56235
|
}
|
|
55893
56236
|
dirPath() {
|
|
55894
|
-
return
|
|
56237
|
+
return path42.join(this.dataDir, INBOX_SUBDIR);
|
|
55895
56238
|
}
|
|
55896
56239
|
filePath(peerDeviceId) {
|
|
55897
|
-
return
|
|
56240
|
+
return path42.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
55898
56241
|
}
|
|
55899
56242
|
};
|
|
55900
56243
|
function parseAllLines(raw) {
|
|
@@ -55982,8 +56325,8 @@ var InboxManager = class {
|
|
|
55982
56325
|
};
|
|
55983
56326
|
|
|
55984
56327
|
// src/state/contact-store.ts
|
|
55985
|
-
var
|
|
55986
|
-
var
|
|
56328
|
+
var fs42 = __toESM(require("fs"), 1);
|
|
56329
|
+
var path43 = __toESM(require("path"), 1);
|
|
55987
56330
|
var FILE_NAME = "contacts.json";
|
|
55988
56331
|
var ContactStore = class {
|
|
55989
56332
|
constructor(dataDir) {
|
|
@@ -55993,10 +56336,10 @@ var ContactStore = class {
|
|
|
55993
56336
|
contacts = /* @__PURE__ */ new Map();
|
|
55994
56337
|
load() {
|
|
55995
56338
|
this.contacts.clear();
|
|
55996
|
-
const file =
|
|
56339
|
+
const file = path43.join(this.dataDir, FILE_NAME);
|
|
55997
56340
|
let raw;
|
|
55998
56341
|
try {
|
|
55999
|
-
raw =
|
|
56342
|
+
raw = fs42.readFileSync(file, "utf8");
|
|
56000
56343
|
} catch (err) {
|
|
56001
56344
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
56002
56345
|
return;
|
|
@@ -56065,20 +56408,20 @@ var ContactStore = class {
|
|
|
56065
56408
|
return true;
|
|
56066
56409
|
}
|
|
56067
56410
|
flush() {
|
|
56068
|
-
const file =
|
|
56411
|
+
const file = path43.join(this.dataDir, FILE_NAME);
|
|
56069
56412
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
56070
56413
|
const content = JSON.stringify(
|
|
56071
56414
|
{ contacts: Array.from(this.contacts.values()) },
|
|
56072
56415
|
null,
|
|
56073
56416
|
2
|
|
56074
56417
|
);
|
|
56075
|
-
|
|
56076
|
-
|
|
56077
|
-
|
|
56418
|
+
fs42.mkdirSync(this.dataDir, { recursive: true });
|
|
56419
|
+
fs42.writeFileSync(tmp, content, { mode: 384 });
|
|
56420
|
+
fs42.renameSync(tmp, file);
|
|
56078
56421
|
}
|
|
56079
56422
|
renameBak(file) {
|
|
56080
56423
|
try {
|
|
56081
|
-
|
|
56424
|
+
fs42.renameSync(file, `${file}.bak`);
|
|
56082
56425
|
} catch {
|
|
56083
56426
|
}
|
|
56084
56427
|
}
|
|
@@ -56186,61 +56529,61 @@ async function connectRemote(args) {
|
|
|
56186
56529
|
}
|
|
56187
56530
|
|
|
56188
56531
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
56189
|
-
var
|
|
56190
|
-
var
|
|
56532
|
+
var fs43 = __toESM(require("fs"), 1);
|
|
56533
|
+
var path44 = __toESM(require("path"), 1);
|
|
56191
56534
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
56192
56535
|
function migrateFlattenSessions(opts) {
|
|
56193
56536
|
const dataDir = opts.dataDir;
|
|
56194
56537
|
const now = opts.now ?? Date.now;
|
|
56195
|
-
const sessionsDir =
|
|
56196
|
-
const flagPath =
|
|
56538
|
+
const sessionsDir = path44.join(dataDir, "sessions");
|
|
56539
|
+
const flagPath = path44.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
56197
56540
|
if (existsSync3(flagPath)) {
|
|
56198
56541
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
56199
56542
|
}
|
|
56200
56543
|
let movedBare = 0;
|
|
56201
56544
|
let movedVmOwner = 0;
|
|
56202
56545
|
let archivedListener = 0;
|
|
56203
|
-
const defaultDir =
|
|
56546
|
+
const defaultDir = path44.join(sessionsDir, "default");
|
|
56204
56547
|
if (existsSync3(defaultDir)) {
|
|
56205
56548
|
for (const entry of readdirSafe(defaultDir)) {
|
|
56206
56549
|
if (!entry.endsWith(".json")) continue;
|
|
56207
|
-
const src =
|
|
56208
|
-
const dst =
|
|
56209
|
-
|
|
56550
|
+
const src = path44.join(defaultDir, entry);
|
|
56551
|
+
const dst = path44.join(sessionsDir, entry);
|
|
56552
|
+
fs43.renameSync(src, dst);
|
|
56210
56553
|
movedBare += 1;
|
|
56211
56554
|
}
|
|
56212
56555
|
rmdirIfEmpty(defaultDir);
|
|
56213
56556
|
}
|
|
56214
56557
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
56215
|
-
const personaDir =
|
|
56216
|
-
if (!
|
|
56558
|
+
const personaDir = path44.join(sessionsDir, pid);
|
|
56559
|
+
if (!isDir2(personaDir)) continue;
|
|
56217
56560
|
if (pid === "default") continue;
|
|
56218
|
-
const ownerSrc =
|
|
56219
|
-
if (existsSync3(ownerSrc) &&
|
|
56220
|
-
const ownerDst =
|
|
56221
|
-
|
|
56561
|
+
const ownerSrc = path44.join(personaDir, "owner");
|
|
56562
|
+
if (existsSync3(ownerSrc) && isDir2(ownerSrc)) {
|
|
56563
|
+
const ownerDst = path44.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
56564
|
+
fs43.mkdirSync(ownerDst, { recursive: true });
|
|
56222
56565
|
for (const file of readdirSafe(ownerSrc)) {
|
|
56223
56566
|
if (!file.endsWith(".json")) continue;
|
|
56224
|
-
|
|
56567
|
+
fs43.renameSync(path44.join(ownerSrc, file), path44.join(ownerDst, file));
|
|
56225
56568
|
movedVmOwner += 1;
|
|
56226
56569
|
}
|
|
56227
56570
|
rmdirIfEmpty(ownerSrc);
|
|
56228
56571
|
}
|
|
56229
|
-
const listenerSrc =
|
|
56230
|
-
if (existsSync3(listenerSrc) &&
|
|
56231
|
-
const archiveDst =
|
|
56232
|
-
|
|
56572
|
+
const listenerSrc = path44.join(personaDir, "listener");
|
|
56573
|
+
if (existsSync3(listenerSrc) && isDir2(listenerSrc)) {
|
|
56574
|
+
const archiveDst = path44.join(dataDir, ".legacy", `listener-${pid}`);
|
|
56575
|
+
fs43.mkdirSync(archiveDst, { recursive: true });
|
|
56233
56576
|
for (const file of readdirSafe(listenerSrc)) {
|
|
56234
56577
|
if (!file.endsWith(".json")) continue;
|
|
56235
|
-
|
|
56578
|
+
fs43.renameSync(path44.join(listenerSrc, file), path44.join(archiveDst, file));
|
|
56236
56579
|
archivedListener += 1;
|
|
56237
56580
|
}
|
|
56238
56581
|
rmdirIfEmpty(listenerSrc);
|
|
56239
56582
|
}
|
|
56240
56583
|
rmdirIfEmpty(personaDir);
|
|
56241
56584
|
}
|
|
56242
|
-
|
|
56243
|
-
|
|
56585
|
+
fs43.mkdirSync(sessionsDir, { recursive: true });
|
|
56586
|
+
fs43.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
56244
56587
|
return {
|
|
56245
56588
|
skipped: false,
|
|
56246
56589
|
flagWritten: true,
|
|
@@ -56251,39 +56594,39 @@ function migrateFlattenSessions(opts) {
|
|
|
56251
56594
|
}
|
|
56252
56595
|
function existsSync3(p2) {
|
|
56253
56596
|
try {
|
|
56254
|
-
|
|
56597
|
+
fs43.statSync(p2);
|
|
56255
56598
|
return true;
|
|
56256
56599
|
} catch {
|
|
56257
56600
|
return false;
|
|
56258
56601
|
}
|
|
56259
56602
|
}
|
|
56260
|
-
function
|
|
56603
|
+
function isDir2(p2) {
|
|
56261
56604
|
try {
|
|
56262
|
-
return
|
|
56605
|
+
return fs43.statSync(p2).isDirectory();
|
|
56263
56606
|
} catch {
|
|
56264
56607
|
return false;
|
|
56265
56608
|
}
|
|
56266
56609
|
}
|
|
56267
56610
|
function readdirSafe(p2) {
|
|
56268
56611
|
try {
|
|
56269
|
-
return
|
|
56612
|
+
return fs43.readdirSync(p2);
|
|
56270
56613
|
} catch {
|
|
56271
56614
|
return [];
|
|
56272
56615
|
}
|
|
56273
56616
|
}
|
|
56274
56617
|
function rmdirIfEmpty(p2) {
|
|
56275
56618
|
try {
|
|
56276
|
-
|
|
56619
|
+
fs43.rmdirSync(p2);
|
|
56277
56620
|
} catch {
|
|
56278
56621
|
}
|
|
56279
56622
|
}
|
|
56280
56623
|
|
|
56281
56624
|
// src/transport/http-router.ts
|
|
56282
|
-
var
|
|
56283
|
-
var
|
|
56625
|
+
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
56626
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
56284
56627
|
|
|
56285
56628
|
// src/attachment/mime.ts
|
|
56286
|
-
var
|
|
56629
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
56287
56630
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
56288
56631
|
var EXT_TO_NATIVE_MIME = {
|
|
56289
56632
|
// 图片
|
|
@@ -56390,7 +56733,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
56390
56733
|
".mk"
|
|
56391
56734
|
]);
|
|
56392
56735
|
function lookupMime(filePathOrName) {
|
|
56393
|
-
const ext =
|
|
56736
|
+
const ext = import_node_path36.default.extname(filePathOrName).toLowerCase();
|
|
56394
56737
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
56395
56738
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
56396
56739
|
return "application/octet-stream";
|
|
@@ -56460,10 +56803,10 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
56460
56803
|
}
|
|
56461
56804
|
|
|
56462
56805
|
// src/attachment/upload.ts
|
|
56463
|
-
var
|
|
56464
|
-
var
|
|
56806
|
+
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
56807
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
56465
56808
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
56466
|
-
var
|
|
56809
|
+
var import_promises5 = require("stream/promises");
|
|
56467
56810
|
var UploadError = class extends Error {
|
|
56468
56811
|
constructor(code, message) {
|
|
56469
56812
|
super(message);
|
|
@@ -56473,27 +56816,27 @@ var UploadError = class extends Error {
|
|
|
56473
56816
|
code;
|
|
56474
56817
|
};
|
|
56475
56818
|
function assertValidFileName(fileName) {
|
|
56476
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
56819
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path37.default.basename(fileName)) {
|
|
56477
56820
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
56478
56821
|
}
|
|
56479
56822
|
}
|
|
56480
56823
|
var HASH_PREFIX_LEN = 16;
|
|
56481
56824
|
async function writeUploadedAttachment(args) {
|
|
56482
56825
|
assertValidFileName(args.fileName);
|
|
56483
|
-
const attachmentsRoot =
|
|
56826
|
+
const attachmentsRoot = import_node_path37.default.join(args.baseDir, ".attachments");
|
|
56484
56827
|
try {
|
|
56485
|
-
|
|
56828
|
+
import_node_fs34.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
56486
56829
|
} catch (err) {
|
|
56487
56830
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
56488
56831
|
}
|
|
56489
56832
|
const hasher = import_node_crypto9.default.createHash("sha256");
|
|
56490
56833
|
let actualSize = 0;
|
|
56491
|
-
const tmpPath =
|
|
56834
|
+
const tmpPath = import_node_path37.default.join(
|
|
56492
56835
|
attachmentsRoot,
|
|
56493
56836
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto9.default.randomBytes(4).toString("hex")}`
|
|
56494
56837
|
);
|
|
56495
56838
|
try {
|
|
56496
|
-
await (0,
|
|
56839
|
+
await (0, import_promises5.pipeline)(
|
|
56497
56840
|
args.body,
|
|
56498
56841
|
async function* (source) {
|
|
56499
56842
|
for await (const chunk of source) {
|
|
@@ -56503,18 +56846,18 @@ async function writeUploadedAttachment(args) {
|
|
|
56503
56846
|
yield buf;
|
|
56504
56847
|
}
|
|
56505
56848
|
},
|
|
56506
|
-
|
|
56849
|
+
import_node_fs34.default.createWriteStream(tmpPath, { mode: 384 })
|
|
56507
56850
|
);
|
|
56508
56851
|
} catch (err) {
|
|
56509
56852
|
try {
|
|
56510
|
-
|
|
56853
|
+
import_node_fs34.default.unlinkSync(tmpPath);
|
|
56511
56854
|
} catch {
|
|
56512
56855
|
}
|
|
56513
56856
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
56514
56857
|
}
|
|
56515
56858
|
if (actualSize !== args.contentLength) {
|
|
56516
56859
|
try {
|
|
56517
|
-
|
|
56860
|
+
import_node_fs34.default.unlinkSync(tmpPath);
|
|
56518
56861
|
} catch {
|
|
56519
56862
|
}
|
|
56520
56863
|
throw new UploadError(
|
|
@@ -56523,34 +56866,34 @@ async function writeUploadedAttachment(args) {
|
|
|
56523
56866
|
);
|
|
56524
56867
|
}
|
|
56525
56868
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
56526
|
-
const hashDir =
|
|
56869
|
+
const hashDir = import_node_path37.default.join(attachmentsRoot, attachmentId);
|
|
56527
56870
|
let finalFileName;
|
|
56528
56871
|
let hashDirExists = false;
|
|
56529
56872
|
try {
|
|
56530
|
-
hashDirExists =
|
|
56873
|
+
hashDirExists = import_node_fs34.default.statSync(hashDir).isDirectory();
|
|
56531
56874
|
} catch {
|
|
56532
56875
|
}
|
|
56533
56876
|
if (hashDirExists) {
|
|
56534
|
-
const existing =
|
|
56877
|
+
const existing = import_node_fs34.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
56535
56878
|
finalFileName = existing[0] ?? args.fileName;
|
|
56536
56879
|
try {
|
|
56537
|
-
|
|
56880
|
+
import_node_fs34.default.unlinkSync(tmpPath);
|
|
56538
56881
|
} catch {
|
|
56539
56882
|
}
|
|
56540
56883
|
} else {
|
|
56541
56884
|
try {
|
|
56542
|
-
|
|
56885
|
+
import_node_fs34.default.mkdirSync(hashDir, { recursive: true });
|
|
56543
56886
|
finalFileName = args.fileName;
|
|
56544
|
-
|
|
56887
|
+
import_node_fs34.default.renameSync(tmpPath, import_node_path37.default.join(hashDir, finalFileName));
|
|
56545
56888
|
} catch (err) {
|
|
56546
56889
|
try {
|
|
56547
|
-
|
|
56890
|
+
import_node_fs34.default.unlinkSync(tmpPath);
|
|
56548
56891
|
} catch {
|
|
56549
56892
|
}
|
|
56550
56893
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
56551
56894
|
}
|
|
56552
56895
|
}
|
|
56553
|
-
const absPath =
|
|
56896
|
+
const absPath = import_node_path37.default.join(hashDir, finalFileName);
|
|
56554
56897
|
const relPath = absPath;
|
|
56555
56898
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
56556
56899
|
relPath: absPath,
|
|
@@ -56564,9 +56907,9 @@ async function writeUploadedAttachment(args) {
|
|
|
56564
56907
|
}
|
|
56565
56908
|
|
|
56566
56909
|
// src/extension/import.ts
|
|
56567
|
-
var
|
|
56568
|
-
var
|
|
56569
|
-
var
|
|
56910
|
+
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
56911
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
56912
|
+
var import_node_os14 = __toESM(require("os"), 1);
|
|
56570
56913
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
56571
56914
|
var ImportError = class extends Error {
|
|
56572
56915
|
constructor(code, message) {
|
|
@@ -56583,7 +56926,7 @@ async function importZip(buf, root) {
|
|
|
56583
56926
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
56584
56927
|
}
|
|
56585
56928
|
for (const name of Object.keys(zip.files)) {
|
|
56586
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
56929
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path38.default.isAbsolute(name)) {
|
|
56587
56930
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
56588
56931
|
}
|
|
56589
56932
|
}
|
|
@@ -56616,33 +56959,33 @@ async function importZip(buf, root) {
|
|
|
56616
56959
|
);
|
|
56617
56960
|
}
|
|
56618
56961
|
}
|
|
56619
|
-
const destDir =
|
|
56962
|
+
const destDir = import_node_path38.default.join(root, manifest.id);
|
|
56620
56963
|
let destExists = false;
|
|
56621
56964
|
try {
|
|
56622
|
-
await
|
|
56965
|
+
await import_promises6.default.access(destDir);
|
|
56623
56966
|
destExists = true;
|
|
56624
56967
|
} catch {
|
|
56625
56968
|
}
|
|
56626
56969
|
if (destExists) {
|
|
56627
56970
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
56628
56971
|
}
|
|
56629
|
-
const stage = await
|
|
56972
|
+
const stage = await import_promises6.default.mkdtemp(import_node_path38.default.join(import_node_os14.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
56630
56973
|
try {
|
|
56631
56974
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
56632
|
-
const dest =
|
|
56975
|
+
const dest = import_node_path38.default.join(stage, name);
|
|
56633
56976
|
if (entry.dir) {
|
|
56634
|
-
await
|
|
56977
|
+
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
56635
56978
|
continue;
|
|
56636
56979
|
}
|
|
56637
|
-
await
|
|
56980
|
+
await import_promises6.default.mkdir(import_node_path38.default.dirname(dest), { recursive: true });
|
|
56638
56981
|
const content = await entry.async("nodebuffer");
|
|
56639
|
-
await
|
|
56982
|
+
await import_promises6.default.writeFile(dest, content);
|
|
56640
56983
|
}
|
|
56641
|
-
await
|
|
56642
|
-
await
|
|
56984
|
+
await import_promises6.default.mkdir(root, { recursive: true });
|
|
56985
|
+
await import_promises6.default.rename(stage, destDir);
|
|
56643
56986
|
return { extId: manifest.id };
|
|
56644
56987
|
} catch (e) {
|
|
56645
|
-
await
|
|
56988
|
+
await import_promises6.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
56646
56989
|
});
|
|
56647
56990
|
throw e;
|
|
56648
56991
|
}
|
|
@@ -56664,7 +57007,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
56664
57007
|
".wasm": "application/wasm"
|
|
56665
57008
|
};
|
|
56666
57009
|
function shareUiAssetMime(filePath) {
|
|
56667
|
-
const ext =
|
|
57010
|
+
const ext = import_node_path39.default.extname(filePath).toLowerCase();
|
|
56668
57011
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
56669
57012
|
}
|
|
56670
57013
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -56763,7 +57106,7 @@ function isValidUploadFileName(fileName) {
|
|
|
56763
57106
|
if (fileName === "." || fileName === "..") return false;
|
|
56764
57107
|
if (fileName.startsWith(".")) return false;
|
|
56765
57108
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
56766
|
-
return fileName ===
|
|
57109
|
+
return fileName === import_node_path39.default.basename(fileName);
|
|
56767
57110
|
}
|
|
56768
57111
|
function createHttpRouter(deps) {
|
|
56769
57112
|
return async (req, res) => {
|
|
@@ -56851,7 +57194,7 @@ function createHttpRouter(deps) {
|
|
|
56851
57194
|
}
|
|
56852
57195
|
let buf;
|
|
56853
57196
|
try {
|
|
56854
|
-
buf = await
|
|
57197
|
+
buf = await import_node_fs35.default.promises.readFile(abs);
|
|
56855
57198
|
} catch {
|
|
56856
57199
|
sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
56857
57200
|
return true;
|
|
@@ -56999,7 +57342,7 @@ function createHttpRouter(deps) {
|
|
|
56999
57342
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
57000
57343
|
return true;
|
|
57001
57344
|
}
|
|
57002
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
57345
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path39.default.basename(r.absPath)));
|
|
57003
57346
|
return true;
|
|
57004
57347
|
}
|
|
57005
57348
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -57120,7 +57463,7 @@ function createHttpRouter(deps) {
|
|
|
57120
57463
|
return true;
|
|
57121
57464
|
}
|
|
57122
57465
|
let absPath;
|
|
57123
|
-
if (
|
|
57466
|
+
if (import_node_path39.default.isAbsolute(pathParam)) {
|
|
57124
57467
|
absPath = pathParam;
|
|
57125
57468
|
} else if (deps.sessionStore) {
|
|
57126
57469
|
const file = deps.sessionStore.read(sid);
|
|
@@ -57128,7 +57471,7 @@ function createHttpRouter(deps) {
|
|
|
57128
57471
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
57129
57472
|
return true;
|
|
57130
57473
|
}
|
|
57131
|
-
absPath =
|
|
57474
|
+
absPath = import_node_path39.default.join(file.cwd, pathParam);
|
|
57132
57475
|
} else {
|
|
57133
57476
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
57134
57477
|
return true;
|
|
@@ -57215,7 +57558,7 @@ function withCtx(ctx, body) {
|
|
|
57215
57558
|
function streamFile(res, absPath, logger) {
|
|
57216
57559
|
let stat;
|
|
57217
57560
|
try {
|
|
57218
|
-
stat =
|
|
57561
|
+
stat = import_node_fs35.default.statSync(absPath);
|
|
57219
57562
|
} catch (err) {
|
|
57220
57563
|
const code = err?.code;
|
|
57221
57564
|
if (code === "ENOENT") {
|
|
@@ -57230,7 +57573,7 @@ function streamFile(res, absPath, logger) {
|
|
|
57230
57573
|
return;
|
|
57231
57574
|
}
|
|
57232
57575
|
const mime = lookupMime(absPath);
|
|
57233
|
-
const basename2 =
|
|
57576
|
+
const basename2 = import_node_path39.default.basename(absPath);
|
|
57234
57577
|
res.writeHead(200, {
|
|
57235
57578
|
"Content-Type": mime,
|
|
57236
57579
|
"Content-Length": String(stat.size),
|
|
@@ -57238,7 +57581,7 @@ function streamFile(res, absPath, logger) {
|
|
|
57238
57581
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
57239
57582
|
"X-Content-Type-Options": "nosniff"
|
|
57240
57583
|
});
|
|
57241
|
-
const stream =
|
|
57584
|
+
const stream = import_node_fs35.default.createReadStream(absPath);
|
|
57242
57585
|
stream.on("error", (err) => {
|
|
57243
57586
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
57244
57587
|
res.destroy();
|
|
@@ -57247,8 +57590,8 @@ function streamFile(res, absPath, logger) {
|
|
|
57247
57590
|
}
|
|
57248
57591
|
|
|
57249
57592
|
// src/attachment/gc.ts
|
|
57250
|
-
var
|
|
57251
|
-
var
|
|
57593
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
57594
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
57252
57595
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
57253
57596
|
function runAttachmentGc(args) {
|
|
57254
57597
|
const now = (args.now ?? Date.now)();
|
|
@@ -57257,12 +57600,12 @@ function runAttachmentGc(args) {
|
|
|
57257
57600
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
57258
57601
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
57259
57602
|
if (entry.stale) continue;
|
|
57260
|
-
if (
|
|
57603
|
+
if (import_node_path40.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
57261
57604
|
}
|
|
57262
57605
|
}
|
|
57263
57606
|
const visited = /* @__PURE__ */ new Set();
|
|
57264
57607
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
57265
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
57608
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path40.default.join(
|
|
57266
57609
|
args.dataDir,
|
|
57267
57610
|
"sessions",
|
|
57268
57611
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -57275,28 +57618,28 @@ function runAttachmentGc(args) {
|
|
|
57275
57618
|
return true;
|
|
57276
57619
|
});
|
|
57277
57620
|
for (const rootDir of roots) {
|
|
57278
|
-
const attRoot =
|
|
57621
|
+
const attRoot = import_node_path40.default.join(rootDir, ".attachments");
|
|
57279
57622
|
let hashDirs;
|
|
57280
57623
|
try {
|
|
57281
|
-
hashDirs =
|
|
57624
|
+
hashDirs = import_node_fs36.default.readdirSync(attRoot);
|
|
57282
57625
|
} catch (err) {
|
|
57283
57626
|
if (err.code === "ENOENT") continue;
|
|
57284
57627
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
57285
57628
|
continue;
|
|
57286
57629
|
}
|
|
57287
57630
|
for (const hashDir of hashDirs) {
|
|
57288
|
-
const hashDirAbs =
|
|
57631
|
+
const hashDirAbs = import_node_path40.default.join(attRoot, hashDir);
|
|
57289
57632
|
let files;
|
|
57290
57633
|
try {
|
|
57291
|
-
files =
|
|
57634
|
+
files = import_node_fs36.default.readdirSync(hashDirAbs);
|
|
57292
57635
|
} catch {
|
|
57293
57636
|
continue;
|
|
57294
57637
|
}
|
|
57295
57638
|
for (const name of files) {
|
|
57296
|
-
const file =
|
|
57639
|
+
const file = import_node_path40.default.join(hashDirAbs, name);
|
|
57297
57640
|
let stat;
|
|
57298
57641
|
try {
|
|
57299
|
-
stat =
|
|
57642
|
+
stat = import_node_fs36.default.statSync(file);
|
|
57300
57643
|
} catch {
|
|
57301
57644
|
continue;
|
|
57302
57645
|
}
|
|
@@ -57305,18 +57648,18 @@ function runAttachmentGc(args) {
|
|
|
57305
57648
|
if (age < ttlMs) continue;
|
|
57306
57649
|
if (liveAbs.has(file)) continue;
|
|
57307
57650
|
try {
|
|
57308
|
-
|
|
57651
|
+
import_node_fs36.default.unlinkSync(file);
|
|
57309
57652
|
} catch (err) {
|
|
57310
57653
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
57311
57654
|
}
|
|
57312
57655
|
}
|
|
57313
57656
|
try {
|
|
57314
|
-
if (
|
|
57657
|
+
if (import_node_fs36.default.readdirSync(hashDirAbs).length === 0) import_node_fs36.default.rmdirSync(hashDirAbs);
|
|
57315
57658
|
} catch {
|
|
57316
57659
|
}
|
|
57317
57660
|
}
|
|
57318
57661
|
try {
|
|
57319
|
-
if (
|
|
57662
|
+
if (import_node_fs36.default.readdirSync(attRoot).length === 0) import_node_fs36.default.rmdirSync(attRoot);
|
|
57320
57663
|
} catch {
|
|
57321
57664
|
}
|
|
57322
57665
|
}
|
|
@@ -57324,8 +57667,8 @@ function runAttachmentGc(args) {
|
|
|
57324
57667
|
}
|
|
57325
57668
|
|
|
57326
57669
|
// src/attachment/group.ts
|
|
57327
|
-
var
|
|
57328
|
-
var
|
|
57670
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
57671
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
57329
57672
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
57330
57673
|
init_protocol();
|
|
57331
57674
|
var GroupFileStore = class {
|
|
@@ -57337,11 +57680,11 @@ var GroupFileStore = class {
|
|
|
57337
57680
|
this.logger = opts.logger;
|
|
57338
57681
|
}
|
|
57339
57682
|
rootForScope(scope) {
|
|
57340
|
-
return
|
|
57683
|
+
return import_node_path41.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
57341
57684
|
}
|
|
57342
57685
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
57343
57686
|
filePath(scope, sessionId) {
|
|
57344
|
-
return
|
|
57687
|
+
return import_node_path41.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
57345
57688
|
}
|
|
57346
57689
|
cacheKey(scope, sessionId) {
|
|
57347
57690
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -57350,7 +57693,7 @@ var GroupFileStore = class {
|
|
|
57350
57693
|
readFile(scope, sessionId) {
|
|
57351
57694
|
const file = this.filePath(scope, sessionId);
|
|
57352
57695
|
try {
|
|
57353
|
-
const raw =
|
|
57696
|
+
const raw = import_node_fs37.default.readFileSync(file, "utf8");
|
|
57354
57697
|
const parsed = JSON.parse(raw);
|
|
57355
57698
|
if (!Array.isArray(parsed)) {
|
|
57356
57699
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -57376,10 +57719,10 @@ var GroupFileStore = class {
|
|
|
57376
57719
|
}
|
|
57377
57720
|
writeFile(scope, sessionId, entries) {
|
|
57378
57721
|
const file = this.filePath(scope, sessionId);
|
|
57379
|
-
|
|
57722
|
+
import_node_fs37.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
|
|
57380
57723
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
57381
|
-
|
|
57382
|
-
|
|
57724
|
+
import_node_fs37.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
57725
|
+
import_node_fs37.default.renameSync(tmp, file);
|
|
57383
57726
|
}
|
|
57384
57727
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
57385
57728
|
list(scope, sessionId) {
|
|
@@ -57465,10 +57808,10 @@ var GroupFileStore = class {
|
|
|
57465
57808
|
};
|
|
57466
57809
|
|
|
57467
57810
|
// src/discovery/state-file.ts
|
|
57468
|
-
var
|
|
57469
|
-
var
|
|
57811
|
+
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
57812
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
57470
57813
|
function defaultStateFilePath(dataDir) {
|
|
57471
|
-
return
|
|
57814
|
+
return import_node_path42.default.join(dataDir, "state.json");
|
|
57472
57815
|
}
|
|
57473
57816
|
function isPidAlive(pid) {
|
|
57474
57817
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -57490,7 +57833,7 @@ var StateFileManager = class {
|
|
|
57490
57833
|
}
|
|
57491
57834
|
read() {
|
|
57492
57835
|
try {
|
|
57493
|
-
const raw =
|
|
57836
|
+
const raw = import_node_fs38.default.readFileSync(this.file, "utf8");
|
|
57494
57837
|
const parsed = JSON.parse(raw);
|
|
57495
57838
|
return parsed;
|
|
57496
57839
|
} catch {
|
|
@@ -57504,20 +57847,20 @@ var StateFileManager = class {
|
|
|
57504
57847
|
return { status: "stale", existing };
|
|
57505
57848
|
}
|
|
57506
57849
|
write(state) {
|
|
57507
|
-
|
|
57850
|
+
import_node_fs38.default.mkdirSync(import_node_path42.default.dirname(this.file), { recursive: true });
|
|
57508
57851
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
57509
|
-
|
|
57510
|
-
|
|
57852
|
+
import_node_fs38.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
57853
|
+
import_node_fs38.default.renameSync(tmp, this.file);
|
|
57511
57854
|
if (process.platform !== "win32") {
|
|
57512
57855
|
try {
|
|
57513
|
-
|
|
57856
|
+
import_node_fs38.default.chmodSync(this.file, 384);
|
|
57514
57857
|
} catch {
|
|
57515
57858
|
}
|
|
57516
57859
|
}
|
|
57517
57860
|
}
|
|
57518
57861
|
delete() {
|
|
57519
57862
|
try {
|
|
57520
|
-
|
|
57863
|
+
import_node_fs38.default.unlinkSync(this.file);
|
|
57521
57864
|
} catch {
|
|
57522
57865
|
}
|
|
57523
57866
|
}
|
|
@@ -57531,14 +57874,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
57531
57874
|
}
|
|
57532
57875
|
|
|
57533
57876
|
// src/tunnel/tunnel-manager.ts
|
|
57534
|
-
var
|
|
57535
|
-
var
|
|
57877
|
+
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
57878
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
57536
57879
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
57537
|
-
var
|
|
57880
|
+
var import_node_child_process12 = require("child_process");
|
|
57538
57881
|
|
|
57539
57882
|
// src/tunnel/tunnel-store.ts
|
|
57540
|
-
var
|
|
57541
|
-
var
|
|
57883
|
+
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
57884
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
57542
57885
|
var TunnelStore = class {
|
|
57543
57886
|
constructor(filePath) {
|
|
57544
57887
|
this.filePath = filePath;
|
|
@@ -57546,7 +57889,7 @@ var TunnelStore = class {
|
|
|
57546
57889
|
filePath;
|
|
57547
57890
|
async get() {
|
|
57548
57891
|
try {
|
|
57549
|
-
const raw = await
|
|
57892
|
+
const raw = await import_node_fs39.default.promises.readFile(this.filePath, "utf8");
|
|
57550
57893
|
const obj = JSON.parse(raw);
|
|
57551
57894
|
if (!isPersistedTunnel(obj)) return null;
|
|
57552
57895
|
return obj;
|
|
@@ -57557,22 +57900,22 @@ var TunnelStore = class {
|
|
|
57557
57900
|
}
|
|
57558
57901
|
}
|
|
57559
57902
|
async set(v2) {
|
|
57560
|
-
const dir =
|
|
57561
|
-
await
|
|
57903
|
+
const dir = import_node_path43.default.dirname(this.filePath);
|
|
57904
|
+
await import_node_fs39.default.promises.mkdir(dir, { recursive: true });
|
|
57562
57905
|
const data = JSON.stringify(v2, null, 2);
|
|
57563
57906
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
57564
|
-
await
|
|
57907
|
+
await import_node_fs39.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
57565
57908
|
if (process.platform !== "win32") {
|
|
57566
57909
|
try {
|
|
57567
|
-
await
|
|
57910
|
+
await import_node_fs39.default.promises.chmod(tmp, 384);
|
|
57568
57911
|
} catch {
|
|
57569
57912
|
}
|
|
57570
57913
|
}
|
|
57571
|
-
await
|
|
57914
|
+
await import_node_fs39.default.promises.rename(tmp, this.filePath);
|
|
57572
57915
|
}
|
|
57573
57916
|
async clear() {
|
|
57574
57917
|
try {
|
|
57575
|
-
await
|
|
57918
|
+
await import_node_fs39.default.promises.unlink(this.filePath);
|
|
57576
57919
|
} catch (err) {
|
|
57577
57920
|
const code = err?.code;
|
|
57578
57921
|
if (code !== "ENOENT") throw err;
|
|
@@ -57667,12 +58010,12 @@ function escape(v2) {
|
|
|
57667
58010
|
}
|
|
57668
58011
|
|
|
57669
58012
|
// src/tunnel/frpc-binary.ts
|
|
57670
|
-
var
|
|
57671
|
-
var
|
|
57672
|
-
var
|
|
57673
|
-
var
|
|
58013
|
+
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
58014
|
+
var import_node_os15 = __toESM(require("os"), 1);
|
|
58015
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
58016
|
+
var import_node_child_process10 = require("child_process");
|
|
57674
58017
|
var import_node_stream3 = require("stream");
|
|
57675
|
-
var
|
|
58018
|
+
var import_promises7 = require("stream/promises");
|
|
57676
58019
|
var FRPC_VERSION = "0.68.0";
|
|
57677
58020
|
var UnsupportedPlatformError = class extends Error {
|
|
57678
58021
|
constructor(platform, arch) {
|
|
@@ -57701,20 +58044,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
57701
58044
|
}
|
|
57702
58045
|
async function ensureFrpcBinary(opts) {
|
|
57703
58046
|
if (opts.override) {
|
|
57704
|
-
if (!
|
|
58047
|
+
if (!import_node_fs40.default.existsSync(opts.override)) {
|
|
57705
58048
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
57706
58049
|
}
|
|
57707
58050
|
return opts.override;
|
|
57708
58051
|
}
|
|
57709
58052
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
57710
58053
|
const platform = opts.platform ?? detectPlatform();
|
|
57711
|
-
const binDir =
|
|
57712
|
-
|
|
58054
|
+
const binDir = import_node_path44.default.join(opts.dataDir, "bin");
|
|
58055
|
+
import_node_fs40.default.mkdirSync(binDir, { recursive: true });
|
|
57713
58056
|
cleanupStaleArtifacts(binDir);
|
|
57714
|
-
const stableBin =
|
|
57715
|
-
if (
|
|
58057
|
+
const stableBin = import_node_path44.default.join(binDir, "frpc");
|
|
58058
|
+
if (import_node_fs40.default.existsSync(stableBin)) return stableBin;
|
|
57716
58059
|
const partialBin = `${stableBin}.partial`;
|
|
57717
|
-
const tarballPath =
|
|
58060
|
+
const tarballPath = import_node_path44.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
57718
58061
|
try {
|
|
57719
58062
|
const url = frpcDownloadUrl(version2, platform);
|
|
57720
58063
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -57723,8 +58066,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
57723
58066
|
} else {
|
|
57724
58067
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
57725
58068
|
}
|
|
57726
|
-
|
|
57727
|
-
|
|
58069
|
+
import_node_fs40.default.chmodSync(partialBin, 493);
|
|
58070
|
+
import_node_fs40.default.renameSync(partialBin, stableBin);
|
|
57728
58071
|
} finally {
|
|
57729
58072
|
safeUnlink(tarballPath);
|
|
57730
58073
|
safeUnlink(partialBin);
|
|
@@ -57734,15 +58077,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
57734
58077
|
function cleanupStaleArtifacts(binDir) {
|
|
57735
58078
|
let entries;
|
|
57736
58079
|
try {
|
|
57737
|
-
entries =
|
|
58080
|
+
entries = import_node_fs40.default.readdirSync(binDir);
|
|
57738
58081
|
} catch {
|
|
57739
58082
|
return;
|
|
57740
58083
|
}
|
|
57741
58084
|
for (const name of entries) {
|
|
57742
58085
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
57743
|
-
const full =
|
|
58086
|
+
const full = import_node_path44.default.join(binDir, name);
|
|
57744
58087
|
try {
|
|
57745
|
-
|
|
58088
|
+
import_node_fs40.default.rmSync(full, { recursive: true, force: true });
|
|
57746
58089
|
} catch {
|
|
57747
58090
|
}
|
|
57748
58091
|
}
|
|
@@ -57750,7 +58093,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
57750
58093
|
}
|
|
57751
58094
|
function safeUnlink(p2) {
|
|
57752
58095
|
try {
|
|
57753
|
-
|
|
58096
|
+
import_node_fs40.default.unlinkSync(p2);
|
|
57754
58097
|
} catch {
|
|
57755
58098
|
}
|
|
57756
58099
|
}
|
|
@@ -57761,46 +58104,46 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
57761
58104
|
if (!res.ok || !res.body) {
|
|
57762
58105
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
57763
58106
|
}
|
|
57764
|
-
const out =
|
|
58107
|
+
const out = import_node_fs40.default.createWriteStream(dest);
|
|
57765
58108
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
57766
|
-
await (0,
|
|
58109
|
+
await (0, import_promises7.pipeline)(nodeStream, out);
|
|
57767
58110
|
}
|
|
57768
58111
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
57769
|
-
const work =
|
|
57770
|
-
|
|
58112
|
+
const work = import_node_path44.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
58113
|
+
import_node_fs40.default.mkdirSync(work, { recursive: true });
|
|
57771
58114
|
try {
|
|
57772
58115
|
await new Promise((resolve7, reject) => {
|
|
57773
|
-
const proc = (0,
|
|
58116
|
+
const proc = (0, import_node_child_process10.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
57774
58117
|
proc.on("error", reject);
|
|
57775
58118
|
proc.on("exit", (code) => code === 0 ? resolve7() : reject(new Error(`tar exited ${code}`)));
|
|
57776
58119
|
});
|
|
57777
58120
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
57778
|
-
const src =
|
|
57779
|
-
if (!
|
|
58121
|
+
const src = import_node_path44.default.join(work, dirName, "frpc");
|
|
58122
|
+
if (!import_node_fs40.default.existsSync(src)) {
|
|
57780
58123
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
57781
58124
|
}
|
|
57782
|
-
|
|
58125
|
+
import_node_fs40.default.copyFileSync(src, destBin);
|
|
57783
58126
|
} finally {
|
|
57784
|
-
|
|
58127
|
+
import_node_fs40.default.rmSync(work, { recursive: true, force: true });
|
|
57785
58128
|
}
|
|
57786
58129
|
}
|
|
57787
58130
|
|
|
57788
58131
|
// src/tunnel/frpc-process.ts
|
|
57789
|
-
var
|
|
57790
|
-
var
|
|
57791
|
-
var
|
|
58132
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
58133
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
58134
|
+
var import_node_child_process11 = require("child_process");
|
|
57792
58135
|
function frpcPidFilePath(dataDir) {
|
|
57793
|
-
return
|
|
58136
|
+
return import_node_path45.default.join(dataDir, "frpc.pid");
|
|
57794
58137
|
}
|
|
57795
58138
|
function writeFrpcPid(dataDir, pid) {
|
|
57796
58139
|
try {
|
|
57797
|
-
|
|
58140
|
+
import_node_fs41.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
57798
58141
|
} catch {
|
|
57799
58142
|
}
|
|
57800
58143
|
}
|
|
57801
58144
|
function clearFrpcPid(dataDir) {
|
|
57802
58145
|
try {
|
|
57803
|
-
|
|
58146
|
+
import_node_fs41.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
57804
58147
|
} catch {
|
|
57805
58148
|
}
|
|
57806
58149
|
}
|
|
@@ -57816,7 +58159,7 @@ function defaultIsPidAlive(pid) {
|
|
|
57816
58159
|
}
|
|
57817
58160
|
function defaultReadPidFile(file) {
|
|
57818
58161
|
try {
|
|
57819
|
-
return
|
|
58162
|
+
return import_node_fs41.default.readFileSync(file, "utf8");
|
|
57820
58163
|
} catch {
|
|
57821
58164
|
return null;
|
|
57822
58165
|
}
|
|
@@ -57832,7 +58175,7 @@ function defaultSleep2(ms) {
|
|
|
57832
58175
|
}
|
|
57833
58176
|
async function killStaleFrpc(deps) {
|
|
57834
58177
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
57835
|
-
const tomlPath =
|
|
58178
|
+
const tomlPath = import_node_path45.default.join(deps.dataDir, "frpc.toml");
|
|
57836
58179
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
57837
58180
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
57838
58181
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -57856,7 +58199,7 @@ async function killStaleFrpc(deps) {
|
|
|
57856
58199
|
}
|
|
57857
58200
|
if (victims.size === 0) {
|
|
57858
58201
|
try {
|
|
57859
|
-
|
|
58202
|
+
import_node_fs41.default.unlinkSync(pidFile);
|
|
57860
58203
|
} catch {
|
|
57861
58204
|
}
|
|
57862
58205
|
return;
|
|
@@ -57867,14 +58210,14 @@ async function killStaleFrpc(deps) {
|
|
|
57867
58210
|
}
|
|
57868
58211
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
57869
58212
|
try {
|
|
57870
|
-
|
|
58213
|
+
import_node_fs41.default.unlinkSync(pidFile);
|
|
57871
58214
|
} catch {
|
|
57872
58215
|
}
|
|
57873
58216
|
}
|
|
57874
58217
|
async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
|
|
57875
58218
|
if (process.platform === "win32") return [];
|
|
57876
58219
|
return new Promise((resolve7) => {
|
|
57877
|
-
const ps = (0,
|
|
58220
|
+
const ps = (0, import_node_child_process11.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
|
|
57878
58221
|
let buf = "";
|
|
57879
58222
|
ps.stdout.on("data", (c) => {
|
|
57880
58223
|
buf += c.toString();
|
|
@@ -57904,7 +58247,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
57904
58247
|
var TunnelManager = class {
|
|
57905
58248
|
constructor(deps) {
|
|
57906
58249
|
this.deps = deps;
|
|
57907
|
-
this.store = deps.store ?? new TunnelStore(
|
|
58250
|
+
this.store = deps.store ?? new TunnelStore(import_node_path46.default.join(deps.dataDir, "tunnel.json"));
|
|
57908
58251
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
57909
58252
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
57910
58253
|
}
|
|
@@ -58031,7 +58374,7 @@ var TunnelManager = class {
|
|
|
58031
58374
|
dataDir: this.deps.dataDir,
|
|
58032
58375
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
58033
58376
|
});
|
|
58034
|
-
const tomlPath =
|
|
58377
|
+
const tomlPath = import_node_path46.default.join(this.deps.dataDir, "frpc.toml");
|
|
58035
58378
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto11.default.randomBytes(3).toString("hex")}`;
|
|
58036
58379
|
const toml = buildFrpcToml({
|
|
58037
58380
|
serverAddr: t.frpsHost,
|
|
@@ -58042,14 +58385,14 @@ var TunnelManager = class {
|
|
|
58042
58385
|
localPort,
|
|
58043
58386
|
logLevel: "info"
|
|
58044
58387
|
});
|
|
58045
|
-
await
|
|
58046
|
-
const proc = (this.deps.spawnImpl ??
|
|
58388
|
+
await import_node_fs42.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
58389
|
+
const proc = (this.deps.spawnImpl ?? import_node_child_process12.spawn)(frpcBin, ["-c", tomlPath], {
|
|
58047
58390
|
stdio: ["ignore", "pipe", "pipe"]
|
|
58048
58391
|
});
|
|
58049
|
-
const logDir =
|
|
58050
|
-
|
|
58051
|
-
const logFilePath =
|
|
58052
|
-
const logStream =
|
|
58392
|
+
const logDir = import_node_path46.default.join(this.deps.dataDir, "log");
|
|
58393
|
+
import_node_fs42.default.mkdirSync(logDir, { recursive: true });
|
|
58394
|
+
const logFilePath = import_node_path46.default.join(logDir, "frpc.log");
|
|
58395
|
+
const logStream = import_node_fs42.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
58053
58396
|
logStream.on("error", () => {
|
|
58054
58397
|
});
|
|
58055
58398
|
const tee = (chunk) => {
|
|
@@ -58131,28 +58474,28 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
58131
58474
|
}
|
|
58132
58475
|
|
|
58133
58476
|
// src/tunnel/device-key.ts
|
|
58134
|
-
var
|
|
58135
|
-
var
|
|
58477
|
+
var import_node_os16 = __toESM(require("os"), 1);
|
|
58478
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
58136
58479
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
58137
58480
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
58138
58481
|
function deriveStableDeviceKey(opts = {}) {
|
|
58139
|
-
const hostname = opts.hostname ??
|
|
58140
|
-
const uid = opts.uid ?? (typeof
|
|
58141
|
-
const home = opts.home ??
|
|
58142
|
-
const defaultDataDir =
|
|
58143
|
-
const normalizedDataDir = opts.dataDir ?
|
|
58482
|
+
const hostname = opts.hostname ?? import_node_os16.default.hostname();
|
|
58483
|
+
const uid = opts.uid ?? (typeof import_node_os16.default.userInfo === "function" ? import_node_os16.default.userInfo().uid : 0);
|
|
58484
|
+
const home = opts.home ?? import_node_os16.default.homedir();
|
|
58485
|
+
const defaultDataDir = import_node_path47.default.resolve(import_node_path47.default.join(home, ".clawd"));
|
|
58486
|
+
const normalizedDataDir = opts.dataDir ? import_node_path47.default.resolve(opts.dataDir) : null;
|
|
58144
58487
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
58145
58488
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
58146
58489
|
return import_node_crypto12.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
58147
58490
|
}
|
|
58148
58491
|
|
|
58149
58492
|
// src/auth-store.ts
|
|
58150
|
-
var
|
|
58151
|
-
var
|
|
58493
|
+
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
58494
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
58152
58495
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
58153
58496
|
var AUTH_FILE_NAME = "auth.json";
|
|
58154
58497
|
function authFilePath(dataDir) {
|
|
58155
|
-
return
|
|
58498
|
+
return import_node_path48.default.join(dataDir, AUTH_FILE_NAME);
|
|
58156
58499
|
}
|
|
58157
58500
|
function loadOrCreateAuthFile(opts) {
|
|
58158
58501
|
const file = authFilePath(opts.dataDir);
|
|
@@ -58184,7 +58527,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
58184
58527
|
}
|
|
58185
58528
|
function readAuthFile(file) {
|
|
58186
58529
|
try {
|
|
58187
|
-
const raw =
|
|
58530
|
+
const raw = import_node_fs43.default.readFileSync(file, "utf8");
|
|
58188
58531
|
const parsed = JSON.parse(raw);
|
|
58189
58532
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
58190
58533
|
return null;
|
|
@@ -58204,26 +58547,26 @@ function readAuthFile(file) {
|
|
|
58204
58547
|
}
|
|
58205
58548
|
}
|
|
58206
58549
|
function writeAuthFile(file, content) {
|
|
58207
|
-
|
|
58208
|
-
|
|
58550
|
+
import_node_fs43.default.mkdirSync(import_node_path48.default.dirname(file), { recursive: true });
|
|
58551
|
+
import_node_fs43.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
58209
58552
|
try {
|
|
58210
|
-
|
|
58553
|
+
import_node_fs43.default.chmodSync(file, 384);
|
|
58211
58554
|
} catch {
|
|
58212
58555
|
}
|
|
58213
58556
|
}
|
|
58214
58557
|
|
|
58215
58558
|
// src/owner-profile.ts
|
|
58216
|
-
var
|
|
58217
|
-
var
|
|
58218
|
-
var
|
|
58559
|
+
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
58560
|
+
var import_node_os17 = __toESM(require("os"), 1);
|
|
58561
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
58219
58562
|
var PROFILE_FILENAME = "profile.json";
|
|
58220
58563
|
function profilePath(dataDir) {
|
|
58221
|
-
return
|
|
58564
|
+
return import_node_path49.default.join(dataDir, PROFILE_FILENAME);
|
|
58222
58565
|
}
|
|
58223
58566
|
function loadOwnerProfile(dataDir) {
|
|
58224
58567
|
let raw;
|
|
58225
58568
|
try {
|
|
58226
|
-
raw =
|
|
58569
|
+
raw = import_node_fs44.default.readFileSync(profilePath(dataDir), "utf8");
|
|
58227
58570
|
} catch {
|
|
58228
58571
|
return {};
|
|
58229
58572
|
}
|
|
@@ -58239,11 +58582,11 @@ function loadOwnerProfile(dataDir) {
|
|
|
58239
58582
|
}
|
|
58240
58583
|
function patchOwnerProfile(dataDir, patch) {
|
|
58241
58584
|
const merged = { ...loadOwnerProfile(dataDir), ...patch };
|
|
58242
|
-
|
|
58585
|
+
import_node_fs44.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
|
|
58243
58586
|
return merged;
|
|
58244
58587
|
}
|
|
58245
58588
|
function loadOwnerDisplayName(dataDir) {
|
|
58246
|
-
const fallback =
|
|
58589
|
+
const fallback = import_node_os17.default.userInfo().username;
|
|
58247
58590
|
const displayName = loadOwnerProfile(dataDir).displayName;
|
|
58248
58591
|
if (typeof displayName !== "string" || displayName.length === 0) {
|
|
58249
58592
|
if (displayName !== void 0) {
|
|
@@ -58255,18 +58598,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
58255
58598
|
}
|
|
58256
58599
|
|
|
58257
58600
|
// src/feishu-auth/owner-identity-store.ts
|
|
58258
|
-
var
|
|
58259
|
-
var
|
|
58601
|
+
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
58602
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
58260
58603
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
58261
58604
|
var OwnerIdentityStore = class {
|
|
58262
58605
|
file;
|
|
58263
58606
|
constructor(dataDir) {
|
|
58264
|
-
this.file =
|
|
58607
|
+
this.file = import_node_path50.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
58265
58608
|
}
|
|
58266
58609
|
read() {
|
|
58267
58610
|
let raw;
|
|
58268
58611
|
try {
|
|
58269
|
-
raw =
|
|
58612
|
+
raw = import_node_fs45.default.readFileSync(this.file, "utf8");
|
|
58270
58613
|
} catch {
|
|
58271
58614
|
return null;
|
|
58272
58615
|
}
|
|
@@ -58294,16 +58637,16 @@ var OwnerIdentityStore = class {
|
|
|
58294
58637
|
};
|
|
58295
58638
|
}
|
|
58296
58639
|
write(record3) {
|
|
58297
|
-
|
|
58298
|
-
|
|
58640
|
+
import_node_fs45.default.mkdirSync(import_node_path50.default.dirname(this.file), { recursive: true });
|
|
58641
|
+
import_node_fs45.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
|
|
58299
58642
|
try {
|
|
58300
|
-
|
|
58643
|
+
import_node_fs45.default.chmodSync(this.file, 384);
|
|
58301
58644
|
} catch {
|
|
58302
58645
|
}
|
|
58303
58646
|
}
|
|
58304
58647
|
clear() {
|
|
58305
58648
|
try {
|
|
58306
|
-
|
|
58649
|
+
import_node_fs45.default.unlinkSync(this.file);
|
|
58307
58650
|
} catch (err) {
|
|
58308
58651
|
const code = err?.code;
|
|
58309
58652
|
if (code !== "ENOENT") throw err;
|
|
@@ -58636,8 +58979,8 @@ function verifyConnectToken(args) {
|
|
|
58636
58979
|
}
|
|
58637
58980
|
|
|
58638
58981
|
// src/feishu-auth/server-key.ts
|
|
58639
|
-
var
|
|
58640
|
-
var
|
|
58982
|
+
var fs57 = __toESM(require("fs"), 1);
|
|
58983
|
+
var path60 = __toESM(require("path"), 1);
|
|
58641
58984
|
var FILE_NAME2 = "server-signing-key.json";
|
|
58642
58985
|
var ServerKeyStore = class {
|
|
58643
58986
|
constructor(dataDir) {
|
|
@@ -58645,12 +58988,12 @@ var ServerKeyStore = class {
|
|
|
58645
58988
|
}
|
|
58646
58989
|
dataDir;
|
|
58647
58990
|
filePath() {
|
|
58648
|
-
return
|
|
58991
|
+
return path60.join(this.dataDir, FILE_NAME2);
|
|
58649
58992
|
}
|
|
58650
58993
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
58651
58994
|
read() {
|
|
58652
58995
|
try {
|
|
58653
|
-
const raw =
|
|
58996
|
+
const raw = fs57.readFileSync(this.filePath(), "utf8");
|
|
58654
58997
|
const parsed = JSON.parse(raw);
|
|
58655
58998
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
58656
58999
|
return parsed.publicKeyPem;
|
|
@@ -58665,12 +59008,12 @@ var ServerKeyStore = class {
|
|
|
58665
59008
|
publicKeyPem,
|
|
58666
59009
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
58667
59010
|
};
|
|
58668
|
-
|
|
58669
|
-
|
|
59011
|
+
fs57.mkdirSync(this.dataDir, { recursive: true });
|
|
59012
|
+
fs57.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
58670
59013
|
}
|
|
58671
59014
|
clear() {
|
|
58672
59015
|
try {
|
|
58673
|
-
|
|
59016
|
+
fs57.unlinkSync(this.filePath());
|
|
58674
59017
|
} catch {
|
|
58675
59018
|
}
|
|
58676
59019
|
}
|
|
@@ -58683,12 +59026,12 @@ init_protocol();
|
|
|
58683
59026
|
init_protocol();
|
|
58684
59027
|
|
|
58685
59028
|
// src/session/fork.ts
|
|
58686
|
-
var
|
|
58687
|
-
var
|
|
58688
|
-
var
|
|
59029
|
+
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
59030
|
+
var import_node_os18 = __toESM(require("os"), 1);
|
|
59031
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
58689
59032
|
init_claude_history();
|
|
58690
59033
|
function readJsonlEntries(file) {
|
|
58691
|
-
const raw =
|
|
59034
|
+
const raw = import_node_fs46.default.readFileSync(file, "utf8");
|
|
58692
59035
|
const out = [];
|
|
58693
59036
|
for (const line of raw.split("\n")) {
|
|
58694
59037
|
const t = line.trim();
|
|
@@ -58701,19 +59044,19 @@ function readJsonlEntries(file) {
|
|
|
58701
59044
|
return out;
|
|
58702
59045
|
}
|
|
58703
59046
|
function forkSession(input) {
|
|
58704
|
-
const baseDir = input.baseDir ??
|
|
58705
|
-
let projectDir =
|
|
58706
|
-
let sourceFile =
|
|
58707
|
-
if (!
|
|
59047
|
+
const baseDir = input.baseDir ?? import_node_path51.default.join(import_node_os18.default.homedir(), ".claude");
|
|
59048
|
+
let projectDir = import_node_path51.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
59049
|
+
let sourceFile = import_node_path51.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
59050
|
+
if (!import_node_fs46.default.existsSync(sourceFile)) {
|
|
58708
59051
|
const found = findTranscriptByToolSessionId(
|
|
58709
|
-
|
|
59052
|
+
import_node_path51.default.join(baseDir, "projects"),
|
|
58710
59053
|
input.toolSessionId
|
|
58711
59054
|
);
|
|
58712
59055
|
if (!found) {
|
|
58713
59056
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
58714
59057
|
}
|
|
58715
59058
|
sourceFile = found;
|
|
58716
|
-
projectDir =
|
|
59059
|
+
projectDir = import_node_path51.default.dirname(found);
|
|
58717
59060
|
}
|
|
58718
59061
|
const entries = readJsonlEntries(sourceFile);
|
|
58719
59062
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -58742,313 +59085,13 @@ function forkSession(input) {
|
|
|
58742
59085
|
}
|
|
58743
59086
|
forkedLines.push(JSON.stringify(forked));
|
|
58744
59087
|
}
|
|
58745
|
-
const outDir = input.targetCwd ?
|
|
58746
|
-
const forkedFilePath =
|
|
58747
|
-
|
|
58748
|
-
|
|
59088
|
+
const outDir = input.targetCwd ? import_node_path51.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
59089
|
+
const forkedFilePath = import_node_path51.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
59090
|
+
import_node_fs46.default.mkdirSync(outDir, { recursive: true });
|
|
59091
|
+
import_node_fs46.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
58749
59092
|
return { forkedToolSessionId, forkedFilePath };
|
|
58750
59093
|
}
|
|
58751
59094
|
|
|
58752
|
-
// src/session/external-scan.ts
|
|
58753
|
-
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
58754
|
-
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
58755
|
-
var import_node_os18 = __toESM(require("os"), 1);
|
|
58756
|
-
var import_node_path51 = __toESM(require("path"), 1);
|
|
58757
|
-
var import_node_module = require("module");
|
|
58758
|
-
var import_node_child_process12 = require("child_process");
|
|
58759
|
-
var import_meta4 = {};
|
|
58760
|
-
function defaultRoots() {
|
|
58761
|
-
const home = import_node_os18.default.homedir();
|
|
58762
|
-
return {
|
|
58763
|
-
claudeProjectsDir: import_node_path51.default.join(home, ".claude", "projects"),
|
|
58764
|
-
codexDir: import_node_path51.default.join(home, ".codex"),
|
|
58765
|
-
clawdDir: import_node_path51.default.join(home, ".clawd")
|
|
58766
|
-
};
|
|
58767
|
-
}
|
|
58768
|
-
function width(s) {
|
|
58769
|
-
let w2 = 0;
|
|
58770
|
-
for (const ch of s) w2 += /[ᄀ-ᅟ⺀-가-힣豈-︰-﹏-⦆¢-₩]/.test(ch) ? 2 : 1;
|
|
58771
|
-
return w2;
|
|
58772
|
-
}
|
|
58773
|
-
function clipW(text, n) {
|
|
58774
|
-
const s = String(text ?? "").split(/\s+/).filter(Boolean).join(" ");
|
|
58775
|
-
if (width(s) <= n) return s;
|
|
58776
|
-
let out = "";
|
|
58777
|
-
let w2 = 0;
|
|
58778
|
-
for (const ch of s) {
|
|
58779
|
-
const cw = width(ch);
|
|
58780
|
-
if (w2 + cw > n - 1) break;
|
|
58781
|
-
out += ch;
|
|
58782
|
-
w2 += cw;
|
|
58783
|
-
}
|
|
58784
|
-
return out + "\u2026";
|
|
58785
|
-
}
|
|
58786
|
-
function toMs(v2) {
|
|
58787
|
-
const n = Number(v2 || 0);
|
|
58788
|
-
return n > 1e11 ? Math.round(n) : Math.round(n * 1e3);
|
|
58789
|
-
}
|
|
58790
|
-
function listFiles(dir, depth = 0, maxDepth = 8, out = []) {
|
|
58791
|
-
let entries;
|
|
58792
|
-
try {
|
|
58793
|
-
entries = import_node_fs46.default.readdirSync(dir, { withFileTypes: true });
|
|
58794
|
-
} catch {
|
|
58795
|
-
return out;
|
|
58796
|
-
}
|
|
58797
|
-
for (const e of entries) {
|
|
58798
|
-
const full = import_node_path51.default.join(dir, e.name);
|
|
58799
|
-
if (e.isDirectory()) {
|
|
58800
|
-
if (depth < maxDepth) listFiles(full, depth + 1, maxDepth, out);
|
|
58801
|
-
} else if (e.isFile()) {
|
|
58802
|
-
out.push(full);
|
|
58803
|
-
}
|
|
58804
|
-
}
|
|
58805
|
-
return out;
|
|
58806
|
-
}
|
|
58807
|
-
async function* jsonLines(file) {
|
|
58808
|
-
let raw;
|
|
58809
|
-
try {
|
|
58810
|
-
raw = await import_promises7.default.readFile(file, "utf8");
|
|
58811
|
-
} catch {
|
|
58812
|
-
return;
|
|
58813
|
-
}
|
|
58814
|
-
for (const line of raw.split("\n")) {
|
|
58815
|
-
const t = line.trim();
|
|
58816
|
-
if (!t) continue;
|
|
58817
|
-
try {
|
|
58818
|
-
yield JSON.parse(t);
|
|
58819
|
-
} catch {
|
|
58820
|
-
}
|
|
58821
|
-
}
|
|
58822
|
-
}
|
|
58823
|
-
function userText(msg) {
|
|
58824
|
-
const content = msg && typeof msg === "object" ? msg.content : null;
|
|
58825
|
-
if (typeof content === "string") return content;
|
|
58826
|
-
if (Array.isArray(content)) {
|
|
58827
|
-
return content.map((b2) => b2 && b2.type === "text" ? String(b2.text ?? "") : "").join("");
|
|
58828
|
-
}
|
|
58829
|
-
return "";
|
|
58830
|
-
}
|
|
58831
|
-
function isDir2(p2) {
|
|
58832
|
-
try {
|
|
58833
|
-
return import_node_fs46.default.statSync(p2).isDirectory();
|
|
58834
|
-
} catch {
|
|
58835
|
-
return false;
|
|
58836
|
-
}
|
|
58837
|
-
}
|
|
58838
|
-
async function scanClaude(roots) {
|
|
58839
|
-
const out = [];
|
|
58840
|
-
let dirs;
|
|
58841
|
-
try {
|
|
58842
|
-
dirs = import_node_fs46.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
|
|
58843
|
-
} catch {
|
|
58844
|
-
return out;
|
|
58845
|
-
}
|
|
58846
|
-
for (const d of dirs) {
|
|
58847
|
-
if (!d.isDirectory()) continue;
|
|
58848
|
-
let files;
|
|
58849
|
-
try {
|
|
58850
|
-
files = import_node_fs46.default.readdirSync(import_node_path51.default.join(roots.claudeProjectsDir, d.name));
|
|
58851
|
-
} catch {
|
|
58852
|
-
continue;
|
|
58853
|
-
}
|
|
58854
|
-
for (const name of files) {
|
|
58855
|
-
if (!name.endsWith(".jsonl")) continue;
|
|
58856
|
-
const file = import_node_path51.default.join(roots.claudeProjectsDir, d.name, name);
|
|
58857
|
-
let st;
|
|
58858
|
-
try {
|
|
58859
|
-
st = import_node_fs46.default.statSync(file);
|
|
58860
|
-
} catch {
|
|
58861
|
-
continue;
|
|
58862
|
-
}
|
|
58863
|
-
let cwd = "";
|
|
58864
|
-
let title = "";
|
|
58865
|
-
let firstUser = "";
|
|
58866
|
-
let turns = 0;
|
|
58867
|
-
let firstTs = 0;
|
|
58868
|
-
let lastTs = 0;
|
|
58869
|
-
let hasMainLine = false;
|
|
58870
|
-
for await (const rec4 of jsonLines(file)) {
|
|
58871
|
-
if (!cwd && typeof rec4.cwd === "string") cwd = rec4.cwd;
|
|
58872
|
-
if (typeof rec4.timestamp === "string") {
|
|
58873
|
-
const t = Date.parse(rec4.timestamp);
|
|
58874
|
-
if (Number.isFinite(t)) {
|
|
58875
|
-
firstTs ||= t;
|
|
58876
|
-
lastTs = t;
|
|
58877
|
-
}
|
|
58878
|
-
}
|
|
58879
|
-
if (rec4.type === "ai-title" && rec4.aiTitle) {
|
|
58880
|
-
title = String(rec4.aiTitle);
|
|
58881
|
-
continue;
|
|
58882
|
-
}
|
|
58883
|
-
if (rec4.type !== "user" && rec4.type !== "assistant") continue;
|
|
58884
|
-
if (!rec4.isSidechain) hasMainLine = true;
|
|
58885
|
-
if (rec4.type !== "user" || rec4.isSidechain || rec4.isMeta) continue;
|
|
58886
|
-
const text = userText(rec4.message || {});
|
|
58887
|
-
if (!text.trim() || text.trimStart().startsWith("<")) continue;
|
|
58888
|
-
turns += 1;
|
|
58889
|
-
firstUser ||= text;
|
|
58890
|
-
}
|
|
58891
|
-
const cand = {
|
|
58892
|
-
tool: "claude",
|
|
58893
|
-
toolSessionId: name.slice(0, -".jsonl".length),
|
|
58894
|
-
cwd,
|
|
58895
|
-
label: clipW(title || firstUser, 56),
|
|
58896
|
-
turns,
|
|
58897
|
-
createdMs: firstTs || st.mtimeMs,
|
|
58898
|
-
updatedMs: lastTs || st.mtimeMs,
|
|
58899
|
-
skip: ""
|
|
58900
|
-
};
|
|
58901
|
-
if (!hasMainLine) cand.skip = "subagent \u652F\u7EBF";
|
|
58902
|
-
else if (!cwd) cand.skip = "\u65E0 cwd";
|
|
58903
|
-
else if (cwd.includes("clawd-title-gen")) cand.skip = "\u6807\u9898\u751F\u6210\u4E34\u65F6\u4F1A\u8BDD";
|
|
58904
|
-
out.push(cand);
|
|
58905
|
-
}
|
|
58906
|
-
}
|
|
58907
|
-
return out;
|
|
58908
|
-
}
|
|
58909
|
-
async function countCodexTurns(rolloutPath) {
|
|
58910
|
-
if (!rolloutPath || !import_node_fs46.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
|
|
58911
|
-
let turns = 0;
|
|
58912
|
-
let first = "";
|
|
58913
|
-
for await (const rec4 of jsonLines(rolloutPath)) {
|
|
58914
|
-
const p2 = rec4.payload || {};
|
|
58915
|
-
if (p2.type !== "message" || p2.role !== "user") continue;
|
|
58916
|
-
const text = (p2.content || []).map((b2) => String(b2 && b2.text || "")).join("");
|
|
58917
|
-
if (!text.trim() || text.trimStart().startsWith("<")) continue;
|
|
58918
|
-
turns += 1;
|
|
58919
|
-
first ||= text;
|
|
58920
|
-
}
|
|
58921
|
-
return { turns, first };
|
|
58922
|
-
}
|
|
58923
|
-
function readCodexThreads(db) {
|
|
58924
|
-
const COLS = ["id", "cwd", "created_at", "updated_at", "name", "title", "preview", "first_user_message", "archived", "rollout_path"];
|
|
58925
|
-
try {
|
|
58926
|
-
const { DatabaseSync } = (0, import_node_module.createRequire)(import_meta4.url)("node:sqlite");
|
|
58927
|
-
const conn = new DatabaseSync(db, { readOnly: true });
|
|
58928
|
-
try {
|
|
58929
|
-
const have = new Set(
|
|
58930
|
-
conn.prepare("PRAGMA table_info(threads)").all().map((r) => r.name)
|
|
58931
|
-
);
|
|
58932
|
-
if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
|
|
58933
|
-
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
58934
|
-
return conn.prepare(`SELECT ${sel} FROM threads`).all();
|
|
58935
|
-
} finally {
|
|
58936
|
-
conn.close();
|
|
58937
|
-
}
|
|
58938
|
-
} catch {
|
|
58939
|
-
}
|
|
58940
|
-
try {
|
|
58941
|
-
const info = (0, import_node_child_process12.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
|
|
58942
|
-
if (info.status !== 0) return null;
|
|
58943
|
-
const have = new Set(
|
|
58944
|
-
info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
|
|
58945
|
-
);
|
|
58946
|
-
if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
|
|
58947
|
-
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
58948
|
-
const res = (0, import_node_child_process12.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
|
|
58949
|
-
encoding: "utf8",
|
|
58950
|
-
maxBuffer: 64 * 1024 * 1024
|
|
58951
|
-
});
|
|
58952
|
-
if (res.status !== 0 || !res.stdout.trim()) return null;
|
|
58953
|
-
return JSON.parse(res.stdout);
|
|
58954
|
-
} catch {
|
|
58955
|
-
return null;
|
|
58956
|
-
}
|
|
58957
|
-
}
|
|
58958
|
-
async function codexFromRows(rows) {
|
|
58959
|
-
const out = [];
|
|
58960
|
-
for (const r of rows) {
|
|
58961
|
-
const updatedMs = toMs(r.updated_at);
|
|
58962
|
-
const { turns, first } = await countCodexTurns(String(r.rollout_path || ""));
|
|
58963
|
-
const label = clipW(r.name || r.title || r.preview || r.first_user_message || first, 56);
|
|
58964
|
-
const cand = {
|
|
58965
|
-
tool: "codex",
|
|
58966
|
-
toolSessionId: String(r.id),
|
|
58967
|
-
cwd: String(r.cwd || ""),
|
|
58968
|
-
label,
|
|
58969
|
-
turns,
|
|
58970
|
-
createdMs: toMs(r.created_at) || updatedMs,
|
|
58971
|
-
updatedMs,
|
|
58972
|
-
skip: ""
|
|
58973
|
-
};
|
|
58974
|
-
if (r.archived) cand.skip = "\u5DF2\u5F52\u6863";
|
|
58975
|
-
else if (!label) cand.skip = "\u7A7A\u4F1A\u8BDD";
|
|
58976
|
-
out.push(cand);
|
|
58977
|
-
}
|
|
58978
|
-
return out;
|
|
58979
|
-
}
|
|
58980
|
-
async function scanCodexRollouts(roots) {
|
|
58981
|
-
const out = [];
|
|
58982
|
-
for (const file of listFiles(import_node_path51.default.join(roots.codexDir, "sessions"))) {
|
|
58983
|
-
if (!file.endsWith(".jsonl")) continue;
|
|
58984
|
-
let st;
|
|
58985
|
-
try {
|
|
58986
|
-
st = import_node_fs46.default.statSync(file);
|
|
58987
|
-
} catch {
|
|
58988
|
-
continue;
|
|
58989
|
-
}
|
|
58990
|
-
let meta = null;
|
|
58991
|
-
for await (const rec4 of jsonLines(file)) {
|
|
58992
|
-
if (rec4.type === "session_meta") {
|
|
58993
|
-
meta = rec4.payload || {};
|
|
58994
|
-
break;
|
|
58995
|
-
}
|
|
58996
|
-
}
|
|
58997
|
-
const tid = meta && (meta.session_id || meta.id);
|
|
58998
|
-
if (!tid) continue;
|
|
58999
|
-
const { turns, first } = await countCodexTurns(file);
|
|
59000
|
-
const cand = {
|
|
59001
|
-
tool: "codex",
|
|
59002
|
-
toolSessionId: String(tid),
|
|
59003
|
-
cwd: String(meta?.cwd || ""),
|
|
59004
|
-
label: clipW(first, 56),
|
|
59005
|
-
turns,
|
|
59006
|
-
createdMs: st.mtimeMs,
|
|
59007
|
-
updatedMs: st.mtimeMs,
|
|
59008
|
-
skip: ""
|
|
59009
|
-
};
|
|
59010
|
-
if (!cand.cwd) cand.skip = "\u65E0 cwd";
|
|
59011
|
-
out.push(cand);
|
|
59012
|
-
}
|
|
59013
|
-
return out;
|
|
59014
|
-
}
|
|
59015
|
-
async function scanCodex(roots) {
|
|
59016
|
-
let dbs = [];
|
|
59017
|
-
try {
|
|
59018
|
-
dbs = import_node_fs46.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path51.default.join(roots.codexDir, n));
|
|
59019
|
-
} catch {
|
|
59020
|
-
}
|
|
59021
|
-
if (dbs.length) {
|
|
59022
|
-
const rows = readCodexThreads(dbs[dbs.length - 1]);
|
|
59023
|
-
if (rows) return codexFromRows(rows);
|
|
59024
|
-
}
|
|
59025
|
-
return scanCodexRollouts(roots);
|
|
59026
|
-
}
|
|
59027
|
-
async function scanExternalSessions(rootsIn) {
|
|
59028
|
-
const roots = { ...defaultRoots(), ...rootsIn };
|
|
59029
|
-
const personaRoot = import_node_path51.default.join(roots.clawdDir, "personas");
|
|
59030
|
-
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
59031
|
-
const out = [];
|
|
59032
|
-
for (const c of all) {
|
|
59033
|
-
if (c.skip) continue;
|
|
59034
|
-
if (c.turns < 1) continue;
|
|
59035
|
-
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
59036
|
-
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path51.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path51.default.sep)) {
|
|
59037
|
-
continue;
|
|
59038
|
-
}
|
|
59039
|
-
out.push({
|
|
59040
|
-
tool: c.tool,
|
|
59041
|
-
cwd: c.cwd,
|
|
59042
|
-
toolSessionId: c.toolSessionId,
|
|
59043
|
-
...c.label ? { label: c.label } : {},
|
|
59044
|
-
createdAt: new Date(c.createdMs).toISOString(),
|
|
59045
|
-
updatedAt: new Date(c.updatedMs).toISOString(),
|
|
59046
|
-
turns: c.turns
|
|
59047
|
-
});
|
|
59048
|
-
}
|
|
59049
|
-
return out;
|
|
59050
|
-
}
|
|
59051
|
-
|
|
59052
59095
|
// src/session/import-ledger.ts
|
|
59053
59096
|
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
59054
59097
|
var import_node_path52 = __toESM(require("path"), 1);
|
|
@@ -59607,8 +59650,8 @@ function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userW
|
|
|
59607
59650
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
59608
59651
|
}
|
|
59609
59652
|
const root = path63.resolve(personaRoot);
|
|
59610
|
-
const
|
|
59611
|
-
if (!target.startsWith(root +
|
|
59653
|
+
const sep4 = root.endsWith(path63.sep) ? "" : path63.sep;
|
|
59654
|
+
if (!target.startsWith(root + sep4)) return false;
|
|
59612
59655
|
const rel = path63.relative(root, target);
|
|
59613
59656
|
if (!rel || rel.startsWith("..")) return false;
|
|
59614
59657
|
const personaId2 = rel.split(path63.sep)[0];
|
|
@@ -59620,8 +59663,8 @@ function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userW
|
|
|
59620
59663
|
function personaIdFromPath(absPath, personaRoot) {
|
|
59621
59664
|
const root = path63.resolve(personaRoot);
|
|
59622
59665
|
const target = path63.resolve(absPath);
|
|
59623
|
-
const
|
|
59624
|
-
if (!target.startsWith(root +
|
|
59666
|
+
const sep4 = root.endsWith(path63.sep) ? "" : path63.sep;
|
|
59667
|
+
if (!target.startsWith(root + sep4)) return null;
|
|
59625
59668
|
const rel = path63.relative(root, target);
|
|
59626
59669
|
if (!rel || rel.startsWith("..")) return null;
|
|
59627
59670
|
const id = rel.split(path63.sep)[0];
|
|
@@ -59630,8 +59673,8 @@ function personaIdFromPath(absPath, personaRoot) {
|
|
|
59630
59673
|
function isPathWithin(dir, absPath) {
|
|
59631
59674
|
const d = path63.resolve(dir);
|
|
59632
59675
|
const t = path63.resolve(absPath);
|
|
59633
|
-
const
|
|
59634
|
-
return t === d || t.startsWith(d +
|
|
59676
|
+
const sep4 = d.endsWith(path63.sep) ? "" : path63.sep;
|
|
59677
|
+
return t === d || t.startsWith(d + sep4);
|
|
59635
59678
|
}
|
|
59636
59679
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
59637
59680
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
@@ -60894,7 +60937,7 @@ function computeMethodAccess(args) {
|
|
|
60894
60937
|
}
|
|
60895
60938
|
|
|
60896
60939
|
// src/version.ts
|
|
60897
|
-
var version = "0.2.
|
|
60940
|
+
var version = "0.2.368".length > 0 ? "0.2.368" : "dev";
|
|
60898
60941
|
|
|
60899
60942
|
// src/cli-probe/probe.ts
|
|
60900
60943
|
var fs62 = __toESM(require("fs"), 1);
|
|
@@ -64826,6 +64869,13 @@ async function startDaemon(config) {
|
|
|
64826
64869
|
projectsStore.seedFromSessions(
|
|
64827
64870
|
manager.list().response.sessions
|
|
64828
64871
|
);
|
|
64872
|
+
void scanExternalSessions().then((candidates) => {
|
|
64873
|
+
projectsStore.seedFromExternal(candidates);
|
|
64874
|
+
logger.info("projects.seed-external", {
|
|
64875
|
+
candidates: candidates.length,
|
|
64876
|
+
total: projectsStore.list().length
|
|
64877
|
+
});
|
|
64878
|
+
}).catch((err) => logger.warn("projects.seed-external failed", { err: String(err) }));
|
|
64829
64879
|
const observer = new SessionObserver({
|
|
64830
64880
|
// TUI 模式 pty 跑 CC 不发 SDK system.task_started 帧 → UI pending 期 progress.agentId
|
|
64831
64881
|
// 永远 undefined,子 agent 调用过程没有抽屉入口。开 meta observer 后从 subagents 目录
|