engine7 7.1.117 → 7.1.119
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.mjs +1006 -872
- package/dist/engine-startup.mjs +92 -40
- package/dist/main.mjs +92 -40
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -408,14 +408,14 @@ var init_live = __esm({
|
|
|
408
408
|
}
|
|
409
409
|
/** 把改动写回 config 文件对应段(找不到文件路径则只内存生效) */
|
|
410
410
|
async persistToFile(dotPath, val) {
|
|
411
|
-
const
|
|
411
|
+
const fs44 = await import("node:fs");
|
|
412
412
|
const cfgPath = this.current?._configFilePath;
|
|
413
|
-
if (!cfgPath || !
|
|
413
|
+
if (!cfgPath || !fs44.existsSync(cfgPath)) {
|
|
414
414
|
console.warn(`[liveConfig] set: no config file path, in-memory only (${dotPath})`);
|
|
415
415
|
return;
|
|
416
416
|
}
|
|
417
417
|
try {
|
|
418
|
-
const raw = JSON.parse(
|
|
418
|
+
const raw = JSON.parse(fs44.readFileSync(cfgPath, "utf-8"));
|
|
419
419
|
const keys = dotPath.split(".");
|
|
420
420
|
let o = raw;
|
|
421
421
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -423,7 +423,7 @@ var init_live = __esm({
|
|
|
423
423
|
o = o[keys[i]];
|
|
424
424
|
}
|
|
425
425
|
o[keys[keys.length - 1]] = val;
|
|
426
|
-
|
|
426
|
+
fs44.writeFileSync(cfgPath, JSON.stringify(raw, null, 2) + "\n", "utf-8");
|
|
427
427
|
console.log(`[liveConfig] persisted ${dotPath} = ${JSON.stringify(val)} to ${cfgPath}`);
|
|
428
428
|
markSelfWrite();
|
|
429
429
|
} catch (e) {
|
|
@@ -714,8 +714,8 @@ function listSchemaFields() {
|
|
|
714
714
|
if (process.env.ENGINE7_INTERNAL === "1") return FIELDS.slice();
|
|
715
715
|
return FIELDS.filter((f) => !f.internal);
|
|
716
716
|
}
|
|
717
|
-
function getField(
|
|
718
|
-
return FIELDS.find((f) => f.path ===
|
|
717
|
+
function getField(path44) {
|
|
718
|
+
return FIELDS.find((f) => f.path === path44);
|
|
719
719
|
}
|
|
720
720
|
function pick(obj, dotPath) {
|
|
721
721
|
let cur = obj;
|
|
@@ -2073,6 +2073,19 @@ function resolveConfigIdentity(configPath) {
|
|
|
2073
2073
|
const stateDir = basename2(cfgDir) === "configs" ? dirname2(cfgDir) : cfgDir;
|
|
2074
2074
|
return { stateDir, configName: cfgName };
|
|
2075
2075
|
}
|
|
2076
|
+
function engineStateDirOfConfig(configPath, env = process.env) {
|
|
2077
|
+
let raw;
|
|
2078
|
+
try {
|
|
2079
|
+
raw = JSON.parse(readFileSync3(configPath, "utf-8"));
|
|
2080
|
+
} catch {
|
|
2081
|
+
return null;
|
|
2082
|
+
}
|
|
2083
|
+
if (typeof raw?.stateDir === "string" && raw.stateDir.trim()) return raw.stateDir.trim();
|
|
2084
|
+
const fromEnv = env.ENGINE_STATE_DIR;
|
|
2085
|
+
if (fromEnv && fromEnv.trim()) return fromEnv.trim();
|
|
2086
|
+
if (basename2(dirname2(configPath)) !== "configs") return null;
|
|
2087
|
+
return resolveConfigIdentity(configPath).stateDir;
|
|
2088
|
+
}
|
|
2076
2089
|
function writeSecretsValue(configPath, envKey, value) {
|
|
2077
2090
|
const { stateDir, configName } = resolveConfigIdentity(configPath);
|
|
2078
2091
|
const dir = join3(secretsHome(), ".engine7-secrets");
|
|
@@ -2191,8 +2204,8 @@ __export(loader_exports, {
|
|
|
2191
2204
|
resolveTimezone: () => resolveTimezone,
|
|
2192
2205
|
takeLoadWarnings: () => takeLoadWarnings
|
|
2193
2206
|
});
|
|
2194
|
-
import * as
|
|
2195
|
-
import * as
|
|
2207
|
+
import * as fs4 from "node:fs";
|
|
2208
|
+
import * as path4 from "node:path";
|
|
2196
2209
|
function parseModelRef(ref) {
|
|
2197
2210
|
const idx = ref.indexOf("/");
|
|
2198
2211
|
if (idx <= 0 || idx === ref.length - 1) {
|
|
@@ -2232,13 +2245,13 @@ function isUnresolvedEnvRef(value) {
|
|
|
2232
2245
|
return typeof value === "string" && ENV_REF_RE.test(value);
|
|
2233
2246
|
}
|
|
2234
2247
|
function loadConfig(configPath) {
|
|
2235
|
-
const resolvedPath =
|
|
2248
|
+
const resolvedPath = path4.resolve(
|
|
2236
2249
|
configPath || process.env.ENGINE_CONFIG || "engine-config.json"
|
|
2237
2250
|
);
|
|
2238
|
-
if (!
|
|
2251
|
+
if (!fs4.existsSync(resolvedPath)) {
|
|
2239
2252
|
throw new Error(`Config file not found: ${resolvedPath}`);
|
|
2240
2253
|
}
|
|
2241
|
-
const raw = JSON.parse(
|
|
2254
|
+
const raw = JSON.parse(fs4.readFileSync(resolvedPath, "utf-8"));
|
|
2242
2255
|
const missingEnvKeys = /* @__PURE__ */ new Set();
|
|
2243
2256
|
const resolveEnv = (node) => {
|
|
2244
2257
|
if (typeof node === "string") {
|
|
@@ -2341,9 +2354,9 @@ function loadConfig(configPath) {
|
|
|
2341
2354
|
}
|
|
2342
2355
|
}
|
|
2343
2356
|
}
|
|
2344
|
-
const stateDir = raw.stateDir || process.env.ENGINE_STATE_DIR ||
|
|
2345
|
-
const workspace = process.env.ENGINE_WORKSPACE || agentDefaults.workspace ||
|
|
2346
|
-
const mediaDir = raw.mediaDir ||
|
|
2357
|
+
const stateDir = raw.stateDir || process.env.ENGINE_STATE_DIR || path4.resolve(".engine");
|
|
2358
|
+
const workspace = process.env.ENGINE_WORKSPACE || agentDefaults.workspace || path4.join(stateDir, "workspace");
|
|
2359
|
+
const mediaDir = raw.mediaDir || path4.join(stateDir, "media", "inbound");
|
|
2347
2360
|
if (!agentDefaults.features) agentDefaults.features = {};
|
|
2348
2361
|
for (const [k, v] of Object.entries(FEATURE_DEFAULTS)) {
|
|
2349
2362
|
if (agentDefaults.features[k] === void 0) {
|
|
@@ -2615,17 +2628,17 @@ var init_registry2 = __esm({
|
|
|
2615
2628
|
});
|
|
2616
2629
|
|
|
2617
2630
|
// src/calendar/db.ts
|
|
2618
|
-
import * as
|
|
2619
|
-
import * as
|
|
2631
|
+
import * as path5 from "node:path";
|
|
2632
|
+
import * as fs5 from "node:fs";
|
|
2620
2633
|
import { createRequire as createRequire2 } from "node:module";
|
|
2621
2634
|
function getSqlite() {
|
|
2622
2635
|
if (!_sqlite) _sqlite = createRequire2(import.meta.url)("node:sqlite");
|
|
2623
2636
|
return _sqlite;
|
|
2624
2637
|
}
|
|
2625
2638
|
function openDb(workspace) {
|
|
2626
|
-
const dir =
|
|
2627
|
-
|
|
2628
|
-
const dbPath =
|
|
2639
|
+
const dir = path5.join(workspace, ".calendar");
|
|
2640
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
2641
|
+
const dbPath = path5.join(dir, "calendar.db");
|
|
2629
2642
|
const db2 = new DatabaseSync(dbPath);
|
|
2630
2643
|
db2.exec("PRAGMA journal_mode=WAL");
|
|
2631
2644
|
db2.exec(`CREATE TABLE IF NOT EXISTS events (
|
|
@@ -2699,14 +2712,14 @@ var init_db = __esm({
|
|
|
2699
2712
|
});
|
|
2700
2713
|
|
|
2701
2714
|
// src/goals/store.ts
|
|
2702
|
-
import
|
|
2703
|
-
import
|
|
2715
|
+
import fs6 from "node:fs";
|
|
2716
|
+
import path6 from "node:path";
|
|
2704
2717
|
import crypto from "node:crypto";
|
|
2705
2718
|
function file(stateDir) {
|
|
2706
|
-
return
|
|
2719
|
+
return path6.join(stateDir, "goals.json");
|
|
2707
2720
|
}
|
|
2708
2721
|
function eventFile(stateDir) {
|
|
2709
|
-
return
|
|
2722
|
+
return path6.join(stateDir, "goal-events.jsonl");
|
|
2710
2723
|
}
|
|
2711
2724
|
function db(stateDir) {
|
|
2712
2725
|
const d = openDb(stateDir);
|
|
@@ -2723,17 +2736,17 @@ function db(stateDir) {
|
|
|
2723
2736
|
return d;
|
|
2724
2737
|
}
|
|
2725
2738
|
function event(stateDir, goalId, type2, payload = {}) {
|
|
2726
|
-
|
|
2739
|
+
fs6.mkdirSync(stateDir, { recursive: true });
|
|
2727
2740
|
const id = `ge-${Date.now()}-${crypto.randomBytes(3).toString("hex")}`;
|
|
2728
2741
|
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
2729
|
-
|
|
2742
|
+
fs6.appendFileSync(eventFile(stateDir), JSON.stringify({ eventId: id, goalId, type: type2, at, ...payload }) + "\n", "utf8");
|
|
2730
2743
|
const d = db(stateDir);
|
|
2731
2744
|
d.prepare("INSERT INTO goal_events (event_id, goal_id, type, payload_json, created_at) VALUES (?, ?, ?, ?, ?)").run(id, goalId, type2, JSON.stringify(payload), at);
|
|
2732
2745
|
d.close?.();
|
|
2733
2746
|
}
|
|
2734
2747
|
function read(stateDir) {
|
|
2735
2748
|
try {
|
|
2736
|
-
const v = JSON.parse(
|
|
2749
|
+
const v = JSON.parse(fs6.readFileSync(file(stateDir), "utf8"));
|
|
2737
2750
|
return Array.isArray(v) ? v : [];
|
|
2738
2751
|
} catch {
|
|
2739
2752
|
return [];
|
|
@@ -2756,7 +2769,7 @@ function listGoals(stateDir) {
|
|
|
2756
2769
|
}
|
|
2757
2770
|
function listGoalEvents(stateDir) {
|
|
2758
2771
|
try {
|
|
2759
|
-
return
|
|
2772
|
+
return fs6.readFileSync(eventFile(stateDir), "utf8").split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line));
|
|
2760
2773
|
} catch {
|
|
2761
2774
|
return [];
|
|
2762
2775
|
}
|
|
@@ -2826,9 +2839,9 @@ function isAutoMemPath(absolutePath, workspace) {
|
|
|
2826
2839
|
return normalizedPath.startsWith(getAutoMemPath(workspace));
|
|
2827
2840
|
}
|
|
2828
2841
|
async function ensureMemoryDirExists(memoryDir) {
|
|
2829
|
-
const
|
|
2842
|
+
const fs44 = await import("node:fs");
|
|
2830
2843
|
try {
|
|
2831
|
-
await
|
|
2844
|
+
await fs44.promises.mkdir(memoryDir, { recursive: true });
|
|
2832
2845
|
} catch (e) {
|
|
2833
2846
|
const code = e?.code;
|
|
2834
2847
|
if (code !== "EEXIST") {
|
|
@@ -3159,13 +3172,13 @@ __export(prompt_exports, {
|
|
|
3159
3172
|
buildSystemPrompt: () => buildSystemPrompt,
|
|
3160
3173
|
buildVolatileRuntimeContext: () => buildVolatileRuntimeContext
|
|
3161
3174
|
});
|
|
3162
|
-
import * as
|
|
3163
|
-
import * as
|
|
3175
|
+
import * as path7 from "node:path";
|
|
3176
|
+
import * as fs7 from "node:fs";
|
|
3164
3177
|
import * as os2 from "node:os";
|
|
3165
3178
|
function readFileIfExists(filePath) {
|
|
3166
3179
|
try {
|
|
3167
|
-
if (
|
|
3168
|
-
return
|
|
3180
|
+
if (fs7.existsSync(filePath)) {
|
|
3181
|
+
return fs7.readFileSync(filePath, "utf-8");
|
|
3169
3182
|
}
|
|
3170
3183
|
} catch {
|
|
3171
3184
|
}
|
|
@@ -3324,7 +3337,7 @@ function loadStaticFiles(workspace, staticFiles) {
|
|
|
3324
3337
|
if (!staticFiles || staticFiles.length === 0) return null;
|
|
3325
3338
|
const parts = [];
|
|
3326
3339
|
for (const file2 of staticFiles) {
|
|
3327
|
-
const filePath =
|
|
3340
|
+
const filePath = path7.isAbsolute(file2) ? file2 : path7.join(workspace, file2);
|
|
3328
3341
|
const content = readFileIfExists(filePath);
|
|
3329
3342
|
if (content) parts.push(content);
|
|
3330
3343
|
}
|
|
@@ -3343,7 +3356,7 @@ function loadMemoryInstructions(workspace) {
|
|
|
3343
3356
|
}
|
|
3344
3357
|
}
|
|
3345
3358
|
function resolveBlockContent(block, ctx) {
|
|
3346
|
-
const overridePath =
|
|
3359
|
+
const overridePath = path7.join(ctx.workspace, "prompts", `${block.name}.md`);
|
|
3347
3360
|
const override = readFileIfExists(overridePath);
|
|
3348
3361
|
if (override) return override;
|
|
3349
3362
|
return block.generate(ctx);
|
|
@@ -3392,7 +3405,7 @@ function buildCustomPrompt(workspace, config) {
|
|
|
3392
3405
|
continue;
|
|
3393
3406
|
}
|
|
3394
3407
|
if (name.endsWith(".md")) {
|
|
3395
|
-
const filePath =
|
|
3408
|
+
const filePath = path7.isAbsolute(name) ? name : path7.join(workspace, name);
|
|
3396
3409
|
const content = readFileIfExists(filePath);
|
|
3397
3410
|
if (content) {
|
|
3398
3411
|
parts.push(content);
|
|
@@ -3508,7 +3521,7 @@ var init_prompt = __esm({
|
|
|
3508
3521
|
{ name: "tone-style", description: "\u8BED\u6C14\u98CE\u683C\uFF08\u7B80\u6D01\u3001\u4E0D\u7528emoji\uFF09", generate: (_) => getToneAndStyleSection() },
|
|
3509
3522
|
{ name: "output-efficiency", description: "\u8F93\u51FA\u6548\u7387\uFF08\u76F4\u5954\u4E3B\u9898\uFF09", generate: (_) => getOutputEfficiencySection() },
|
|
3510
3523
|
// OpenClaw 叠加层
|
|
3511
|
-
{ name: "soul", description: "SOUL.md \u4EBA\u683C\u8EAB\u4EFD", generate: (ctx) => readFileIfExists(
|
|
3524
|
+
{ name: "soul", description: "SOUL.md \u4EBA\u683C\u8EAB\u4EFD", generate: (ctx) => readFileIfExists(path7.join(ctx.workspace, "SOUL.md")) },
|
|
3512
3525
|
{ name: "static-files", description: "\u914D\u7F6E\u6587\u4EF6\u6307\u5B9A\u7684\u989D\u5916\u6587\u4EF6\uFF08AGENTS/USER/MEMORY\u7B49\uFF09", generate: (ctx) => loadStaticFiles(ctx.workspace, ctx.staticFiles) },
|
|
3513
3526
|
{ name: "auto-memory-instructions", description: "auto memory \u5B8C\u6574\u6307\u4EE4\uFF08\u5B58+\u8BFB+recall\u8BF4\u660E\uFF09", generate: (ctx) => loadMemoryInstructions(ctx.workspace) },
|
|
3514
3527
|
// Boundary(永远在最后)
|
|
@@ -6462,8 +6475,8 @@ var init_attachments = __esm({
|
|
|
6462
6475
|
});
|
|
6463
6476
|
|
|
6464
6477
|
// src/utils/context-dump.ts
|
|
6465
|
-
import * as
|
|
6466
|
-
import * as
|
|
6478
|
+
import * as fs8 from "node:fs";
|
|
6479
|
+
import * as path8 from "node:path";
|
|
6467
6480
|
function dumpApiRequest(opts) {
|
|
6468
6481
|
const lines = [
|
|
6469
6482
|
"=== API Request Debug\uFF08\u53D1\u7ED9 LLM \u7684\u6700\u7EC8\u8BF7\u6C42\u4F53\uFF0C\u6BCF\u6B21\u8986\u76D6\u5199\uFF09===",
|
|
@@ -6496,7 +6509,7 @@ function dumpApiRequest(opts) {
|
|
|
6496
6509
|
lines.push(`[${i}] ${m.role}: (empty)`);
|
|
6497
6510
|
}
|
|
6498
6511
|
}
|
|
6499
|
-
|
|
6512
|
+
fs8.writeFileSync(path8.join(opts.workspace, ".context-debug.txt"), lines.join("\n") + "\n", "utf-8");
|
|
6500
6513
|
}
|
|
6501
6514
|
var init_context_dump = __esm({
|
|
6502
6515
|
"src/utils/context-dump.ts"() {
|
|
@@ -7556,7 +7569,7 @@ var init_contextOverflow = __esm({
|
|
|
7556
7569
|
});
|
|
7557
7570
|
|
|
7558
7571
|
// src/utils/path.ts
|
|
7559
|
-
import * as
|
|
7572
|
+
import * as path9 from "node:path";
|
|
7560
7573
|
function fixMsysPath(p) {
|
|
7561
7574
|
let fixed = p.includes("\\") ? p.replace(/\\/g, "/") : p;
|
|
7562
7575
|
if (process.platform === "win32") {
|
|
@@ -7566,15 +7579,15 @@ function fixMsysPath(p) {
|
|
|
7566
7579
|
}
|
|
7567
7580
|
function resolvePath(p, workspace) {
|
|
7568
7581
|
const fixed = fixMsysPath(p);
|
|
7569
|
-
const resolved =
|
|
7570
|
-
const normalized =
|
|
7571
|
-
const normalizedWorkspace =
|
|
7582
|
+
const resolved = path9.isAbsolute(fixed) ? path9.normalize(fixed) : path9.resolve(workspace, fixed);
|
|
7583
|
+
const normalized = path9.normalize(resolved);
|
|
7584
|
+
const normalizedWorkspace = path9.normalize(workspace);
|
|
7572
7585
|
if (sandboxOff) return normalized;
|
|
7573
|
-
if (normalized === normalizedWorkspace || normalized.startsWith(normalizedWorkspace +
|
|
7586
|
+
if (normalized === normalizedWorkspace || normalized.startsWith(normalizedWorkspace + path9.sep)) {
|
|
7574
7587
|
return normalized;
|
|
7575
7588
|
}
|
|
7576
7589
|
for (const allowed of extraAllowedPaths) {
|
|
7577
|
-
if (normalized === allowed || normalized.startsWith(allowed +
|
|
7590
|
+
if (normalized === allowed || normalized.startsWith(allowed + path9.sep)) {
|
|
7578
7591
|
return normalized;
|
|
7579
7592
|
}
|
|
7580
7593
|
}
|
|
@@ -7809,9 +7822,9 @@ __export(BashTool_exports, {
|
|
|
7809
7822
|
findShell: () => findShell,
|
|
7810
7823
|
killChild: () => killChild
|
|
7811
7824
|
});
|
|
7812
|
-
import { spawn as spawn2, execSync } from "node:child_process";
|
|
7813
|
-
import * as
|
|
7814
|
-
import * as
|
|
7825
|
+
import { spawn as spawn2, execSync as execSync2 } from "node:child_process";
|
|
7826
|
+
import * as fs9 from "node:fs";
|
|
7827
|
+
import * as path10 from "node:path";
|
|
7815
7828
|
function isWslBash(p) {
|
|
7816
7829
|
const normalized = p.replace(/\//g, "\\").toLowerCase();
|
|
7817
7830
|
return WSL_PATH_MARKERS.some((m) => normalized.includes(m.toLowerCase()));
|
|
@@ -7823,14 +7836,14 @@ function findShell() {
|
|
|
7823
7836
|
return cachedShell;
|
|
7824
7837
|
}
|
|
7825
7838
|
try {
|
|
7826
|
-
const result =
|
|
7839
|
+
const result = execSync2("where.exe bash", {
|
|
7827
7840
|
encoding: "utf-8",
|
|
7828
7841
|
timeout: 5e3,
|
|
7829
7842
|
stdio: ["ignore", "pipe", "ignore"]
|
|
7830
7843
|
});
|
|
7831
7844
|
const candidates = result.trim().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
7832
7845
|
const nonWsl = candidates.find((p) => !isWslBash(p));
|
|
7833
|
-
if (nonWsl &&
|
|
7846
|
+
if (nonWsl && fs9.existsSync(nonWsl)) {
|
|
7834
7847
|
cachedShell = { shell: nonWsl, args: ["-c"] };
|
|
7835
7848
|
return cachedShell;
|
|
7836
7849
|
}
|
|
@@ -7840,10 +7853,10 @@ function findShell() {
|
|
|
7840
7853
|
"C:\\Program Files\\Git\\bin\\bash.exe",
|
|
7841
7854
|
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
7842
7855
|
"C:\\Program Files\\Git\\usr\\bin\\bash.exe",
|
|
7843
|
-
|
|
7856
|
+
path10.join(process.env.LOCALAPPDATA || "", "Programs", "Git", "bin", "bash.exe")
|
|
7844
7857
|
];
|
|
7845
7858
|
for (const p of knownPaths) {
|
|
7846
|
-
if (p &&
|
|
7859
|
+
if (p && fs9.existsSync(p)) {
|
|
7847
7860
|
cachedShell = { shell: p, args: ["-c"] };
|
|
7848
7861
|
return cachedShell;
|
|
7849
7862
|
}
|
|
@@ -7946,8 +7959,8 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
|
|
|
7946
7959
|
}
|
|
7947
7960
|
const MAX_OUTPUT = 100 * 1024;
|
|
7948
7961
|
const osMod = await import("node:os");
|
|
7949
|
-
const outputFile =
|
|
7950
|
-
const outputHandle = await
|
|
7962
|
+
const outputFile = path10.join(osMod.tmpdir(), `exec-${Date.now()}-${Math.random().toString(36).slice(2)}.out`);
|
|
7963
|
+
const outputHandle = await fs9.promises.open(outputFile, "w");
|
|
7951
7964
|
return new Promise((resolve12) => {
|
|
7952
7965
|
const { shell, args: shellArgs } = findShell();
|
|
7953
7966
|
const child = spawn2(shell, [...shellArgs, command], {
|
|
@@ -7966,21 +7979,21 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
|
|
|
7966
7979
|
let fileOutput = "";
|
|
7967
7980
|
let truncated = false;
|
|
7968
7981
|
try {
|
|
7969
|
-
const st = await
|
|
7982
|
+
const st = await fs9.promises.stat(outputFile);
|
|
7970
7983
|
if (st.size > MAX_OUTPUT) {
|
|
7971
|
-
const rfd = await
|
|
7984
|
+
const rfd = await fs9.promises.open(outputFile, "r");
|
|
7972
7985
|
const buf = Buffer.alloc(MAX_OUTPUT);
|
|
7973
7986
|
await rfd.read(buf, 0, MAX_OUTPUT, 0);
|
|
7974
7987
|
await rfd.close();
|
|
7975
7988
|
fileOutput = buf.toString("utf-8");
|
|
7976
7989
|
truncated = true;
|
|
7977
7990
|
} else {
|
|
7978
|
-
fileOutput = await
|
|
7991
|
+
fileOutput = await fs9.promises.readFile(outputFile, "utf-8");
|
|
7979
7992
|
}
|
|
7980
7993
|
} catch {
|
|
7981
7994
|
}
|
|
7982
7995
|
try {
|
|
7983
|
-
await
|
|
7996
|
+
await fs9.promises.unlink(outputFile);
|
|
7984
7997
|
} catch {
|
|
7985
7998
|
}
|
|
7986
7999
|
const processedStdout = fileOutput.replace(/^(\s*\n)+/, "").trimEnd();
|
|
@@ -8057,8 +8070,8 @@ __export(task_manager_exports, {
|
|
|
8057
8070
|
});
|
|
8058
8071
|
import { randomBytes } from "node:crypto";
|
|
8059
8072
|
import { spawn as spawn3 } from "node:child_process";
|
|
8060
|
-
import * as
|
|
8061
|
-
import * as
|
|
8073
|
+
import * as fs10 from "node:fs";
|
|
8074
|
+
import * as path11 from "node:path";
|
|
8062
8075
|
function generateTaskId(type2 = "local_bash") {
|
|
8063
8076
|
const prefix = TASK_ID_PREFIXES[type2] ?? "x";
|
|
8064
8077
|
const bytes = randomBytes(8);
|
|
@@ -8071,42 +8084,42 @@ function generateTaskId(type2 = "local_bash") {
|
|
|
8071
8084
|
function getTaskOutputDir() {
|
|
8072
8085
|
if (_taskOutputDir === void 0) {
|
|
8073
8086
|
const stateDir = process.env.ENGINE_STATE_DIR || process.cwd();
|
|
8074
|
-
_taskOutputDir =
|
|
8087
|
+
_taskOutputDir = path11.join(stateDir, "tasks");
|
|
8075
8088
|
}
|
|
8076
8089
|
return _taskOutputDir;
|
|
8077
8090
|
}
|
|
8078
8091
|
function getTaskOutputPath(taskId) {
|
|
8079
|
-
return
|
|
8092
|
+
return path11.join(getTaskOutputDir(), `${taskId}.output`);
|
|
8080
8093
|
}
|
|
8081
8094
|
function ensureOutputDir() {
|
|
8082
8095
|
const dir = getTaskOutputDir();
|
|
8083
|
-
if (!
|
|
8084
|
-
|
|
8096
|
+
if (!fs10.existsSync(dir)) {
|
|
8097
|
+
fs10.mkdirSync(dir, { recursive: true });
|
|
8085
8098
|
}
|
|
8086
8099
|
}
|
|
8087
8100
|
function initTaskOutput(taskId) {
|
|
8088
8101
|
ensureOutputDir();
|
|
8089
8102
|
const outputPath = getTaskOutputPath(taskId);
|
|
8090
|
-
|
|
8103
|
+
fs10.writeFileSync(outputPath, "", "utf-8");
|
|
8091
8104
|
return outputPath;
|
|
8092
8105
|
}
|
|
8093
8106
|
function persistTask(state2) {
|
|
8094
8107
|
try {
|
|
8095
8108
|
ensureOutputDir();
|
|
8096
8109
|
const p = taskIndexPath();
|
|
8097
|
-
const existing =
|
|
8110
|
+
const existing = fs10.existsSync(p) ? JSON.parse(fs10.readFileSync(p, "utf8")) : [];
|
|
8098
8111
|
const next = existing.filter((t) => t.id !== state2.id);
|
|
8099
8112
|
next.push({ ...state2 });
|
|
8100
8113
|
const tmp = `${p}.${process.pid}.tmp`;
|
|
8101
|
-
|
|
8102
|
-
|
|
8114
|
+
fs10.writeFileSync(tmp, JSON.stringify(next, null, 2));
|
|
8115
|
+
fs10.renameSync(tmp, p);
|
|
8103
8116
|
} catch (err) {
|
|
8104
8117
|
console.warn(`[task-manager] persist failed: ${err.message}`);
|
|
8105
8118
|
}
|
|
8106
8119
|
}
|
|
8107
8120
|
function loadPersistedTasks() {
|
|
8108
8121
|
try {
|
|
8109
|
-
const v = JSON.parse(
|
|
8122
|
+
const v = JSON.parse(fs10.readFileSync(taskIndexPath(), "utf8"));
|
|
8110
8123
|
return Array.isArray(v) ? v : [];
|
|
8111
8124
|
} catch {
|
|
8112
8125
|
return [];
|
|
@@ -8116,7 +8129,7 @@ function loadNotificationQueue() {
|
|
|
8116
8129
|
if (notificationsLoaded) return;
|
|
8117
8130
|
notificationsLoaded = true;
|
|
8118
8131
|
try {
|
|
8119
|
-
const value = JSON.parse(
|
|
8132
|
+
const value = JSON.parse(fs10.readFileSync(notificationQueuePath(), "utf8"));
|
|
8120
8133
|
if (Array.isArray(value)) pendingNotifications.push(...value.filter((x) => x && typeof x.notification === "string"));
|
|
8121
8134
|
} catch {
|
|
8122
8135
|
}
|
|
@@ -8126,8 +8139,8 @@ function persistNotificationQueue() {
|
|
|
8126
8139
|
ensureOutputDir();
|
|
8127
8140
|
const p = notificationQueuePath();
|
|
8128
8141
|
const tmp = `${p}.${process.pid}.tmp`;
|
|
8129
|
-
|
|
8130
|
-
|
|
8142
|
+
fs10.writeFileSync(tmp, JSON.stringify(pendingNotifications, null, 2), "utf8");
|
|
8143
|
+
fs10.renameSync(tmp, p);
|
|
8131
8144
|
} catch (err) {
|
|
8132
8145
|
console.warn(`[task-manager] notification persist failed: ${err.message}`);
|
|
8133
8146
|
}
|
|
@@ -8264,14 +8277,14 @@ function spawnBackgroundTask(opts) {
|
|
|
8264
8277
|
const taskId = generateTaskId("local_bash");
|
|
8265
8278
|
const outputPath = initTaskOutput(taskId);
|
|
8266
8279
|
const { shell, args: shellArgs } = findShell();
|
|
8267
|
-
const outputFd =
|
|
8280
|
+
const outputFd = fs10.openSync(outputPath, "w");
|
|
8268
8281
|
const child = spawn3(shell, [...shellArgs, opts.command], {
|
|
8269
8282
|
cwd: opts.cwd,
|
|
8270
8283
|
env: opts.env || process.env,
|
|
8271
8284
|
stdio: ["ignore", outputFd, outputFd]
|
|
8272
8285
|
});
|
|
8273
8286
|
try {
|
|
8274
|
-
|
|
8287
|
+
fs10.closeSync(outputFd);
|
|
8275
8288
|
} catch {
|
|
8276
8289
|
}
|
|
8277
8290
|
processes.set(taskId, child);
|
|
@@ -8303,12 +8316,12 @@ function spawnBackgroundTask(opts) {
|
|
|
8303
8316
|
let killedForSize = false;
|
|
8304
8317
|
sizeWatchdog = setInterval(() => {
|
|
8305
8318
|
if (tasks.get(taskId)?.status !== "running") return;
|
|
8306
|
-
|
|
8319
|
+
fs10.stat(outputPath, (err, st) => {
|
|
8307
8320
|
if (err || st.size <= MAX_TASK_OUTPUT_BYTES) return;
|
|
8308
8321
|
killedForSize = true;
|
|
8309
8322
|
if (sizeWatchdog) clearInterval(sizeWatchdog);
|
|
8310
8323
|
try {
|
|
8311
|
-
|
|
8324
|
+
fs10.appendFileSync(outputPath, "\n[output truncated: exceeded 5GB disk cap]\n");
|
|
8312
8325
|
} catch {
|
|
8313
8326
|
}
|
|
8314
8327
|
killChild(child);
|
|
@@ -8438,16 +8451,16 @@ function getTaskOutput(taskId, maxBytes = 8 * 1024 * 1024) {
|
|
|
8438
8451
|
if (!state2) return "";
|
|
8439
8452
|
try {
|
|
8440
8453
|
const outputPath = state2.outputFile;
|
|
8441
|
-
if (!
|
|
8442
|
-
const stat4 =
|
|
8454
|
+
if (!fs10.existsSync(outputPath)) return "";
|
|
8455
|
+
const stat4 = fs10.statSync(outputPath);
|
|
8443
8456
|
if (stat4.size <= maxBytes) {
|
|
8444
|
-
return
|
|
8457
|
+
return fs10.readFileSync(outputPath, "utf-8");
|
|
8445
8458
|
}
|
|
8446
|
-
const fd =
|
|
8459
|
+
const fd = fs10.openSync(outputPath, "r");
|
|
8447
8460
|
const start = stat4.size - maxBytes;
|
|
8448
8461
|
const buf = Buffer.alloc(maxBytes);
|
|
8449
|
-
|
|
8450
|
-
|
|
8462
|
+
fs10.readSync(fd, buf, 0, maxBytes, start);
|
|
8463
|
+
fs10.closeSync(fd);
|
|
8451
8464
|
const content = buf.toString("utf-8");
|
|
8452
8465
|
const omitted = Math.round((stat4.size - maxBytes) / 1024);
|
|
8453
8466
|
return `[${omitted}KB of earlier output omitted]
|
|
@@ -8461,14 +8474,14 @@ function getTaskOutputDelta(taskId, fromOffset, maxBytes = 8 * 1024 * 1024) {
|
|
|
8461
8474
|
if (!state2) return { content: "", newOffset: fromOffset };
|
|
8462
8475
|
try {
|
|
8463
8476
|
const outputPath = state2.outputFile;
|
|
8464
|
-
if (!
|
|
8465
|
-
const stat4 =
|
|
8477
|
+
if (!fs10.existsSync(outputPath)) return { content: "", newOffset: fromOffset };
|
|
8478
|
+
const stat4 = fs10.statSync(outputPath);
|
|
8466
8479
|
if (fromOffset >= stat4.size) return { content: "", newOffset: stat4.size };
|
|
8467
8480
|
const readLen = Math.min(maxBytes, stat4.size - fromOffset);
|
|
8468
8481
|
const buf = Buffer.alloc(readLen);
|
|
8469
|
-
const fd =
|
|
8470
|
-
|
|
8471
|
-
|
|
8482
|
+
const fd = fs10.openSync(outputPath, "r");
|
|
8483
|
+
fs10.readSync(fd, buf, 0, readLen, fromOffset);
|
|
8484
|
+
fs10.closeSync(fd);
|
|
8472
8485
|
return { content: buf.toString("utf-8"), newOffset: fromOffset + readLen };
|
|
8473
8486
|
} catch {
|
|
8474
8487
|
return { content: "", newOffset: fromOffset };
|
|
@@ -8478,8 +8491,8 @@ function getTaskOutputSize(taskId) {
|
|
|
8478
8491
|
const state2 = tasks.get(taskId);
|
|
8479
8492
|
if (!state2) return 0;
|
|
8480
8493
|
try {
|
|
8481
|
-
if (!
|
|
8482
|
-
return
|
|
8494
|
+
if (!fs10.existsSync(state2.outputFile)) return 0;
|
|
8495
|
+
return fs10.statSync(state2.outputFile).size;
|
|
8483
8496
|
} catch {
|
|
8484
8497
|
return 0;
|
|
8485
8498
|
}
|
|
@@ -8517,10 +8530,10 @@ var init_task_manager = __esm({
|
|
|
8517
8530
|
MAX_TASK_OUTPUT_BYTES = 5 * 1024 * 1024 * 1024;
|
|
8518
8531
|
tasks = /* @__PURE__ */ new Map();
|
|
8519
8532
|
processes = /* @__PURE__ */ new Map();
|
|
8520
|
-
taskIndexPath = () =>
|
|
8533
|
+
taskIndexPath = () => path11.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "index.json");
|
|
8521
8534
|
pendingNotifications = [];
|
|
8522
8535
|
notificationsLoaded = false;
|
|
8523
|
-
notificationQueuePath = () =>
|
|
8536
|
+
notificationQueuePath = () => path11.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "notifications.json");
|
|
8524
8537
|
notificationCallback = null;
|
|
8525
8538
|
DEAD_LETTER_MAX_ATTEMPTS = 10;
|
|
8526
8539
|
RETRY_BASE_MS = 1e3;
|
|
@@ -8662,8 +8675,8 @@ __export(context_analyzer_exports, {
|
|
|
8662
8675
|
formatContextReport: () => formatContextReport,
|
|
8663
8676
|
scanMemoryFiles: () => scanMemoryFiles
|
|
8664
8677
|
});
|
|
8665
|
-
import * as
|
|
8666
|
-
import * as
|
|
8678
|
+
import * as fs11 from "node:fs";
|
|
8679
|
+
import * as path12 from "node:path";
|
|
8667
8680
|
function estimateMessageTokens2(m) {
|
|
8668
8681
|
let tokens = 0;
|
|
8669
8682
|
if (typeof m.content === "string") {
|
|
@@ -8773,9 +8786,9 @@ function breakdownMessages(messages) {
|
|
|
8773
8786
|
}
|
|
8774
8787
|
async function scanMemoryFiles(workspace) {
|
|
8775
8788
|
const files = [];
|
|
8776
|
-
const soul = readFileIfExists2(
|
|
8789
|
+
const soul = readFileIfExists2(path12.join(workspace, "SOUL.md"));
|
|
8777
8790
|
if (soul) files.push({ path: "SOUL.md", tokens: roughTokenCountEstimation(soul), stable: true });
|
|
8778
|
-
const agents = readFileIfExists2(
|
|
8791
|
+
const agents = readFileIfExists2(path12.join(workspace, "AGENTS.md"));
|
|
8779
8792
|
if (agents) files.push({ path: "AGENTS.md", tokens: roughTokenCountEstimation(agents), stable: true });
|
|
8780
8793
|
try {
|
|
8781
8794
|
const { buildMemoryPrompt: buildMemoryPrompt2 } = await Promise.resolve().then(() => (init_memdir(), memdir_exports));
|
|
@@ -8791,7 +8804,7 @@ async function scanMemoryFiles(workspace) {
|
|
|
8791
8804
|
}
|
|
8792
8805
|
function readFileIfExists2(filePath) {
|
|
8793
8806
|
try {
|
|
8794
|
-
if (
|
|
8807
|
+
if (fs11.existsSync(filePath)) return fs11.readFileSync(filePath, "utf-8");
|
|
8795
8808
|
} catch {
|
|
8796
8809
|
}
|
|
8797
8810
|
return null;
|
|
@@ -9770,8 +9783,8 @@ ${perTurnSystemDynamic}` : deferredHint || perTurnSystemDynamic;
|
|
|
9770
9783
|
});
|
|
9771
9784
|
|
|
9772
9785
|
// src/session/writer.ts
|
|
9773
|
-
import * as
|
|
9774
|
-
import * as
|
|
9786
|
+
import * as fs12 from "node:fs";
|
|
9787
|
+
import * as path13 from "node:path";
|
|
9775
9788
|
import * as crypto2 from "node:crypto";
|
|
9776
9789
|
function assistantWriteParamsFrom(m) {
|
|
9777
9790
|
const anyM = m;
|
|
@@ -9807,7 +9820,7 @@ var init_writer = __esm({
|
|
|
9807
9820
|
this.sessionId = sessionId || crypto2.randomUUID();
|
|
9808
9821
|
this.engineSessionId = "";
|
|
9809
9822
|
const filename = `${this.sessionId}.jsonl`;
|
|
9810
|
-
this.filePath =
|
|
9823
|
+
this.filePath = path13.join(sessionsDir, filename);
|
|
9811
9824
|
}
|
|
9812
9825
|
get id() {
|
|
9813
9826
|
return this.sessionId;
|
|
@@ -9818,9 +9831,9 @@ var init_writer = __esm({
|
|
|
9818
9831
|
/** 打开文件写入 header(新文件才写 header) */
|
|
9819
9832
|
open(cwd, engineSessionId) {
|
|
9820
9833
|
this.engineSessionId = engineSessionId || "";
|
|
9821
|
-
|
|
9822
|
-
const fileExists =
|
|
9823
|
-
this.stream =
|
|
9834
|
+
fs12.mkdirSync(path13.dirname(this.filePath), { recursive: true });
|
|
9835
|
+
const fileExists = fs12.existsSync(this.filePath) && fs12.statSync(this.filePath).size > 0;
|
|
9836
|
+
this.stream = fs12.createWriteStream(this.filePath, { flags: "a" });
|
|
9824
9837
|
this.stream.on("error", (err) => {
|
|
9825
9838
|
console.error(`[SessionWriter] write error on ${this.filePath}:`, err.message);
|
|
9826
9839
|
});
|
|
@@ -10023,17 +10036,17 @@ var init_writer = __esm({
|
|
|
10023
10036
|
this.stream.end();
|
|
10024
10037
|
this.stream = null;
|
|
10025
10038
|
}
|
|
10026
|
-
if (!
|
|
10027
|
-
const fileSize =
|
|
10039
|
+
if (!fs12.existsSync(this.filePath)) return null;
|
|
10040
|
+
const fileSize = fs12.statSync(this.filePath).size;
|
|
10028
10041
|
if (fileSize === 0) return null;
|
|
10029
10042
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-");
|
|
10030
10043
|
const archivedPath = `${this.filePath}.${reason}.${ts}`;
|
|
10031
|
-
|
|
10044
|
+
fs12.renameSync(this.filePath, archivedPath);
|
|
10032
10045
|
const sizeMB = (fileSize / 1024 / 1024).toFixed(1);
|
|
10033
|
-
console.log(`[SessionWriter] Archived JSONL: ${
|
|
10046
|
+
console.log(`[SessionWriter] Archived JSONL: ${path13.basename(this.filePath)} \u2192 ${path13.basename(archivedPath)} (${sizeMB}MB)`);
|
|
10034
10047
|
const postBoundaryData = this.readPostBoundaryFromArchived(archivedPath);
|
|
10035
|
-
const dir =
|
|
10036
|
-
|
|
10048
|
+
const dir = path13.dirname(this.filePath);
|
|
10049
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
10037
10050
|
const header = {
|
|
10038
10051
|
type: "session",
|
|
10039
10052
|
version: 3,
|
|
@@ -10047,8 +10060,8 @@ var init_writer = __esm({
|
|
|
10047
10060
|
if (postBoundaryData.length > 0) {
|
|
10048
10061
|
initialData += postBoundaryData.toString("utf-8");
|
|
10049
10062
|
}
|
|
10050
|
-
|
|
10051
|
-
this.stream =
|
|
10063
|
+
fs12.writeFileSync(this.filePath, initialData, "utf-8");
|
|
10064
|
+
this.stream = fs12.createWriteStream(this.filePath, { flags: "a" });
|
|
10052
10065
|
this.stream.on("error", (err) => {
|
|
10053
10066
|
console.error(`[SessionWriter] write error on ${this.filePath}:`, err.message);
|
|
10054
10067
|
});
|
|
@@ -10058,10 +10071,10 @@ var init_writer = __esm({
|
|
|
10058
10071
|
* 从归档文件中读取最后一个 compact_boundary 之后的内容
|
|
10059
10072
|
*/
|
|
10060
10073
|
readPostBoundaryFromArchived(archivedPath) {
|
|
10061
|
-
const fileSize =
|
|
10074
|
+
const fileSize = fs12.statSync(archivedPath).size;
|
|
10062
10075
|
if (fileSize === 0) return Buffer.alloc(0);
|
|
10063
10076
|
if (fileSize <= 5 * 1024 * 1024) {
|
|
10064
|
-
const content =
|
|
10077
|
+
const content = fs12.readFileSync(archivedPath, "utf-8");
|
|
10065
10078
|
const lines = content.split("\n");
|
|
10066
10079
|
let lastBoundaryIdx = -1;
|
|
10067
10080
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -10078,11 +10091,11 @@ var init_writer = __esm({
|
|
|
10078
10091
|
{
|
|
10079
10092
|
const probeSize = Math.min(fileSize, 1024 * 1024);
|
|
10080
10093
|
const probeBuf = Buffer.allocUnsafe(probeSize);
|
|
10081
|
-
const probeFd =
|
|
10094
|
+
const probeFd = fs12.openSync(archivedPath, "r");
|
|
10082
10095
|
let hasBoundary = false;
|
|
10083
10096
|
let probed = 0;
|
|
10084
10097
|
while (probed < fileSize) {
|
|
10085
|
-
const n =
|
|
10098
|
+
const n = fs12.readSync(probeFd, probeBuf, 0, Math.min(probeSize, fileSize - probed), probed);
|
|
10086
10099
|
if (n === 0) break;
|
|
10087
10100
|
if (probeBuf.subarray(0, n).includes(Buffer.from(boundaryMarker))) {
|
|
10088
10101
|
hasBoundary = true;
|
|
@@ -10090,19 +10103,19 @@ var init_writer = __esm({
|
|
|
10090
10103
|
}
|
|
10091
10104
|
probed += n;
|
|
10092
10105
|
}
|
|
10093
|
-
|
|
10106
|
+
fs12.closeSync(probeFd);
|
|
10094
10107
|
if (!hasBoundary) return Buffer.alloc(0);
|
|
10095
10108
|
}
|
|
10096
10109
|
const outBuf = Buffer.allocUnsafe(Math.min(fileSize, 8 * 1024 * 1024));
|
|
10097
10110
|
let outLen = 0;
|
|
10098
10111
|
const chunk = Buffer.allocUnsafe(CHUNK_SIZE);
|
|
10099
|
-
const fd =
|
|
10112
|
+
const fd = fs12.openSync(archivedPath, "r");
|
|
10100
10113
|
try {
|
|
10101
10114
|
let filePos = 0;
|
|
10102
10115
|
let carryBuf;
|
|
10103
10116
|
let carryLen = 0;
|
|
10104
10117
|
while (filePos < fileSize) {
|
|
10105
|
-
const bytesRead =
|
|
10118
|
+
const bytesRead = fs12.readSync(fd, chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
|
|
10106
10119
|
if (bytesRead === 0) break;
|
|
10107
10120
|
filePos += bytesRead;
|
|
10108
10121
|
let scanBuf;
|
|
@@ -10151,7 +10164,7 @@ var init_writer = __esm({
|
|
|
10151
10164
|
}
|
|
10152
10165
|
}
|
|
10153
10166
|
} finally {
|
|
10154
|
-
|
|
10167
|
+
fs12.closeSync(fd);
|
|
10155
10168
|
}
|
|
10156
10169
|
return outBuf.subarray(0, outLen);
|
|
10157
10170
|
}
|
|
@@ -10163,15 +10176,15 @@ var init_writer = __esm({
|
|
|
10163
10176
|
*/
|
|
10164
10177
|
readLastId() {
|
|
10165
10178
|
try {
|
|
10166
|
-
const stat4 =
|
|
10179
|
+
const stat4 = fs12.statSync(this.filePath);
|
|
10167
10180
|
if (stat4.size === 0) return null;
|
|
10168
10181
|
const readSize = Math.min(stat4.size, 4096);
|
|
10169
10182
|
const buf = Buffer.alloc(readSize);
|
|
10170
|
-
const fd =
|
|
10183
|
+
const fd = fs12.openSync(this.filePath, "r");
|
|
10171
10184
|
try {
|
|
10172
|
-
|
|
10185
|
+
fs12.readSync(fd, buf, 0, readSize, stat4.size - readSize);
|
|
10173
10186
|
} finally {
|
|
10174
|
-
|
|
10187
|
+
fs12.closeSync(fd);
|
|
10175
10188
|
}
|
|
10176
10189
|
const text = buf.toString("utf-8");
|
|
10177
10190
|
const lines = text.split("\n").filter((l) => l.trim().length > 0);
|
|
@@ -10218,11 +10231,11 @@ var init_writer = __esm({
|
|
|
10218
10231
|
});
|
|
10219
10232
|
|
|
10220
10233
|
// src/session/reader.ts
|
|
10221
|
-
import * as
|
|
10222
|
-
import * as
|
|
10234
|
+
import * as fs13 from "node:fs";
|
|
10235
|
+
import * as path14 from "node:path";
|
|
10223
10236
|
import * as readline from "node:readline";
|
|
10224
10237
|
async function readSessionHeader(filePath) {
|
|
10225
|
-
const stream =
|
|
10238
|
+
const stream = fs13.createReadStream(filePath, { encoding: "utf-8" });
|
|
10226
10239
|
const rl = readline.createInterface({ input: stream });
|
|
10227
10240
|
return new Promise((resolve12) => {
|
|
10228
10241
|
let resolved = false;
|
|
@@ -10253,7 +10266,7 @@ async function readSessionHeader(filePath) {
|
|
|
10253
10266
|
});
|
|
10254
10267
|
}
|
|
10255
10268
|
async function readLargeFilePostBoundary(filePath) {
|
|
10256
|
-
const stat4 =
|
|
10269
|
+
const stat4 = fs13.statSync(filePath);
|
|
10257
10270
|
const fileSize = stat4.size;
|
|
10258
10271
|
const boundaryMarker = '"compact_boundary"';
|
|
10259
10272
|
const CHUNK_SIZE = TRANSCRIPT_READ_CHUNK_SIZE;
|
|
@@ -10261,13 +10274,13 @@ async function readLargeFilePostBoundary(filePath) {
|
|
|
10261
10274
|
let outLen = 0;
|
|
10262
10275
|
let boundaryStartOffset = 0;
|
|
10263
10276
|
const chunk = Buffer.allocUnsafe(CHUNK_SIZE);
|
|
10264
|
-
const fd =
|
|
10277
|
+
const fd = fs13.openSync(filePath, "r");
|
|
10265
10278
|
try {
|
|
10266
10279
|
let filePos = 0;
|
|
10267
10280
|
let carryBuf;
|
|
10268
10281
|
let carryLen = 0;
|
|
10269
10282
|
while (filePos < fileSize) {
|
|
10270
|
-
const bytesRead =
|
|
10283
|
+
const bytesRead = fs13.readSync(fd, chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
|
|
10271
10284
|
if (bytesRead === 0) break;
|
|
10272
10285
|
filePos += bytesRead;
|
|
10273
10286
|
let scanBuf;
|
|
@@ -10319,7 +10332,7 @@ async function readLargeFilePostBoundary(filePath) {
|
|
|
10319
10332
|
}
|
|
10320
10333
|
}
|
|
10321
10334
|
} finally {
|
|
10322
|
-
|
|
10335
|
+
fs13.closeSync(fd);
|
|
10323
10336
|
}
|
|
10324
10337
|
const postBoundaryText = outBuf.subarray(0, outLen).toString("utf-8");
|
|
10325
10338
|
return postBoundaryText.split("\n").filter((l) => l.trim().length > 0);
|
|
@@ -10443,7 +10456,7 @@ function recoverOrphanedParallelToolResults(allEntries, chain, byUuid, seen) {
|
|
|
10443
10456
|
return result;
|
|
10444
10457
|
}
|
|
10445
10458
|
async function readSessionHistory(filePath) {
|
|
10446
|
-
const stat4 =
|
|
10459
|
+
const stat4 = fs13.statSync(filePath);
|
|
10447
10460
|
const fileSize = stat4.size;
|
|
10448
10461
|
if (fileSize > MAX_TRANSCRIPT_READ_BYTES) {
|
|
10449
10462
|
console.warn(`[reader] Session file exceeds 50MB limit (${(fileSize / 1024 / 1024).toFixed(1)}MB), using chunked fd read with boundary skip`);
|
|
@@ -10482,7 +10495,7 @@ async function readSessionHistory(filePath) {
|
|
|
10482
10495
|
return [...sessionStarts, ...filtered, ...restAttachments];
|
|
10483
10496
|
}
|
|
10484
10497
|
async function readAllLines(filePath) {
|
|
10485
|
-
const stream =
|
|
10498
|
+
const stream = fs13.createReadStream(filePath, { encoding: "utf-8" });
|
|
10486
10499
|
const rl = readline.createInterface({ input: stream });
|
|
10487
10500
|
const lines = [];
|
|
10488
10501
|
return new Promise((resolve12, reject) => {
|
|
@@ -10636,12 +10649,12 @@ function extractText(content) {
|
|
|
10636
10649
|
return content.filter((b) => b.type === "text").map((b) => b.text || "").join("") || null;
|
|
10637
10650
|
}
|
|
10638
10651
|
function listSessions(sessionsDir) {
|
|
10639
|
-
if (!
|
|
10640
|
-
const files =
|
|
10641
|
-
file:
|
|
10652
|
+
if (!fs13.existsSync(sessionsDir)) return [];
|
|
10653
|
+
const files = fs13.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") || f.includes(".jsonl.")).map((f) => ({
|
|
10654
|
+
file: path14.join(sessionsDir, f),
|
|
10642
10655
|
id: f.replace(/\.jsonl.*$/, ""),
|
|
10643
10656
|
// strip .jsonl and everything after (archived suffix)
|
|
10644
|
-
modified: new Date(
|
|
10657
|
+
modified: new Date(fs13.statSync(path14.join(sessionsDir, f)).mtimeMs)
|
|
10645
10658
|
})).sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
10646
10659
|
return files;
|
|
10647
10660
|
}
|
|
@@ -10662,8 +10675,8 @@ __export(session_manager_exports, {
|
|
|
10662
10675
|
SessionManager: () => SessionManager,
|
|
10663
10676
|
alignRestoreHeadToTurnBoundary: () => alignRestoreHeadToTurnBoundary
|
|
10664
10677
|
});
|
|
10665
|
-
import * as
|
|
10666
|
-
import * as
|
|
10678
|
+
import * as path15 from "node:path";
|
|
10679
|
+
import * as fs14 from "node:fs";
|
|
10667
10680
|
import * as crypto3 from "node:crypto";
|
|
10668
10681
|
function alignRestoreHeadToTurnBoundary(messages, minKeep = RESTORE_MIN_KEEP_MESSAGES) {
|
|
10669
10682
|
const isTurnBoundary = (m) => isAttachmentMessage(m) ? true : m.role === "user";
|
|
@@ -10702,24 +10715,24 @@ var init_session_manager = __esm({
|
|
|
10702
10715
|
constructor(config) {
|
|
10703
10716
|
this.config = config;
|
|
10704
10717
|
this.scopeConfig = config.scopeConfig;
|
|
10705
|
-
this.sessionsDir =
|
|
10706
|
-
this.indexPath =
|
|
10707
|
-
this.platformMapPath =
|
|
10708
|
-
|
|
10718
|
+
this.sessionsDir = path15.join(config.stateDir, "agents", "main", "sessions");
|
|
10719
|
+
this.indexPath = path15.join(this.sessionsDir, "session-index.json");
|
|
10720
|
+
this.platformMapPath = path15.join(this.sessionsDir, "platform-map.json");
|
|
10721
|
+
fs14.mkdirSync(this.sessionsDir, { recursive: true });
|
|
10709
10722
|
}
|
|
10710
10723
|
// === 索引操作 ===
|
|
10711
10724
|
loadIndex() {
|
|
10712
10725
|
try {
|
|
10713
|
-
if (
|
|
10714
|
-
const raw =
|
|
10726
|
+
if (fs14.existsSync(this.indexPath)) {
|
|
10727
|
+
const raw = fs14.readFileSync(this.indexPath, "utf-8");
|
|
10715
10728
|
const obj = JSON.parse(raw);
|
|
10716
10729
|
this.index = new Map(Object.entries(obj));
|
|
10717
10730
|
let fixed = 0;
|
|
10718
10731
|
for (const [key, entry] of this.index) {
|
|
10719
|
-
if (
|
|
10720
|
-
const basename10 =
|
|
10721
|
-
const localPath =
|
|
10722
|
-
if (
|
|
10732
|
+
if (fs14.existsSync(entry.file)) continue;
|
|
10733
|
+
const basename10 = path15.basename(entry.file);
|
|
10734
|
+
const localPath = path15.join(this.sessionsDir, basename10);
|
|
10735
|
+
if (fs14.existsSync(localPath)) {
|
|
10723
10736
|
entry.file = localPath;
|
|
10724
10737
|
fixed++;
|
|
10725
10738
|
}
|
|
@@ -10738,7 +10751,7 @@ var init_session_manager = __esm({
|
|
|
10738
10751
|
try {
|
|
10739
10752
|
const obj = {};
|
|
10740
10753
|
for (const [k, v] of this.index) obj[k] = v;
|
|
10741
|
-
|
|
10754
|
+
fs14.writeFileSync(this.indexPath, JSON.stringify(obj, null, 2));
|
|
10742
10755
|
} catch (err) {
|
|
10743
10756
|
console.error(`[session] Failed to save index: ${err.message}`);
|
|
10744
10757
|
}
|
|
@@ -10746,8 +10759,8 @@ var init_session_manager = __esm({
|
|
|
10746
10759
|
// === 平台映射 ===
|
|
10747
10760
|
loadPlatformMap() {
|
|
10748
10761
|
try {
|
|
10749
|
-
if (
|
|
10750
|
-
const raw =
|
|
10762
|
+
if (fs14.existsSync(this.platformMapPath)) {
|
|
10763
|
+
const raw = fs14.readFileSync(this.platformMapPath, "utf-8");
|
|
10751
10764
|
const obj = JSON.parse(raw);
|
|
10752
10765
|
this.platformMap = new Map(Object.entries(obj));
|
|
10753
10766
|
console.log(`[session] Platform map loaded: ${this.platformMap.size} entries`);
|
|
@@ -10759,7 +10772,7 @@ var init_session_manager = __esm({
|
|
|
10759
10772
|
try {
|
|
10760
10773
|
const obj = {};
|
|
10761
10774
|
for (const [k, v] of this.platformMap) obj[k] = v;
|
|
10762
|
-
|
|
10775
|
+
fs14.writeFileSync(this.platformMapPath, JSON.stringify(obj, null, 2));
|
|
10763
10776
|
} catch (err) {
|
|
10764
10777
|
console.error(`[session] Failed to save platform map: ${err.message}`);
|
|
10765
10778
|
}
|
|
@@ -10798,17 +10811,17 @@ var init_session_manager = __esm({
|
|
|
10798
10811
|
*/
|
|
10799
10812
|
getSessionFilePath(sessionId) {
|
|
10800
10813
|
const entry = this.index.get(sessionId);
|
|
10801
|
-
if (entry &&
|
|
10802
|
-
const direct =
|
|
10803
|
-
return
|
|
10814
|
+
if (entry && fs14.existsSync(entry.file)) return entry.file;
|
|
10815
|
+
const direct = path15.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
10816
|
+
return fs14.existsSync(direct) ? direct : null;
|
|
10804
10817
|
}
|
|
10805
10818
|
// === Writer 管理 ===
|
|
10806
10819
|
getWriter(sessionId) {
|
|
10807
10820
|
let writer = this.writers.get(sessionId);
|
|
10808
10821
|
if (!writer) {
|
|
10809
10822
|
const existing = this.index.get(sessionId);
|
|
10810
|
-
if (existing &&
|
|
10811
|
-
const existingFileId =
|
|
10823
|
+
if (existing && fs14.existsSync(existing.file)) {
|
|
10824
|
+
const existingFileId = path15.basename(existing.file, ".jsonl");
|
|
10812
10825
|
writer = new SessionWriter(this.sessionsDir, existingFileId);
|
|
10813
10826
|
writer.open(this.config.workspace, sessionId);
|
|
10814
10827
|
} else {
|
|
@@ -10820,7 +10833,7 @@ var init_session_manager = __esm({
|
|
|
10820
10833
|
this.saveIndex();
|
|
10821
10834
|
this.writers.set(sessionId, writer);
|
|
10822
10835
|
this.onWriterCreated?.(writer, sessionId);
|
|
10823
|
-
console.log(`[session] ${existing ? "Resumed" : "New"}: ${sessionId} \u2192 ${
|
|
10836
|
+
console.log(`[session] ${existing ? "Resumed" : "New"}: ${sessionId} \u2192 ${path15.basename(writer.path)}`);
|
|
10824
10837
|
}
|
|
10825
10838
|
return writer;
|
|
10826
10839
|
}
|
|
@@ -10839,7 +10852,7 @@ var init_session_manager = __esm({
|
|
|
10839
10852
|
if (!writer) return null;
|
|
10840
10853
|
try {
|
|
10841
10854
|
this.lastArchiveCheck = Date.now();
|
|
10842
|
-
const stat4 =
|
|
10855
|
+
const stat4 = fs14.statSync(writer.path);
|
|
10843
10856
|
if (stat4.size < threshold) return null;
|
|
10844
10857
|
const sizeMB = (stat4.size / 1024 / 1024).toFixed(1);
|
|
10845
10858
|
const thresholdMB = (threshold / 1024 / 1024).toFixed(1);
|
|
@@ -10848,10 +10861,10 @@ var init_session_manager = __esm({
|
|
|
10848
10861
|
if (archivedPath) {
|
|
10849
10862
|
this.index.set(sessionId, { file: writer.path, updatedAt: Date.now() });
|
|
10850
10863
|
this.saveIndex();
|
|
10851
|
-
const newSize =
|
|
10864
|
+
const newSize = fs14.statSync(writer.path).size;
|
|
10852
10865
|
const oldSizeMB = (stat4.size / 1024 / 1024).toFixed(1);
|
|
10853
|
-
console.log(`[session] Archive complete: ${
|
|
10854
|
-
const fileId =
|
|
10866
|
+
console.log(`[session] Archive complete: ${path15.basename(archivedPath)} (${oldSizeMB}MB) \u2192 new JSONL created (${newSize} bytes)`);
|
|
10867
|
+
const fileId = path15.basename(writer.path).replace(/\.jsonl$/, "");
|
|
10855
10868
|
this.purgeOldArchives(fileId, 3);
|
|
10856
10869
|
return archivedPath;
|
|
10857
10870
|
}
|
|
@@ -10867,15 +10880,15 @@ var init_session_manager = __esm({
|
|
|
10867
10880
|
purgeOldArchives(sessionId, keepCount = 3) {
|
|
10868
10881
|
try {
|
|
10869
10882
|
const dir = this.sessionsDir;
|
|
10870
|
-
if (!
|
|
10871
|
-
const allFiles =
|
|
10883
|
+
if (!fs14.existsSync(dir)) return;
|
|
10884
|
+
const allFiles = fs14.readdirSync(dir);
|
|
10872
10885
|
const archiveFiles = allFiles.filter((f) => {
|
|
10873
10886
|
if (!f.startsWith(sessionId)) return false;
|
|
10874
10887
|
return f.includes(".archived.") || f.includes(".compaction.");
|
|
10875
10888
|
}).map((f) => ({
|
|
10876
10889
|
name: f,
|
|
10877
|
-
path:
|
|
10878
|
-
mtime:
|
|
10890
|
+
path: path15.join(dir, f),
|
|
10891
|
+
mtime: fs14.statSync(path15.join(dir, f)).mtimeMs
|
|
10879
10892
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
10880
10893
|
console.log(`[session] purgeOldArchives: sessionId=${sessionId.substring(0, 8)}... found=${archiveFiles.length} keep=${keepCount}`);
|
|
10881
10894
|
if (archiveFiles.length <= keepCount) return;
|
|
@@ -10885,7 +10898,7 @@ var init_session_manager = __esm({
|
|
|
10885
10898
|
console.log(`[session] Skipping archived (kept for history): ${f.name}`);
|
|
10886
10899
|
continue;
|
|
10887
10900
|
}
|
|
10888
|
-
|
|
10901
|
+
fs14.unlinkSync(f.path);
|
|
10889
10902
|
console.log(`[session] Purged old archive: ${f.name}`);
|
|
10890
10903
|
}
|
|
10891
10904
|
if (toDelete.length > 0) {
|
|
@@ -10934,29 +10947,29 @@ var init_session_manager = __esm({
|
|
|
10934
10947
|
/** 列出 session 的所有文件(当前 + 归档),按修改时间排序 */
|
|
10935
10948
|
findAllSessionFiles(sessionId) {
|
|
10936
10949
|
const results = [];
|
|
10937
|
-
const mainFile =
|
|
10938
|
-
if (
|
|
10950
|
+
const mainFile = path15.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
10951
|
+
if (fs14.existsSync(mainFile)) {
|
|
10939
10952
|
results.push(mainFile);
|
|
10940
10953
|
}
|
|
10941
|
-
if (
|
|
10942
|
-
const compactionFiles =
|
|
10954
|
+
if (fs14.existsSync(this.sessionsDir)) {
|
|
10955
|
+
const compactionFiles = fs14.readdirSync(this.sessionsDir).filter((f) => f.startsWith(`${sessionId}.jsonl.compaction.`)).map((f) => ({
|
|
10943
10956
|
name: f,
|
|
10944
|
-
path:
|
|
10945
|
-
mtime:
|
|
10957
|
+
path: path15.join(this.sessionsDir, f),
|
|
10958
|
+
mtime: fs14.statSync(path15.join(this.sessionsDir, f)).mtimeMs
|
|
10946
10959
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
10947
10960
|
if (compactionFiles.length > 0) {
|
|
10948
10961
|
results.push(compactionFiles[0].path);
|
|
10949
10962
|
}
|
|
10950
10963
|
}
|
|
10951
10964
|
results.sort((a, b) => {
|
|
10952
|
-
const ta =
|
|
10953
|
-
const tb =
|
|
10965
|
+
const ta = fs14.statSync(a).mtimeMs;
|
|
10966
|
+
const tb = fs14.statSync(b).mtimeMs;
|
|
10954
10967
|
return ta - tb;
|
|
10955
10968
|
});
|
|
10956
10969
|
return results;
|
|
10957
10970
|
}
|
|
10958
10971
|
async findSessionFiles(sessionId) {
|
|
10959
|
-
if (!
|
|
10972
|
+
if (!fs14.existsSync(this.sessionsDir)) {
|
|
10960
10973
|
console.log(`[session:find] SESSIONS_DIR not found: ${this.sessionsDir}`);
|
|
10961
10974
|
return [];
|
|
10962
10975
|
}
|
|
@@ -10968,15 +10981,15 @@ var init_session_manager = __esm({
|
|
|
10968
10981
|
return mappedFiles;
|
|
10969
10982
|
}
|
|
10970
10983
|
const indexedEntry = this.index.get(mappedId);
|
|
10971
|
-
if (indexedEntry &&
|
|
10972
|
-
const fileUuid =
|
|
10984
|
+
if (indexedEntry && fs14.existsSync(indexedEntry.file)) {
|
|
10985
|
+
const fileUuid = path15.basename(indexedEntry.file, ".jsonl");
|
|
10973
10986
|
return this.findAllSessionFiles(fileUuid);
|
|
10974
10987
|
}
|
|
10975
10988
|
}
|
|
10976
10989
|
const allFiles = this.findAllSessionFiles(sessionId);
|
|
10977
10990
|
if (allFiles.length > 0) {
|
|
10978
10991
|
const labels = allFiles.map((f) => {
|
|
10979
|
-
const base =
|
|
10992
|
+
const base = path15.basename(f);
|
|
10980
10993
|
return base.endsWith(".jsonl") ? base : `${base} (archived)`;
|
|
10981
10994
|
});
|
|
10982
10995
|
console.log(`[session:find] Found ${allFiles.length} file(s) for ${sessionId}: ${labels.join(", ")}`);
|
|
@@ -10984,9 +10997,9 @@ var init_session_manager = __esm({
|
|
|
10984
10997
|
}
|
|
10985
10998
|
const indexed = this.index.get(sessionId);
|
|
10986
10999
|
if (indexed) {
|
|
10987
|
-
console.log(`[session:find] Index hit: ${sessionId} \u2192 ${indexed.file} (exists=${
|
|
10988
|
-
if (
|
|
10989
|
-
return this.findAllSessionFiles(
|
|
11000
|
+
console.log(`[session:find] Index hit: ${sessionId} \u2192 ${indexed.file} (exists=${fs14.existsSync(indexed.file)})`);
|
|
11001
|
+
if (fs14.existsSync(indexed.file)) {
|
|
11002
|
+
return this.findAllSessionFiles(path15.basename(indexed.file, ".jsonl"));
|
|
10990
11003
|
}
|
|
10991
11004
|
} else {
|
|
10992
11005
|
console.log(`[session:find] Index miss: ${sessionId} (index has ${this.index.size} entries)`);
|
|
@@ -11015,8 +11028,8 @@ var init_session_manager = __esm({
|
|
|
11015
11028
|
return [];
|
|
11016
11029
|
}
|
|
11017
11030
|
files.sort((a, b) => {
|
|
11018
|
-
const ta =
|
|
11019
|
-
const tb =
|
|
11031
|
+
const ta = fs14.statSync(a).mtimeMs;
|
|
11032
|
+
const tb = fs14.statSync(b).mtimeMs;
|
|
11020
11033
|
return ta - tb;
|
|
11021
11034
|
});
|
|
11022
11035
|
const latestFile = files[files.length - 1];
|
|
@@ -11024,7 +11037,7 @@ var init_session_manager = __esm({
|
|
|
11024
11037
|
if (!currentEntry || currentEntry.file !== latestFile) {
|
|
11025
11038
|
this.index.set(sessionId, { file: latestFile, updatedAt: Date.now() });
|
|
11026
11039
|
this.saveIndex();
|
|
11027
|
-
console.log(`[session:restore] Synced index: ${sessionId} \u2192 ${
|
|
11040
|
+
console.log(`[session:restore] Synced index: ${sessionId} \u2192 ${path15.basename(latestFile)}`);
|
|
11028
11041
|
}
|
|
11029
11042
|
const allMessages = [];
|
|
11030
11043
|
for (const file2 of files) {
|
|
@@ -11063,7 +11076,7 @@ var init_session_manager = __esm({
|
|
|
11063
11076
|
if (isAttachmentMessage(m) && m.attachment.type === "relevant_memories") {
|
|
11064
11077
|
for (const mem of m.attachment.memories) {
|
|
11065
11078
|
rawCount++;
|
|
11066
|
-
restoredPaths.add(
|
|
11079
|
+
restoredPaths.add(path15.resolve(mem.path));
|
|
11067
11080
|
}
|
|
11068
11081
|
}
|
|
11069
11082
|
}
|
|
@@ -11095,15 +11108,15 @@ var init_session_manager = __esm({
|
|
|
11095
11108
|
*/
|
|
11096
11109
|
rotateMainSession() {
|
|
11097
11110
|
const entry = this.index.get("main");
|
|
11098
|
-
if (!entry || !
|
|
11099
|
-
const oldFileId =
|
|
11100
|
-
const stat4 =
|
|
11111
|
+
if (!entry || !fs14.existsSync(entry.file)) return;
|
|
11112
|
+
const oldFileId = path15.basename(entry.file, ".jsonl");
|
|
11113
|
+
const stat4 = fs14.statSync(entry.file);
|
|
11101
11114
|
if (stat4.size < 1024) return;
|
|
11102
11115
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-");
|
|
11103
11116
|
const archivedPath = `${entry.file}.archived.${ts}`;
|
|
11104
|
-
|
|
11117
|
+
fs14.renameSync(entry.file, archivedPath);
|
|
11105
11118
|
const sizeMB = (stat4.size / 1024 / 1024).toFixed(1);
|
|
11106
|
-
console.log(`[session] Archived: ${
|
|
11119
|
+
console.log(`[session] Archived: ${path15.basename(entry.file)} \u2192 ${path15.basename(archivedPath)} (${sizeMB}MB)`);
|
|
11107
11120
|
const newWriter = new SessionWriter(this.sessionsDir);
|
|
11108
11121
|
newWriter.open(this.config.workspace, "main");
|
|
11109
11122
|
newWriter.writeModelChange(this.config.providerId, this.config.model);
|
|
@@ -11112,7 +11125,7 @@ var init_session_manager = __esm({
|
|
|
11112
11125
|
this.index.set("main", { file: newPath, updatedAt: Date.now() });
|
|
11113
11126
|
this.saveIndex();
|
|
11114
11127
|
this.purgeOldArchives(oldFileId, 3);
|
|
11115
|
-
console.log(`[session] Rotated main: ${oldFileId}.jsonl \u2192 ${
|
|
11128
|
+
console.log(`[session] Rotated main: ${oldFileId}.jsonl \u2192 ${path15.basename(newPath)}`);
|
|
11116
11129
|
}
|
|
11117
11130
|
// === 迁移 ===
|
|
11118
11131
|
/** 迁移旧索引:session-index.json 里有 "discord:xxx" 格式的 key 时,生成 UUID 替换 */
|
|
@@ -11177,15 +11190,15 @@ var init_session_manager = __esm({
|
|
|
11177
11190
|
});
|
|
11178
11191
|
|
|
11179
11192
|
// src/tools/read.ts
|
|
11180
|
-
import * as
|
|
11181
|
-
import * as
|
|
11193
|
+
import * as fs15 from "node:fs";
|
|
11194
|
+
import * as path16 from "node:path";
|
|
11182
11195
|
function isBlockedDevicePath(filePath) {
|
|
11183
11196
|
if (BLOCKED_DEVICE_PATHS.has(filePath)) return true;
|
|
11184
11197
|
if (filePath.startsWith("/proc/") && (filePath.endsWith("/fd/0") || filePath.endsWith("/fd/1") || filePath.endsWith("/fd/2"))) return true;
|
|
11185
11198
|
return false;
|
|
11186
11199
|
}
|
|
11187
11200
|
function checkReadLoop(filePath, offset, limit) {
|
|
11188
|
-
const stat4 =
|
|
11201
|
+
const stat4 = fs15.statSync(filePath);
|
|
11189
11202
|
const mtimeMs = stat4.mtimeMs;
|
|
11190
11203
|
const prev = readHistory.get(filePath);
|
|
11191
11204
|
if (prev && prev.offset === offset && prev.limit === limit && prev.mtimeMs === mtimeMs) {
|
|
@@ -11199,19 +11212,19 @@ function checkReadLoop(filePath, offset, limit) {
|
|
|
11199
11212
|
return null;
|
|
11200
11213
|
}
|
|
11201
11214
|
function readFileContent(filePath) {
|
|
11202
|
-
const fd =
|
|
11215
|
+
const fd = fs15.openSync(filePath, "r");
|
|
11203
11216
|
const bom = Buffer.alloc(2);
|
|
11204
|
-
|
|
11205
|
-
|
|
11217
|
+
fs15.readSync(fd, bom, 0, 2, 0);
|
|
11218
|
+
fs15.closeSync(fd);
|
|
11206
11219
|
let encoding = "utf8";
|
|
11207
11220
|
if (bom[0] === 255 && bom[1] === 254) {
|
|
11208
11221
|
encoding = "utf16le";
|
|
11209
11222
|
}
|
|
11210
|
-
const stat4 =
|
|
11223
|
+
const stat4 = fs15.statSync(filePath);
|
|
11211
11224
|
if (stat4.size > MAX_FILE_SIZE) {
|
|
11212
11225
|
throw new Error(`\u6587\u4EF6\u592A\u5927 (${(stat4.size / 1024).toFixed(1)}KB)\uFF0C\u8D85\u8FC7 ${MAX_FILE_SIZE / 1024}KB \u9650\u5236\u3002\u8BF7\u4F7F\u7528 offset + limit \u5206\u6BB5\u8BFB\u53D6\u3002`);
|
|
11213
11226
|
}
|
|
11214
|
-
const raw =
|
|
11227
|
+
const raw = fs15.readFileSync(filePath, encoding);
|
|
11215
11228
|
const content = raw.toString().replaceAll("\r\n", "\n");
|
|
11216
11229
|
return { content, encoding };
|
|
11217
11230
|
}
|
|
@@ -11353,11 +11366,11 @@ Usage:
|
|
|
11353
11366
|
} catch (e) {
|
|
11354
11367
|
return { content: e.message, isError: true };
|
|
11355
11368
|
}
|
|
11356
|
-
if (!
|
|
11369
|
+
if (!fs15.existsSync(filePath)) {
|
|
11357
11370
|
return { content: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`, isError: true };
|
|
11358
11371
|
}
|
|
11359
|
-
const stat4 =
|
|
11360
|
-
const baseName =
|
|
11372
|
+
const stat4 = fs15.statSync(filePath);
|
|
11373
|
+
const baseName = path16.basename(filePath).toUpperCase();
|
|
11361
11374
|
if (BLOCKED_BASENAMES.has(baseName)) {
|
|
11362
11375
|
return { content: `\u8BBE\u5907\u6587\u4EF6\u4E0D\u652F\u6301\u8BFB\u53D6: ${filePath}`, isError: true };
|
|
11363
11376
|
}
|
|
@@ -11365,11 +11378,11 @@ Usage:
|
|
|
11365
11378
|
return { content: `\u8BBE\u5907\u6587\u4EF6\u4F1A\u963B\u585E\u6216\u4EA7\u751F\u65E0\u9650\u8F93\u51FA: ${filePath}`, isError: true };
|
|
11366
11379
|
}
|
|
11367
11380
|
if (stat4.isDirectory()) {
|
|
11368
|
-
const entries2 =
|
|
11381
|
+
const entries2 = fs15.readdirSync(filePath);
|
|
11369
11382
|
const items = entries2.map((e) => {
|
|
11370
|
-
const full =
|
|
11383
|
+
const full = path16.join(filePath, e);
|
|
11371
11384
|
try {
|
|
11372
|
-
const s =
|
|
11385
|
+
const s = fs15.statSync(full);
|
|
11373
11386
|
return s.isDirectory() ? `${e}/` : e;
|
|
11374
11387
|
} catch {
|
|
11375
11388
|
return e;
|
|
@@ -11378,7 +11391,7 @@ Usage:
|
|
|
11378
11391
|
return { content: `\u76EE\u5F55 (${entries2.length} \u9879):
|
|
11379
11392
|
${items.join("\n")}` };
|
|
11380
11393
|
}
|
|
11381
|
-
const ext =
|
|
11394
|
+
const ext = path16.extname(filePath).toLowerCase();
|
|
11382
11395
|
if (BINARY_EXTENSIONS.has(ext)) {
|
|
11383
11396
|
return { content: `\u4E8C\u8FDB\u5236\u6587\u4EF6\u4E0D\u652F\u6301\u8BFB\u53D6 (${ext}): ${filePath}`, isError: true };
|
|
11384
11397
|
}
|
|
@@ -11425,22 +11438,22 @@ ${result}` : result };
|
|
|
11425
11438
|
});
|
|
11426
11439
|
|
|
11427
11440
|
// src/tools/write.ts
|
|
11428
|
-
import * as
|
|
11429
|
-
import * as
|
|
11441
|
+
import * as fs16 from "node:fs";
|
|
11442
|
+
import * as path17 from "node:path";
|
|
11430
11443
|
function isBlockedPath(filePath) {
|
|
11431
11444
|
return BLOCKED_PATTERNS.some((p) => p.test(filePath));
|
|
11432
11445
|
}
|
|
11433
11446
|
function atomicWrite(filePath, content) {
|
|
11434
11447
|
const tmpPath = filePath + ".tmp." + Date.now() + ".write";
|
|
11435
|
-
|
|
11448
|
+
fs16.writeFileSync(tmpPath, content, "utf-8");
|
|
11436
11449
|
try {
|
|
11437
|
-
|
|
11450
|
+
fs16.renameSync(tmpPath, filePath);
|
|
11438
11451
|
} catch (e) {
|
|
11439
11452
|
try {
|
|
11440
|
-
|
|
11453
|
+
fs16.unlinkSync(tmpPath);
|
|
11441
11454
|
} catch {
|
|
11442
11455
|
}
|
|
11443
|
-
|
|
11456
|
+
fs16.writeFileSync(filePath, content, "utf-8");
|
|
11444
11457
|
}
|
|
11445
11458
|
}
|
|
11446
11459
|
function simpleDiff(oldContent, newContent) {
|
|
@@ -11534,15 +11547,15 @@ Usage:
|
|
|
11534
11547
|
}
|
|
11535
11548
|
const rawContent = args.content;
|
|
11536
11549
|
const content = rawContent.replaceAll("\r\n", "\n");
|
|
11537
|
-
if (
|
|
11550
|
+
if (fs16.existsSync(filePath) && fs16.statSync(filePath).isDirectory()) {
|
|
11538
11551
|
return { content: `\u8DEF\u5F84\u662F\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6: ${filePath}`, isError: true };
|
|
11539
11552
|
}
|
|
11540
11553
|
let oldContent = null;
|
|
11541
11554
|
let isCreate = true;
|
|
11542
|
-
if (
|
|
11555
|
+
if (fs16.existsSync(filePath)) {
|
|
11543
11556
|
isCreate = false;
|
|
11544
11557
|
try {
|
|
11545
|
-
oldContent =
|
|
11558
|
+
oldContent = fs16.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
|
|
11546
11559
|
} catch {
|
|
11547
11560
|
isCreate = true;
|
|
11548
11561
|
}
|
|
@@ -11558,10 +11571,10 @@ Usage:
|
|
|
11558
11571
|
isError: true
|
|
11559
11572
|
};
|
|
11560
11573
|
}
|
|
11561
|
-
const currentStat =
|
|
11574
|
+
const currentStat = fs16.statSync(filePath);
|
|
11562
11575
|
const lastWriteTime = Math.floor(currentStat.mtimeMs);
|
|
11563
11576
|
if (lastWriteTime > readState.timestamp) {
|
|
11564
|
-
const currentContent =
|
|
11577
|
+
const currentContent = fs16.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
|
|
11565
11578
|
if (currentContent !== oldContent) {
|
|
11566
11579
|
return {
|
|
11567
11580
|
content: `\u6587\u4EF6\u5728\u8BFB\u53D6\u540E\u88AB\u4FEE\u6539\u3002\u8BF7\u5148\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\u518D\u5199\u5165: ${filePath}`,
|
|
@@ -11570,9 +11583,9 @@ Usage:
|
|
|
11570
11583
|
}
|
|
11571
11584
|
}
|
|
11572
11585
|
}
|
|
11573
|
-
const dir =
|
|
11586
|
+
const dir = path17.dirname(filePath);
|
|
11574
11587
|
try {
|
|
11575
|
-
|
|
11588
|
+
fs16.mkdirSync(dir, { recursive: true });
|
|
11576
11589
|
} catch (e) {
|
|
11577
11590
|
return { content: `\u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55: ${dir} \u2014 ${e.message}`, isError: true };
|
|
11578
11591
|
}
|
|
@@ -11581,11 +11594,11 @@ Usage:
|
|
|
11581
11594
|
} catch (e) {
|
|
11582
11595
|
return { content: `\u5199\u5165\u5931\u8D25: ${e.message}`, isError: true };
|
|
11583
11596
|
}
|
|
11584
|
-
readFileState.set(filePath, { timestamp:
|
|
11597
|
+
readFileState.set(filePath, { timestamp: fs16.statSync(filePath).mtimeMs });
|
|
11585
11598
|
const action = isCreate ? "\u521B\u5EFA" : "\u66F4\u65B0";
|
|
11586
11599
|
const lines = content.split("\n").length;
|
|
11587
11600
|
const chars = content.length;
|
|
11588
|
-
const stat4 =
|
|
11601
|
+
const stat4 = fs16.statSync(filePath);
|
|
11589
11602
|
let diff = "";
|
|
11590
11603
|
if (!isCreate && oldContent !== null) {
|
|
11591
11604
|
diff = `
|
|
@@ -11604,8 +11617,8 @@ ${simpleDiff(oldContent, content)}`;
|
|
|
11604
11617
|
});
|
|
11605
11618
|
|
|
11606
11619
|
// src/tools/edit.ts
|
|
11607
|
-
import * as
|
|
11608
|
-
import * as
|
|
11620
|
+
import * as fs17 from "node:fs";
|
|
11621
|
+
import * as path18 from "node:path";
|
|
11609
11622
|
function normalizeQuotes(str) {
|
|
11610
11623
|
return str.replaceAll(LEFT_SINGLE_CURLY, "'").replaceAll(RIGHT_SINGLE_CURLY, "'").replaceAll(LEFT_DOUBLE_CURLY, '"').replaceAll(RIGHT_DOUBLE_CURLY, '"');
|
|
11611
11624
|
}
|
|
@@ -11758,7 +11771,7 @@ Usage:
|
|
|
11758
11771
|
}
|
|
11759
11772
|
let fileContent = null;
|
|
11760
11773
|
try {
|
|
11761
|
-
const stat4 =
|
|
11774
|
+
const stat4 = fs17.statSync(filePath);
|
|
11762
11775
|
if (stat4.isDirectory()) {
|
|
11763
11776
|
return { content: `\u8DEF\u5F84\u662F\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6: ${filePath}`, isError: true };
|
|
11764
11777
|
}
|
|
@@ -11768,21 +11781,21 @@ Usage:
|
|
|
11768
11781
|
} catch (e) {
|
|
11769
11782
|
if (e.code === "ENOENT") {
|
|
11770
11783
|
if (oldString === "") {
|
|
11771
|
-
const dir =
|
|
11772
|
-
|
|
11773
|
-
|
|
11774
|
-
readFileState.set(filePath, { timestamp:
|
|
11784
|
+
const dir = path18.dirname(filePath);
|
|
11785
|
+
fs17.mkdirSync(dir, { recursive: true });
|
|
11786
|
+
fs17.writeFileSync(filePath, newString, "utf-8");
|
|
11787
|
+
readFileState.set(filePath, { timestamp: fs17.statSync(filePath).mtimeMs });
|
|
11775
11788
|
return { content: `\u521B\u5EFA\u6587\u4EF6: ${filePath} (${newString.split("\n").length} \u884C)` };
|
|
11776
11789
|
}
|
|
11777
11790
|
return { content: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`, isError: true };
|
|
11778
11791
|
}
|
|
11779
11792
|
throw e;
|
|
11780
11793
|
}
|
|
11781
|
-
const rawContent =
|
|
11794
|
+
const rawContent = fs17.readFileSync(filePath, "utf-8");
|
|
11782
11795
|
fileContent = rawContent.replaceAll("\r\n", "\n");
|
|
11783
11796
|
if (oldString === "" && fileContent.trim() === "") {
|
|
11784
|
-
|
|
11785
|
-
readFileState.set(filePath, { timestamp:
|
|
11797
|
+
fs17.writeFileSync(filePath, newString, "utf-8");
|
|
11798
|
+
readFileState.set(filePath, { timestamp: fs17.statSync(filePath).mtimeMs });
|
|
11786
11799
|
return { content: `\u5199\u5165\u7A7A\u6587\u4EF6: ${filePath} (${newString.split("\n").length} \u884C)` };
|
|
11787
11800
|
}
|
|
11788
11801
|
const readState = readFileState.get(filePath);
|
|
@@ -11792,11 +11805,11 @@ Usage:
|
|
|
11792
11805
|
isError: true
|
|
11793
11806
|
};
|
|
11794
11807
|
}
|
|
11795
|
-
const currentStat =
|
|
11808
|
+
const currentStat = fs17.statSync(filePath);
|
|
11796
11809
|
const lastWriteTime = Math.floor(currentStat.mtimeMs);
|
|
11797
11810
|
if (lastWriteTime > readState.timestamp) {
|
|
11798
11811
|
if (fileContent !== rawContent.replaceAll("\r\n", "\n")) {
|
|
11799
|
-
if (fileContent !==
|
|
11812
|
+
if (fileContent !== fs17.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n")) {
|
|
11800
11813
|
return {
|
|
11801
11814
|
content: `\u6587\u4EF6\u5728\u8BFB\u53D6\u540E\u88AB\u4FEE\u6539\u3002\u8BF7\u5148\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\u518D\u7F16\u8F91: ${filePath}`,
|
|
11802
11815
|
isError: true
|
|
@@ -11828,8 +11841,8 @@ ${preview}
|
|
|
11828
11841
|
const actualNewString = preserveQuoteStyle(oldString, actualOldString, newString);
|
|
11829
11842
|
const diffView = generateEditDiff(fileContent, actualOldString, actualNewString);
|
|
11830
11843
|
const newContent = applyEditToFile(fileContent, actualOldString, actualNewString, replaceAll);
|
|
11831
|
-
|
|
11832
|
-
readFileState.set(filePath, { timestamp:
|
|
11844
|
+
fs17.writeFileSync(filePath, newContent, "utf-8");
|
|
11845
|
+
readFileState.set(filePath, { timestamp: fs17.statSync(filePath).mtimeMs });
|
|
11833
11846
|
const strategy = actualOldString === oldString ? "\u7CBE\u786E\u5339\u914D" : "\u5F15\u53F7\u89C4\u8303\u5316\u5339\u914D";
|
|
11834
11847
|
const count = replaceAll ? matchCount : 1;
|
|
11835
11848
|
const diff = `${oldString.length}\u2192${newString.length}\u5B57\u7B26`;
|
|
@@ -11846,8 +11859,8 @@ ${diffView}`
|
|
|
11846
11859
|
});
|
|
11847
11860
|
|
|
11848
11861
|
// src/tools/glob.ts
|
|
11849
|
-
import * as
|
|
11850
|
-
import * as
|
|
11862
|
+
import * as fs18 from "node:fs";
|
|
11863
|
+
import * as path19 from "node:path";
|
|
11851
11864
|
function globMatch(pattern, filename) {
|
|
11852
11865
|
const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
11853
11866
|
try {
|
|
@@ -11867,18 +11880,18 @@ function findFiles(dir, pattern, limit, baseDir) {
|
|
|
11867
11880
|
}
|
|
11868
11881
|
let entries2;
|
|
11869
11882
|
try {
|
|
11870
|
-
entries2 =
|
|
11883
|
+
entries2 = fs18.readdirSync(currentDir, { withFileTypes: true });
|
|
11871
11884
|
} catch {
|
|
11872
11885
|
return;
|
|
11873
11886
|
}
|
|
11874
11887
|
for (const entry of entries2) {
|
|
11875
11888
|
if (truncated) return;
|
|
11876
|
-
const fullPath =
|
|
11889
|
+
const fullPath = path19.join(currentDir, entry.name);
|
|
11877
11890
|
if (entry.isDirectory()) {
|
|
11878
11891
|
if (VCS_DIRS.has(entry.name)) continue;
|
|
11879
11892
|
walk(fullPath);
|
|
11880
11893
|
} else if (entry.isFile()) {
|
|
11881
|
-
const relativePath =
|
|
11894
|
+
const relativePath = path19.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
11882
11895
|
const patternsToTry = [pattern];
|
|
11883
11896
|
if (pattern.startsWith("**/")) {
|
|
11884
11897
|
patternsToTry.push(pattern.slice(3));
|
|
@@ -11888,7 +11901,7 @@ function findFiles(dir, pattern, limit, baseDir) {
|
|
|
11888
11901
|
);
|
|
11889
11902
|
if (matched) {
|
|
11890
11903
|
try {
|
|
11891
|
-
const stat4 =
|
|
11904
|
+
const stat4 = fs18.statSync(fullPath);
|
|
11892
11905
|
results.push({ path: fullPath, mtimeMs: stat4.mtimeMs });
|
|
11893
11906
|
} catch {
|
|
11894
11907
|
}
|
|
@@ -11905,7 +11918,7 @@ function findFiles(dir, pattern, limit, baseDir) {
|
|
|
11905
11918
|
};
|
|
11906
11919
|
}
|
|
11907
11920
|
function toRelativePath(absolutePath, cwd) {
|
|
11908
|
-
if (absolutePath.startsWith(cwd +
|
|
11921
|
+
if (absolutePath.startsWith(cwd + path19.sep)) {
|
|
11909
11922
|
return absolutePath.slice(cwd.length + 1);
|
|
11910
11923
|
}
|
|
11911
11924
|
return absolutePath;
|
|
@@ -11938,10 +11951,10 @@ var init_glob = __esm({
|
|
|
11938
11951
|
const searchPath = args.path ? resolvePath(args.path, ctx.workspace) : ctx.workspace;
|
|
11939
11952
|
const pattern = args.pattern;
|
|
11940
11953
|
const limit = args.limit || DEFAULT_LIMIT;
|
|
11941
|
-
if (!
|
|
11954
|
+
if (!fs18.existsSync(searchPath)) {
|
|
11942
11955
|
return { content: `\u76EE\u5F55\u4E0D\u5B58\u5728: ${searchPath}`, isError: true };
|
|
11943
11956
|
}
|
|
11944
|
-
if (!
|
|
11957
|
+
if (!fs18.statSync(searchPath).isDirectory()) {
|
|
11945
11958
|
return { content: `\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${searchPath}`, isError: true };
|
|
11946
11959
|
}
|
|
11947
11960
|
const start = Date.now();
|
|
@@ -11965,7 +11978,7 @@ ${filenames.join("\n")}${truncatedNote}`
|
|
|
11965
11978
|
|
|
11966
11979
|
// src/tools/grep.ts
|
|
11967
11980
|
import { execFile } from "node:child_process";
|
|
11968
|
-
import * as
|
|
11981
|
+
import * as path20 from "node:path";
|
|
11969
11982
|
function ripGrep(args, searchPath, signal) {
|
|
11970
11983
|
return new Promise((resolve12) => {
|
|
11971
11984
|
const fullArgs = [...args, searchPath];
|
|
@@ -11997,7 +12010,7 @@ function applyHeadLimit(items, limit, offset = 0) {
|
|
|
11997
12010
|
};
|
|
11998
12011
|
}
|
|
11999
12012
|
function toRelativePath2(absolutePath, cwd) {
|
|
12000
|
-
if (absolutePath.startsWith(cwd +
|
|
12013
|
+
if (absolutePath.startsWith(cwd + path20.sep)) {
|
|
12001
12014
|
return absolutePath.slice(cwd.length + 1);
|
|
12002
12015
|
}
|
|
12003
12016
|
if (absolutePath.startsWith(cwd)) {
|
|
@@ -13247,7 +13260,7 @@ async function acquireLock(inboxPath) {
|
|
|
13247
13260
|
for (let i = 0; i < LOCK_RETRIES; i++) {
|
|
13248
13261
|
if (await isLockStale(lockPath2)) {
|
|
13249
13262
|
try {
|
|
13250
|
-
await import("node:fs/promises").then((
|
|
13263
|
+
await import("node:fs/promises").then((fs44) => fs44.rm(lockPath2, { force: true }));
|
|
13251
13264
|
} catch {
|
|
13252
13265
|
}
|
|
13253
13266
|
}
|
|
@@ -13255,7 +13268,7 @@ async function acquireLock(inboxPath) {
|
|
|
13255
13268
|
await writeFile2(lockPath2, `${process.pid}-${Date.now()}`, { encoding: "utf-8", flag: "wx" });
|
|
13256
13269
|
return async () => {
|
|
13257
13270
|
try {
|
|
13258
|
-
await import("node:fs/promises").then((
|
|
13271
|
+
await import("node:fs/promises").then((fs44) => fs44.rm(lockPath2, { force: true }));
|
|
13259
13272
|
} catch {
|
|
13260
13273
|
}
|
|
13261
13274
|
};
|
|
@@ -14498,12 +14511,12 @@ Examples:
|
|
|
14498
14511
|
});
|
|
14499
14512
|
|
|
14500
14513
|
// src/tools/msg-husband.ts
|
|
14501
|
-
import
|
|
14502
|
-
import
|
|
14514
|
+
import fs19 from "node:fs";
|
|
14515
|
+
import path21 from "node:path";
|
|
14503
14516
|
function getHusbandFeishuId(workspace) {
|
|
14504
|
-
const contactsPath =
|
|
14517
|
+
const contactsPath = path21.join(workspace, "prompts", "contacts.md");
|
|
14505
14518
|
try {
|
|
14506
|
-
const text =
|
|
14519
|
+
const text = fs19.readFileSync(contactsPath, "utf-8");
|
|
14507
14520
|
const m = text.match(/\|\s*翀哥\s*\|\s*(ou_[a-f0-9]+)\s*\|/);
|
|
14508
14521
|
return m ? m[1] : null;
|
|
14509
14522
|
} catch {
|
|
@@ -14656,8 +14669,8 @@ Examples:
|
|
|
14656
14669
|
if (!to && !resolvedChannelId) {
|
|
14657
14670
|
return { content: "to \u548C channel_id \u4E0D\u80FD\u540C\u65F6\u4E3A\u7A7A\uFF0C\u4E14\u6CA1\u6709\u53EF\u7528\u7684\u6765\u6E90\u9891\u9053", isError: true };
|
|
14658
14671
|
}
|
|
14659
|
-
const
|
|
14660
|
-
if (!
|
|
14672
|
+
const fs44 = await import("node:fs");
|
|
14673
|
+
if (!fs44.existsSync(filePath)) {
|
|
14661
14674
|
return { content: `\u53D1\u9001\u5931\u8D25: \u6587\u4EF6\u4E0D\u5B58\u5728 ${filePath}`, isError: true };
|
|
14662
14675
|
}
|
|
14663
14676
|
const toIds = to ? to.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
@@ -14685,7 +14698,7 @@ Examples:
|
|
|
14685
14698
|
md: "text/markdown"
|
|
14686
14699
|
};
|
|
14687
14700
|
const mimeType = mimeTypeMap[ext] || "application/octet-stream";
|
|
14688
|
-
const stat4 =
|
|
14701
|
+
const stat4 = fs44.statSync(filePath);
|
|
14689
14702
|
const sizeMB = stat4.size / 1024 / 1024;
|
|
14690
14703
|
if (sizeMB > 25) {
|
|
14691
14704
|
return { content: `\u53D1\u9001\u5931\u8D25: \u6587\u4EF6 ${sizeMB.toFixed(1)}MB \u8D85\u8FC7 Discord 25MB \u9650\u5236`, isError: true };
|
|
@@ -14714,8 +14727,8 @@ Examples:
|
|
|
14714
14727
|
});
|
|
14715
14728
|
|
|
14716
14729
|
// src/tools/my-eyes.ts
|
|
14717
|
-
import * as
|
|
14718
|
-
import * as
|
|
14730
|
+
import * as fs20 from "node:fs";
|
|
14731
|
+
import * as path22 from "node:path";
|
|
14719
14732
|
function extractUsage(data) {
|
|
14720
14733
|
try {
|
|
14721
14734
|
const u = data?.usage ?? data?.usageMetadata;
|
|
@@ -14730,9 +14743,9 @@ function extractUsage(data) {
|
|
|
14730
14743
|
}
|
|
14731
14744
|
}
|
|
14732
14745
|
function resolveLatestImage(specifiedPath, mediaDir) {
|
|
14733
|
-
if (specifiedPath &&
|
|
14734
|
-
if (!
|
|
14735
|
-
const files =
|
|
14746
|
+
if (specifiedPath && fs20.existsSync(specifiedPath)) return specifiedPath;
|
|
14747
|
+
if (!fs20.existsSync(mediaDir)) return null;
|
|
14748
|
+
const files = fs20.readdirSync(mediaDir).filter((f) => /\.(jpg|jpeg|png|webp|gif|bmp|mp4|mov)$/i.test(f)).map((f) => ({ name: f, p: path22.join(mediaDir, f), mtime: fs20.statSync(path22.join(mediaDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
14736
14749
|
return files[0]?.p || null;
|
|
14737
14750
|
}
|
|
14738
14751
|
var MIME_MAP, VIDEO_EXT, VIDEO_MAX_BYTES;
|
|
@@ -14780,15 +14793,15 @@ var init_my_eyes = __esm({
|
|
|
14780
14793
|
if (!provider?.streamChat) {
|
|
14781
14794
|
return { content: "Error: provider \u4E0D\u53EF\u7528\u3002", isError: true };
|
|
14782
14795
|
}
|
|
14783
|
-
const mediaDir =
|
|
14796
|
+
const mediaDir = path22.join(ctx.stateDir, "media", "inbound");
|
|
14784
14797
|
const imagePath = resolveLatestImage(args.image_path, mediaDir);
|
|
14785
14798
|
if (!imagePath) {
|
|
14786
14799
|
return { content: "Error: no image found. Provide image_path or ensure media/inbound has images.", isError: true };
|
|
14787
14800
|
}
|
|
14788
14801
|
const rawPrompt = args.prompt?.trim() || "\u63CF\u8FF0\u8FD9\u5F20\u56FE\u7247\u7684\u5185\u5BB9";
|
|
14789
|
-
const ext =
|
|
14802
|
+
const ext = path22.extname(imagePath).toLowerCase();
|
|
14790
14803
|
if (VIDEO_EXT.test(imagePath)) {
|
|
14791
|
-
const stat4 =
|
|
14804
|
+
const stat4 = fs20.statSync(imagePath);
|
|
14792
14805
|
if (stat4.size > VIDEO_MAX_BYTES) {
|
|
14793
14806
|
return { content: `Error: video too large (${(stat4.size / 1e6).toFixed(1)}MB > ${(VIDEO_MAX_BYTES / 1e6).toFixed(0)}MB). Compress or trim first.`, isError: true };
|
|
14794
14807
|
}
|
|
@@ -14802,7 +14815,7 @@ var init_my_eyes = __esm({
|
|
|
14802
14815
|
}
|
|
14803
14816
|
const explicit = liveConfig.get("tools.my_eyes.videoBaseUrl");
|
|
14804
14817
|
const baseUrl = explicit || vProviderCfg.baseUrl.replace(/\/anthropic\/?$/, "/v1").replace(/\/$/, "");
|
|
14805
|
-
const vidB64 =
|
|
14818
|
+
const vidB64 = fs20.readFileSync(imagePath).toString("base64");
|
|
14806
14819
|
try {
|
|
14807
14820
|
const res = await fetch(`${baseUrl}/chat/completions`, {
|
|
14808
14821
|
method: "POST",
|
|
@@ -14833,7 +14846,7 @@ var init_my_eyes = __esm({
|
|
|
14833
14846
|
}
|
|
14834
14847
|
}
|
|
14835
14848
|
const mime = MIME_MAP[ext] || "jpeg";
|
|
14836
|
-
const imgB64 =
|
|
14849
|
+
const imgB64 = fs20.readFileSync(imagePath).toString("base64");
|
|
14837
14850
|
const userMsg = {
|
|
14838
14851
|
role: "user",
|
|
14839
14852
|
content: [
|
|
@@ -14868,7 +14881,7 @@ var init_my_eyes = __esm({
|
|
|
14868
14881
|
});
|
|
14869
14882
|
|
|
14870
14883
|
// src/tools/opus-encoder.ts
|
|
14871
|
-
import * as
|
|
14884
|
+
import * as fs21 from "node:fs";
|
|
14872
14885
|
function oggCrc32(buf) {
|
|
14873
14886
|
let crc = 0;
|
|
14874
14887
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -14928,7 +14941,7 @@ async function wavToOggOpusNative(wavPath) {
|
|
|
14928
14941
|
const mod = await import("@discordjs/opus");
|
|
14929
14942
|
const OpusEncoder = mod.OpusEncoder ?? mod.default?.OpusEncoder;
|
|
14930
14943
|
if (!OpusEncoder) throw new Error("@discordjs/opus export shape unexpected");
|
|
14931
|
-
const wav = parseWav(
|
|
14944
|
+
const wav = parseWav(fs21.readFileSync(wavPath));
|
|
14932
14945
|
if (wav.channels !== 1) throw new Error(`unsupported ${wav.channels}ch (need mono)`);
|
|
14933
14946
|
if (!NATIVE_RATES.includes(wav.sampleRate)) throw new Error(`unsupported rate ${wav.sampleRate}`);
|
|
14934
14947
|
if (wav.pcm.length === 0) throw new Error("empty pcm data");
|
|
@@ -14964,7 +14977,7 @@ async function wavToOggOpusNative(wavPath) {
|
|
|
14964
14977
|
}
|
|
14965
14978
|
ogg.page(cur, pageGranule, false, true);
|
|
14966
14979
|
const oggPath = wavPath.replace(/\.wav$/, ".ogg");
|
|
14967
|
-
|
|
14980
|
+
fs21.writeFileSync(oggPath, ogg.finish());
|
|
14968
14981
|
return oggPath;
|
|
14969
14982
|
}
|
|
14970
14983
|
var FRAME_MS, PRESKIP_48K, OPUS_RATE, NATIVE_RATES, BITRATE, CRC_TABLE, OggWriter;
|
|
@@ -15072,8 +15085,8 @@ var init_voice_chat_tts_daemon = __esm({
|
|
|
15072
15085
|
import { execFile as execFile2 } from "node:child_process";
|
|
15073
15086
|
import { createInterface as createInterface2 } from "node:readline";
|
|
15074
15087
|
import { promisify } from "node:util";
|
|
15075
|
-
import * as
|
|
15076
|
-
import * as
|
|
15088
|
+
import * as fs22 from "node:fs";
|
|
15089
|
+
import * as path23 from "node:path";
|
|
15077
15090
|
import * as os4 from "node:os";
|
|
15078
15091
|
function wavDurationSec(buf) {
|
|
15079
15092
|
if (buf.length < 12 || buf.toString("ascii", 0, 4) !== "RIFF" || buf.toString("ascii", 8, 12) !== "WAVE") {
|
|
@@ -15128,8 +15141,8 @@ function resolvePython(configuredPath) {
|
|
|
15128
15141
|
// LOCALAPPDATA 缺席(非 Windows / 精简环境)时**不加这两个候选**:
|
|
15129
15142
|
// 拼出来会是相对路径 'Microsoft/WindowsApps/python.exe',那可能撞上 cwd 里的东西。
|
|
15130
15143
|
...localAppData ? [
|
|
15131
|
-
|
|
15132
|
-
|
|
15144
|
+
path23.join(localAppData, "Microsoft", "WindowsApps", "python3.exe"),
|
|
15145
|
+
path23.join(localAppData, "Microsoft", "WindowsApps", "python.exe")
|
|
15133
15146
|
] : []
|
|
15134
15147
|
];
|
|
15135
15148
|
for (const c of candidates) {
|
|
@@ -15149,8 +15162,8 @@ async function ttsCosyvoice(text, apiKey, model, voice, workspaceId, instruction
|
|
|
15149
15162
|
}
|
|
15150
15163
|
async function ttsCosyvoiceStream(text, cfg, onChunk) {
|
|
15151
15164
|
const { apiKey, model, voice, workspaceId, instruction } = cfg;
|
|
15152
|
-
|
|
15153
|
-
const output =
|
|
15165
|
+
fs22.mkdirSync(VOICE_DIR, { recursive: true });
|
|
15166
|
+
const output = path23.join(VOICE_DIR, `tts_${Date.now()}.wav`);
|
|
15154
15167
|
const script = `
|
|
15155
15168
|
import sys, json, base64, threading
|
|
15156
15169
|
import dashscope
|
|
@@ -15235,7 +15248,7 @@ print('EOS')
|
|
|
15235
15248
|
header.writeUInt16LE(16, 34);
|
|
15236
15249
|
header.write("data", 36);
|
|
15237
15250
|
header.writeUInt32LE(pcm.length, 40);
|
|
15238
|
-
|
|
15251
|
+
fs22.writeFileSync(output, Buffer.concat([header, pcm]));
|
|
15239
15252
|
return output;
|
|
15240
15253
|
}
|
|
15241
15254
|
async function ttsQwen3Local(text, cfg, onChunk) {
|
|
@@ -15287,9 +15300,9 @@ async function ttsQwen3Opus(text, cfg) {
|
|
|
15287
15300
|
const ogg = Buffer.from(await res.arrayBuffer());
|
|
15288
15301
|
if (ogg.length < 20) throw new Error("qwen3-3060 opus: empty output");
|
|
15289
15302
|
const durationMs = parseInt(res.headers.get("x-duration-ms") || "0", 10);
|
|
15290
|
-
|
|
15291
|
-
const oggPath =
|
|
15292
|
-
|
|
15303
|
+
fs22.mkdirSync(VOICE_DIR, { recursive: true });
|
|
15304
|
+
const oggPath = path23.join(VOICE_DIR, `tts_${Date.now()}.ogg`);
|
|
15305
|
+
fs22.writeFileSync(oggPath, ogg);
|
|
15293
15306
|
return { oggPath, durationMs };
|
|
15294
15307
|
}
|
|
15295
15308
|
async function ttsGptsovits(text, c) {
|
|
@@ -15301,8 +15314,8 @@ async function ttsGptsovits(text, c) {
|
|
|
15301
15314
|
"gptsovits \u672A\u914D\u7F6E\uFF1A\u9700\u8981 tools.my_voice \u91CC\u7684 gptsovitsUrl / gptsovitsRefWav / gptsovitsRefText\u3002\u53C2\u8003\u97F3\u9891\u4E0E\u53C2\u8003\u6587\u672C**\u5FC5\u987B\u9010\u5B57\u5BF9\u5E94**\uFF0C\u5426\u5219\u5408\u6210\u51FA\u6765\u7684\u58F0\u97F3\u4F1A\u5E26\u6742\u97F3\uFF080925 \u8E29\u8FC7\u88C1\u574F ref.wav \u7684\u5751\uFF09\u3002"
|
|
15302
15315
|
);
|
|
15303
15316
|
}
|
|
15304
|
-
|
|
15305
|
-
const output =
|
|
15317
|
+
fs22.mkdirSync(VOICE_DIR, { recursive: true });
|
|
15318
|
+
const output = path23.join(VOICE_DIR, `tts_${Date.now()}.wav`);
|
|
15306
15319
|
const params = new URLSearchParams({
|
|
15307
15320
|
text,
|
|
15308
15321
|
text_language: "zh",
|
|
@@ -15313,12 +15326,12 @@ async function ttsGptsovits(text, c) {
|
|
|
15313
15326
|
const res = await fetch(`${url}/?${params}`);
|
|
15314
15327
|
if (!res.ok) throw new Error(`GPT-SoVITS API ${res.status}`);
|
|
15315
15328
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
15316
|
-
|
|
15329
|
+
fs22.writeFileSync(output, buf);
|
|
15317
15330
|
return output;
|
|
15318
15331
|
}
|
|
15319
15332
|
async function ttsEdge(text) {
|
|
15320
|
-
|
|
15321
|
-
const output =
|
|
15333
|
+
fs22.mkdirSync(VOICE_DIR, { recursive: true });
|
|
15334
|
+
const output = path23.join(VOICE_DIR, `tts_${Date.now()}.mp3`);
|
|
15322
15335
|
const script = `
|
|
15323
15336
|
import asyncio, edge_tts, sys
|
|
15324
15337
|
async def main():
|
|
@@ -15356,8 +15369,8 @@ async function synthQwen3(text, _sink) {
|
|
|
15356
15369
|
const pcmChunks = [];
|
|
15357
15370
|
await ttsQwen3Local(text, { url: c.url, voice: c.voice, lang: c.lang }, (pcm2) => pcmChunks.push(pcm2));
|
|
15358
15371
|
const pcm = Buffer.concat(pcmChunks);
|
|
15359
|
-
|
|
15360
|
-
const wavPath =
|
|
15372
|
+
fs22.mkdirSync(VOICE_DIR, { recursive: true });
|
|
15373
|
+
const wavPath = path23.join(VOICE_DIR, `tts_${Date.now()}.wav`);
|
|
15361
15374
|
const header = Buffer.alloc(44);
|
|
15362
15375
|
header.write("RIFF", 0);
|
|
15363
15376
|
header.writeUInt32LE(36 + pcm.length, 4);
|
|
@@ -15372,7 +15385,7 @@ async function synthQwen3(text, _sink) {
|
|
|
15372
15385
|
header.writeUInt16LE(16, 34);
|
|
15373
15386
|
header.write("data", 36);
|
|
15374
15387
|
header.writeUInt32LE(pcm.length, 40);
|
|
15375
|
-
|
|
15388
|
+
fs22.writeFileSync(wavPath, Buffer.concat([header, pcm]));
|
|
15376
15389
|
return { path: wavPath, format: "wav", unit: unit(text), voice: c.voice };
|
|
15377
15390
|
}
|
|
15378
15391
|
}
|
|
@@ -15388,7 +15401,7 @@ var init_impl = __esm({
|
|
|
15388
15401
|
init_well_formed();
|
|
15389
15402
|
init_voice_chat_tts_daemon();
|
|
15390
15403
|
execFileAsync = promisify(execFile2);
|
|
15391
|
-
VOICE_DIR =
|
|
15404
|
+
VOICE_DIR = path23.join(os4.tmpdir(), "engine-voice");
|
|
15392
15405
|
_pyCache = null;
|
|
15393
15406
|
EDGE_VOICE = "zh-CN-XiaoxiaoNeural";
|
|
15394
15407
|
unit = (text) => ({ kind: "chars", amount: [...text].length });
|
|
@@ -15402,9 +15415,9 @@ var init_impl = __esm({
|
|
|
15402
15415
|
});
|
|
15403
15416
|
|
|
15404
15417
|
// src/tools/tts/relay.ts
|
|
15405
|
-
import * as
|
|
15418
|
+
import * as fs23 from "node:fs";
|
|
15406
15419
|
import * as os5 from "node:os";
|
|
15407
|
-
import * as
|
|
15420
|
+
import * as path24 from "node:path";
|
|
15408
15421
|
async function synthRelay(text, cfg) {
|
|
15409
15422
|
const res = await fetchFn(`${cfg.baseUrl}/audio/speech`, {
|
|
15410
15423
|
method: "POST",
|
|
@@ -15422,9 +15435,9 @@ async function synthRelay(text, cfg) {
|
|
|
15422
15435
|
}
|
|
15423
15436
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
15424
15437
|
if (buf.length < 20) throw new Error(`relay tts: \u54CD\u5E94\u4F53\u53EA\u6709 ${buf.length} \u5B57\u8282\uFF0C\u4E0D\u662F\u6709\u6548\u97F3\u9891`);
|
|
15425
|
-
|
|
15426
|
-
const out =
|
|
15427
|
-
|
|
15438
|
+
fs23.mkdirSync(VOICE_DIR2, { recursive: true });
|
|
15439
|
+
const out = path24.join(VOICE_DIR2, `tts_relay_${Date.now()}.mp3`);
|
|
15440
|
+
fs23.writeFileSync(out, buf);
|
|
15428
15441
|
return {
|
|
15429
15442
|
path: out,
|
|
15430
15443
|
format: "mp3",
|
|
@@ -15437,7 +15450,7 @@ var VOICE_DIR2, fetchFn;
|
|
|
15437
15450
|
var init_relay = __esm({
|
|
15438
15451
|
"src/tools/tts/relay.ts"() {
|
|
15439
15452
|
"use strict";
|
|
15440
|
-
VOICE_DIR2 =
|
|
15453
|
+
VOICE_DIR2 = path24.join(os5.tmpdir(), "engine-voice");
|
|
15441
15454
|
fetchFn = fetch;
|
|
15442
15455
|
}
|
|
15443
15456
|
});
|
|
@@ -15608,13 +15621,13 @@ var init_providers = __esm({
|
|
|
15608
15621
|
});
|
|
15609
15622
|
|
|
15610
15623
|
// src/utils/ffmpeg-path.ts
|
|
15611
|
-
import * as
|
|
15624
|
+
import * as fs24 from "node:fs";
|
|
15612
15625
|
function resolveFfmpegPath() {
|
|
15613
15626
|
const env = (process.env.E7_FFMPEG_PATH || "").trim();
|
|
15614
|
-
if (env &&
|
|
15627
|
+
if (env && fs24.existsSync(env)) return env;
|
|
15615
15628
|
try {
|
|
15616
15629
|
const p = __require("@ffmpeg-installer/ffmpeg")?.path;
|
|
15617
|
-
if (p &&
|
|
15630
|
+
if (p && fs24.existsSync(p)) return p;
|
|
15618
15631
|
} catch {
|
|
15619
15632
|
}
|
|
15620
15633
|
return "ffmpeg";
|
|
@@ -15628,8 +15641,8 @@ var init_ffmpeg_path = __esm({
|
|
|
15628
15641
|
// src/tools/my-voice.ts
|
|
15629
15642
|
import { execFile as execFile3 } from "node:child_process";
|
|
15630
15643
|
import { promisify as promisify2 } from "node:util";
|
|
15631
|
-
import * as
|
|
15632
|
-
import * as
|
|
15644
|
+
import * as fs25 from "node:fs";
|
|
15645
|
+
import * as path25 from "node:path";
|
|
15633
15646
|
async function toWav24kWithDuration(audioPath) {
|
|
15634
15647
|
let wavPath = audioPath;
|
|
15635
15648
|
if (!audioPath.endsWith(".wav")) {
|
|
@@ -15646,15 +15659,15 @@ async function toWav24kWithDuration(audioPath) {
|
|
|
15646
15659
|
"pcm_s16le",
|
|
15647
15660
|
wavPath
|
|
15648
15661
|
], { timeout: 3e4 });
|
|
15649
|
-
if (!
|
|
15662
|
+
if (!fs25.existsSync(wavPath) || fs25.statSync(wavPath).size < 44) {
|
|
15650
15663
|
throw new Error("toWav24k produced empty output");
|
|
15651
15664
|
}
|
|
15652
15665
|
try {
|
|
15653
|
-
|
|
15666
|
+
fs25.unlinkSync(audioPath);
|
|
15654
15667
|
} catch {
|
|
15655
15668
|
}
|
|
15656
15669
|
}
|
|
15657
|
-
const durationSec = wavDurationSec(
|
|
15670
|
+
const durationSec = wavDurationSec(fs25.readFileSync(wavPath));
|
|
15658
15671
|
return { wavPath, durationSec };
|
|
15659
15672
|
}
|
|
15660
15673
|
async function compressWav(wavPath) {
|
|
@@ -15672,7 +15685,7 @@ async function compressWav(wavPath) {
|
|
|
15672
15685
|
"+faststart",
|
|
15673
15686
|
m4aPath
|
|
15674
15687
|
], { timeout: 3e4 });
|
|
15675
|
-
|
|
15688
|
+
fs25.unlinkSync(wavPath);
|
|
15676
15689
|
return m4aPath;
|
|
15677
15690
|
} catch {
|
|
15678
15691
|
return wavPath;
|
|
@@ -15699,10 +15712,10 @@ async function wavToOggOpus(wavPath) {
|
|
|
15699
15712
|
oggPath
|
|
15700
15713
|
], { timeout: 3e4 });
|
|
15701
15714
|
}
|
|
15702
|
-
if (!
|
|
15715
|
+
if (!fs25.existsSync(oggPath) || fs25.statSync(oggPath).size < 20) {
|
|
15703
15716
|
throw new Error("ogg/opus encode produced empty output");
|
|
15704
15717
|
}
|
|
15705
|
-
|
|
15718
|
+
fs25.unlinkSync(wavPath);
|
|
15706
15719
|
return oggPath;
|
|
15707
15720
|
}
|
|
15708
15721
|
async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
@@ -15717,7 +15730,7 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
15717
15730
|
} catch (e) {
|
|
15718
15731
|
return { content: `\u8BED\u97F3\u751F\u6210\u5931\u8D25\uFF08headless\u2192multaca\uFF09\uFF1A${e.message}\u3002\u8BF7\u7528\u6587\u5B57\u56DE\u590D\u4EE3\u66FF\u3002`, isError: true };
|
|
15719
15732
|
}
|
|
15720
|
-
if (!audioPath || !
|
|
15733
|
+
if (!audioPath || !fs25.existsSync(audioPath)) {
|
|
15721
15734
|
return { content: "\u8BED\u97F3\u751F\u6210\u5931\u8D25\uFF08headless\u2192multaca\uFF09\uFF1ATTS \u672A\u4EA7\u51FA\u6587\u4EF6\u3002\u8BF7\u7528\u6587\u5B57\u56DE\u590D\u4EE3\u66FF\u3002", isError: true };
|
|
15722
15735
|
}
|
|
15723
15736
|
if (audioPath.endsWith(".wav")) {
|
|
@@ -15727,21 +15740,21 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
15727
15740
|
console.warn(`[my-voice:multaca] opus encode failed (${e.message}), attaching wav`);
|
|
15728
15741
|
}
|
|
15729
15742
|
}
|
|
15730
|
-
const ext =
|
|
15731
|
-
const sizeKB =
|
|
15743
|
+
const ext = path25.extname(audioPath).toLowerCase();
|
|
15744
|
+
const sizeKB = fs25.statSync(audioPath).size / 1024;
|
|
15732
15745
|
const voiceFile = `voice_${Date.now()}${ext}`;
|
|
15733
|
-
const cwdCopy =
|
|
15746
|
+
const cwdCopy = path25.join(process.cwd(), voiceFile);
|
|
15734
15747
|
try {
|
|
15735
|
-
|
|
15748
|
+
fs25.copyFileSync(audioPath, cwdCopy);
|
|
15736
15749
|
} catch (e) {
|
|
15737
15750
|
try {
|
|
15738
|
-
|
|
15751
|
+
fs25.unlinkSync(audioPath);
|
|
15739
15752
|
} catch {
|
|
15740
15753
|
}
|
|
15741
15754
|
return { content: `\u8BED\u97F3\u6302\u8F7D\u5931\u8D25\uFF08\u62F7\u8D1D\u5230\u5DE5\u4F5C\u76EE\u5F55\uFF09\uFF1A${e.message}`, isError: true };
|
|
15742
15755
|
}
|
|
15743
15756
|
try {
|
|
15744
|
-
|
|
15757
|
+
fs25.unlinkSync(audioPath);
|
|
15745
15758
|
} catch {
|
|
15746
15759
|
}
|
|
15747
15760
|
const content = opts.caption || `\u{1F399}\uFE0F \u8BED\u97F3\u6D88\u606F\uFF08${text.length} \u5B57\uFF09`;
|
|
@@ -15770,13 +15783,13 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
15770
15783
|
}
|
|
15771
15784
|
if (!ok) throw new Error(`unexpected CLI output: ${String(stdout).slice(0, 200)}`);
|
|
15772
15785
|
try {
|
|
15773
|
-
|
|
15786
|
+
fs25.unlinkSync(cwdCopy);
|
|
15774
15787
|
} catch {
|
|
15775
15788
|
}
|
|
15776
15789
|
return { content: `Voice sent to multaca issue ${issueId}! (${actualEngine}, ${sizeKB.toFixed(0)}KB, \u9644\u4EF6\u5DF2\u6302\u5230\u8BC4\u8BBA\u2014\u2014\u5728 multaca \u5BA2\u6237\u7AEF\u64AD\u653E)` };
|
|
15777
15790
|
} catch (e) {
|
|
15778
15791
|
try {
|
|
15779
|
-
|
|
15792
|
+
fs25.unlinkSync(cwdCopy);
|
|
15780
15793
|
} catch {
|
|
15781
15794
|
}
|
|
15782
15795
|
return { content: `\u8BED\u97F3\u6302\u5230 multaca issue \u5931\u8D25\uFF1A${e.message}\u3002\u8BF7\u7528\u6587\u5B57\u56DE\u590D\u4EE3\u66FF\u3002`, isError: true };
|
|
@@ -15906,10 +15919,10 @@ var init_my_voice = __esm({
|
|
|
15906
15919
|
audioPath = await compressWav(audioPath);
|
|
15907
15920
|
}
|
|
15908
15921
|
}
|
|
15909
|
-
const ext =
|
|
15922
|
+
const ext = path25.extname(audioPath).toLowerCase();
|
|
15910
15923
|
const mimeMap = { ".mp3": "audio/mpeg", ".wav": "audio/wav", ".m4a": "audio/mp4", ".ogg": "audio/ogg", ".silk": "audio/silk" };
|
|
15911
15924
|
const mimeType = mimeMap[ext] || "audio/mpeg";
|
|
15912
|
-
const sizeKB =
|
|
15925
|
+
const sizeKB = fs25.statSync(audioPath).size / 1024;
|
|
15913
15926
|
try {
|
|
15914
15927
|
await mgr.sendFile(resolvedChannel, target, caption, {
|
|
15915
15928
|
path: audioPath,
|
|
@@ -15918,7 +15931,7 @@ var init_my_voice = __esm({
|
|
|
15918
15931
|
...voiceDurationSec !== void 0 ? { voiceDurationSec } : {}
|
|
15919
15932
|
});
|
|
15920
15933
|
try {
|
|
15921
|
-
|
|
15934
|
+
fs25.unlinkSync(audioPath);
|
|
15922
15935
|
} catch {
|
|
15923
15936
|
}
|
|
15924
15937
|
return { content: `Voice sent! (${actualEngine}, ${sizeKB.toFixed(0)}KB, ${resolvedChannel})` };
|
|
@@ -15940,8 +15953,8 @@ __export(my_selfie_exports, {
|
|
|
15940
15953
|
dimsOf: () => dimsOf,
|
|
15941
15954
|
resolvePortraitDesc: () => resolvePortraitDesc
|
|
15942
15955
|
});
|
|
15943
|
-
import * as
|
|
15944
|
-
import * as
|
|
15956
|
+
import * as fs26 from "node:fs";
|
|
15957
|
+
import * as path26 from "node:path";
|
|
15945
15958
|
function getProxyDispatcher2() {
|
|
15946
15959
|
const cfg = liveConfig.all();
|
|
15947
15960
|
const proxy = cfg.providers?.xai?.proxy;
|
|
@@ -15955,7 +15968,7 @@ function getProxyDispatcher2() {
|
|
|
15955
15968
|
}
|
|
15956
15969
|
function dimsOf(p) {
|
|
15957
15970
|
try {
|
|
15958
|
-
const b =
|
|
15971
|
+
const b = fs26.readFileSync(p);
|
|
15959
15972
|
let w = 0, h = 0;
|
|
15960
15973
|
if (b.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
|
|
15961
15974
|
w = b.readUInt32BE(16);
|
|
@@ -16068,9 +16081,9 @@ function registerPortrait(relPath, name) {
|
|
|
16068
16081
|
const cur = cfg?.tools?.my_selfie?.references || cfg?.my_selfie?.references || [];
|
|
16069
16082
|
const next = Array.isArray(cur) ? cur.filter((r) => r?.name !== name) : [];
|
|
16070
16083
|
next.unshift({ name, path: relPath });
|
|
16071
|
-
const
|
|
16072
|
-
void liveConfig.set(
|
|
16073
|
-
console.log(`[my-selfie] \u5F62\u8C61\u5DF2\u767B\u8BB0\uFF1A${
|
|
16084
|
+
const path44 = cfg?.tools?.my_selfie ? "tools.my_selfie.references" : "my_selfie.references";
|
|
16085
|
+
void liveConfig.set(path44, next);
|
|
16086
|
+
console.log(`[my-selfie] \u5F62\u8C61\u5DF2\u767B\u8BB0\uFF1A${path44}[0] = ${relPath}`);
|
|
16074
16087
|
} catch (e) {
|
|
16075
16088
|
console.warn(`[my-selfie] \u5199\u5165 references \u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u672C\u6B21\u51FA\u56FE\uFF09: ${e.message}`);
|
|
16076
16089
|
}
|
|
@@ -16368,10 +16381,10 @@ var init_my_selfie = __esm({
|
|
|
16368
16381
|
const REFERENCES = getReferences(ctx);
|
|
16369
16382
|
const refName = args.reference || "default";
|
|
16370
16383
|
const refEntry = REFERENCES.find((r) => r.name === refName) || REFERENCES[0];
|
|
16371
|
-
let refPath =
|
|
16384
|
+
let refPath = path26.join(ctx.workspace, refEntry.p);
|
|
16372
16385
|
const adoptImg = args.referenceImage?.trim();
|
|
16373
16386
|
if (adoptImg) {
|
|
16374
|
-
if (!
|
|
16387
|
+
if (!fs26.existsSync(adoptImg)) {
|
|
16375
16388
|
return { content: `\u627E\u4E0D\u5230\u90A3\u5F20\u56FE\uFF1A${adoptImg}`, isError: true };
|
|
16376
16389
|
}
|
|
16377
16390
|
const acheck = dimsOf(adoptImg);
|
|
@@ -16382,16 +16395,16 @@ var init_my_selfie = __esm({
|
|
|
16382
16395
|
isError: true
|
|
16383
16396
|
};
|
|
16384
16397
|
}
|
|
16385
|
-
const adir =
|
|
16386
|
-
if (!
|
|
16387
|
-
const aext = (
|
|
16398
|
+
const adir = path26.join(ctx.workspace, "images");
|
|
16399
|
+
if (!fs26.existsSync(adir)) fs26.mkdirSync(adir, { recursive: true });
|
|
16400
|
+
const aext = (path26.extname(adoptImg) || ".png").toLowerCase();
|
|
16388
16401
|
const afname = `portrait_${Date.now()}${aext}`;
|
|
16389
|
-
|
|
16402
|
+
fs26.copyFileSync(adoptImg, path26.join(adir, afname));
|
|
16390
16403
|
registerPortrait(`images/${afname}`, refName);
|
|
16391
|
-
refPath =
|
|
16404
|
+
refPath = path26.join(adir, afname);
|
|
16392
16405
|
console.log(`[my-selfie] \u91C7\u7EB3\u73B0\u6210\u56FE\u5F53\u5F62\u8C61\uFF1Aimages/${afname}${acheck ? ` (${acheck})` : ""}`);
|
|
16393
16406
|
}
|
|
16394
|
-
if (provider !== "autodl" && !
|
|
16407
|
+
if (provider !== "autodl" && !fs26.existsSync(refPath)) {
|
|
16395
16408
|
const cfgAll = liveConfig.all();
|
|
16396
16409
|
const portraitDesc = resolvePortraitDesc(
|
|
16397
16410
|
args.portrait,
|
|
@@ -16416,16 +16429,16 @@ var init_my_selfie = __esm({
|
|
|
16416
16429
|
} catch (e) {
|
|
16417
16430
|
return { content: `\u5851\u9020\u5F62\u8C61\u5931\u8D25\uFF1A${e.message}`, isError: true };
|
|
16418
16431
|
}
|
|
16419
|
-
const pdir =
|
|
16420
|
-
if (!
|
|
16432
|
+
const pdir = path26.join(ctx.workspace, "images");
|
|
16433
|
+
if (!fs26.existsSync(pdir)) fs26.mkdirSync(pdir, { recursive: true });
|
|
16421
16434
|
const pfname = `portrait_${Date.now()}.png`;
|
|
16422
|
-
|
|
16435
|
+
fs26.writeFileSync(path26.join(pdir, pfname), portraitBuf);
|
|
16423
16436
|
registerPortrait(`images/${pfname}`, refName);
|
|
16424
|
-
refPath =
|
|
16437
|
+
refPath = path26.join(pdir, pfname);
|
|
16425
16438
|
console.log(`[my-selfie] \u5F62\u8C61\u5DF2\u5B58 images/${pfname}\uFF0C\u7EE7\u7EED\u8FD9\u6B21\u81EA\u62CD`);
|
|
16426
16439
|
}
|
|
16427
16440
|
const resolution = args.resolution || DEFAULT_RESOLUTION;
|
|
16428
|
-
const refB64 =
|
|
16441
|
+
const refB64 = fs26.existsSync(refPath) ? fs26.readFileSync(refPath).toString("base64") : "";
|
|
16429
16442
|
let imageBuffer;
|
|
16430
16443
|
try {
|
|
16431
16444
|
if (provider === "autodl") {
|
|
@@ -16441,7 +16454,7 @@ var init_my_selfie = __esm({
|
|
|
16441
16454
|
return { content: `Error: relay provider \u672A\u914D\u7F6E\u3002config \u91CC\u8981\u6709 models.providers.${cfgAll?.my_selfie?.relayProviderId || "7yi"} \u7684 baseUrl \u548C apiKey\u3002`, isError: true };
|
|
16442
16455
|
}
|
|
16443
16456
|
const model = cfgAll?.my_selfie?.relayModel || cfgAll?.tools?.my_selfie?.relayModel || "engine7-img-free";
|
|
16444
|
-
const ext =
|
|
16457
|
+
const ext = path26.extname(refPath).toLowerCase();
|
|
16445
16458
|
const mime = ext === ".png" ? "image/png" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
16446
16459
|
imageBuffer = await generateWithRelay(refB64, fullPrompt, mime, relay.baseUrl, relay.apiKey, model);
|
|
16447
16460
|
} else {
|
|
@@ -16450,11 +16463,11 @@ var init_my_selfie = __esm({
|
|
|
16450
16463
|
} catch (err) {
|
|
16451
16464
|
return { content: `Selfie generation failed: ${err.message}`, isError: true };
|
|
16452
16465
|
}
|
|
16453
|
-
const imagesDir =
|
|
16454
|
-
if (!
|
|
16466
|
+
const imagesDir = path26.join(ctx.workspace, "images");
|
|
16467
|
+
if (!fs26.existsSync(imagesDir)) fs26.mkdirSync(imagesDir, { recursive: true });
|
|
16455
16468
|
const filename = `selfie_${Date.now()}.jpg`;
|
|
16456
|
-
const outputPath =
|
|
16457
|
-
|
|
16469
|
+
const outputPath = path26.join(imagesDir, filename);
|
|
16470
|
+
fs26.writeFileSync(outputPath, imageBuffer);
|
|
16458
16471
|
const mgr = ctx.channelManager;
|
|
16459
16472
|
if (mgr) {
|
|
16460
16473
|
const resolvedChannel = ctx.channel || "feishu";
|
|
@@ -16465,11 +16478,11 @@ var init_my_selfie = __esm({
|
|
|
16465
16478
|
mimeType: "image/jpeg"
|
|
16466
16479
|
});
|
|
16467
16480
|
} catch (err) {
|
|
16468
|
-
return { content: `Selfie generated but send failed: ${err.message}. Image: ${
|
|
16481
|
+
return { content: `Selfie generated but send failed: ${err.message}. Image: ${path26.resolve(outputPath)}`, isError: false };
|
|
16469
16482
|
}
|
|
16470
16483
|
return { content: `Selfie sent! Mode: ${mode}, Provider: ${provider}, Ref: ${refEntry.name}` };
|
|
16471
16484
|
}
|
|
16472
|
-
return { content: `Selfie generated! Mode: ${mode}, Ref: ${refEntry.name}. Image: ${
|
|
16485
|
+
return { content: `Selfie generated! Mode: ${mode}, Ref: ${refEntry.name}. Image: ${path26.resolve(outputPath)}` };
|
|
16473
16486
|
},
|
|
16474
16487
|
isConcurrencySafe: () => false,
|
|
16475
16488
|
interruptBehavior: () => "block",
|
|
@@ -17299,8 +17312,8 @@ var init_calendar = __esm({
|
|
|
17299
17312
|
});
|
|
17300
17313
|
|
|
17301
17314
|
// src/tools/service.ts
|
|
17302
|
-
import * as
|
|
17303
|
-
import * as
|
|
17315
|
+
import * as fs27 from "node:fs";
|
|
17316
|
+
import * as path27 from "node:path";
|
|
17304
17317
|
import { exec, spawn as spawn4 } from "node:child_process";
|
|
17305
17318
|
import { promisify as promisify3 } from "node:util";
|
|
17306
17319
|
function getServices() {
|
|
@@ -17308,9 +17321,9 @@ function getServices() {
|
|
|
17308
17321
|
}
|
|
17309
17322
|
function serviceLogPath(fileName) {
|
|
17310
17323
|
const stateDir = String(liveConfig.get("stateDir") ?? "");
|
|
17311
|
-
const logDir =
|
|
17312
|
-
if (!
|
|
17313
|
-
return
|
|
17324
|
+
const logDir = path27.join(stateDir, "logs");
|
|
17325
|
+
if (!fs27.existsSync(logDir)) fs27.mkdirSync(logDir, { recursive: true });
|
|
17326
|
+
return path27.join(logDir, fileName);
|
|
17314
17327
|
}
|
|
17315
17328
|
async function runCmd(cmd, timeoutMs = 15e3) {
|
|
17316
17329
|
try {
|
|
@@ -17525,24 +17538,24 @@ var init_constants5 = __esm({
|
|
|
17525
17538
|
});
|
|
17526
17539
|
|
|
17527
17540
|
// src/tools/TodoWriteTool/TodoWriteTool.ts
|
|
17528
|
-
import
|
|
17529
|
-
import
|
|
17541
|
+
import fs28 from "node:fs";
|
|
17542
|
+
import path28 from "node:path";
|
|
17530
17543
|
function todoFilePath(sessionId) {
|
|
17531
|
-
return
|
|
17544
|
+
return path28.join(todosDir, `${sessionId}.json`);
|
|
17532
17545
|
}
|
|
17533
17546
|
function loadTodos(sessionId) {
|
|
17534
17547
|
if (!todosDir) return [];
|
|
17535
17548
|
try {
|
|
17536
17549
|
const filePath = todoFilePath(sessionId);
|
|
17537
|
-
if (!
|
|
17538
|
-
return JSON.parse(
|
|
17550
|
+
if (!fs28.existsSync(filePath)) return [];
|
|
17551
|
+
return JSON.parse(fs28.readFileSync(filePath, "utf-8"));
|
|
17539
17552
|
} catch {
|
|
17540
17553
|
return [];
|
|
17541
17554
|
}
|
|
17542
17555
|
}
|
|
17543
17556
|
function saveTodos(sessionId, todos) {
|
|
17544
17557
|
if (!todosDir) return;
|
|
17545
|
-
|
|
17558
|
+
fs28.writeFileSync(todoFilePath(sessionId), JSON.stringify(todos, null, 2), "utf-8");
|
|
17546
17559
|
}
|
|
17547
17560
|
var todosDir;
|
|
17548
17561
|
var init_TodoWriteTool = __esm({
|
|
@@ -17799,15 +17812,15 @@ var init_constants7 = __esm({
|
|
|
17799
17812
|
});
|
|
17800
17813
|
|
|
17801
17814
|
// src/utils/plans.ts
|
|
17802
|
-
import * as
|
|
17803
|
-
import * as
|
|
17815
|
+
import * as fs29 from "node:fs";
|
|
17816
|
+
import * as path29 from "node:path";
|
|
17804
17817
|
import * as crypto4 from "node:crypto";
|
|
17805
17818
|
function generateSlug() {
|
|
17806
17819
|
return crypto4.randomBytes(4).toString("hex");
|
|
17807
17820
|
}
|
|
17808
17821
|
function getPlansDirectory(stateDir) {
|
|
17809
|
-
const plansDir =
|
|
17810
|
-
|
|
17822
|
+
const plansDir = path29.join(stateDir, "plans");
|
|
17823
|
+
fs29.mkdirSync(plansDir, { recursive: true });
|
|
17811
17824
|
return plansDir;
|
|
17812
17825
|
}
|
|
17813
17826
|
function getPlanSlug(sessionId, stateDir) {
|
|
@@ -17816,8 +17829,8 @@ function getPlanSlug(sessionId, stateDir) {
|
|
|
17816
17829
|
const plansDir = getPlansDirectory(stateDir);
|
|
17817
17830
|
for (let i = 0; i < MAX_SLUG_RETRIES; i++) {
|
|
17818
17831
|
slug = generateSlug();
|
|
17819
|
-
const filePath =
|
|
17820
|
-
if (!
|
|
17832
|
+
const filePath = path29.join(plansDir, `${slug}.md`);
|
|
17833
|
+
if (!fs29.existsSync(filePath)) {
|
|
17821
17834
|
break;
|
|
17822
17835
|
}
|
|
17823
17836
|
}
|
|
@@ -17828,21 +17841,21 @@ function getPlanSlug(sessionId, stateDir) {
|
|
|
17828
17841
|
function getPlanFilePath(sessionId, stateDir, agentId) {
|
|
17829
17842
|
const slug = getPlanSlug(sessionId, stateDir);
|
|
17830
17843
|
if (!agentId) {
|
|
17831
|
-
return
|
|
17844
|
+
return path29.join(getPlansDirectory(stateDir), `${slug}.md`);
|
|
17832
17845
|
}
|
|
17833
|
-
return
|
|
17846
|
+
return path29.join(getPlansDirectory(stateDir), `${slug}-agent-${agentId}.md`);
|
|
17834
17847
|
}
|
|
17835
17848
|
function getPlan(sessionId, stateDir, agentId) {
|
|
17836
17849
|
const filePath = getPlanFilePath(sessionId, stateDir, agentId);
|
|
17837
17850
|
try {
|
|
17838
|
-
return
|
|
17851
|
+
return fs29.readFileSync(filePath, "utf-8");
|
|
17839
17852
|
} catch {
|
|
17840
17853
|
return null;
|
|
17841
17854
|
}
|
|
17842
17855
|
}
|
|
17843
17856
|
function writePlan(sessionId, stateDir, content, agentId) {
|
|
17844
17857
|
const filePath = getPlanFilePath(sessionId, stateDir, agentId);
|
|
17845
|
-
|
|
17858
|
+
fs29.writeFileSync(filePath, content, "utf-8");
|
|
17846
17859
|
return filePath;
|
|
17847
17860
|
}
|
|
17848
17861
|
var MAX_SLUG_RETRIES, planSlugCache;
|
|
@@ -17990,28 +18003,28 @@ var init_constants8 = __esm({
|
|
|
17990
18003
|
});
|
|
17991
18004
|
|
|
17992
18005
|
// src/utils/tasks.ts
|
|
17993
|
-
import * as
|
|
17994
|
-
import * as
|
|
18006
|
+
import * as fs30 from "node:fs";
|
|
18007
|
+
import * as path30 from "node:path";
|
|
17995
18008
|
function sanitizePathComponent2(input) {
|
|
17996
18009
|
return input.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
17997
18010
|
}
|
|
17998
18011
|
function getTasksDir2(stateDir, listId) {
|
|
17999
|
-
return
|
|
18012
|
+
return path30.join(stateDir, "tasks", sanitizePathComponent2(listId));
|
|
18000
18013
|
}
|
|
18001
18014
|
function getTaskPath(stateDir, listId, taskId) {
|
|
18002
|
-
return
|
|
18015
|
+
return path30.join(getTasksDir2(stateDir, listId), `${sanitizePathComponent2(taskId)}.json`);
|
|
18003
18016
|
}
|
|
18004
18017
|
function ensureTasksDir2(stateDir, listId) {
|
|
18005
18018
|
const dir = getTasksDir2(stateDir, listId);
|
|
18006
|
-
|
|
18019
|
+
fs30.mkdirSync(dir, { recursive: true });
|
|
18007
18020
|
return dir;
|
|
18008
18021
|
}
|
|
18009
18022
|
function getHighWaterMarkPath(stateDir, listId) {
|
|
18010
|
-
return
|
|
18023
|
+
return path30.join(getTasksDir2(stateDir, listId), HIGH_WATER_MARK_FILE);
|
|
18011
18024
|
}
|
|
18012
18025
|
function readHighWaterMark(stateDir, listId) {
|
|
18013
18026
|
try {
|
|
18014
|
-
const content =
|
|
18027
|
+
const content = fs30.readFileSync(getHighWaterMarkPath(stateDir, listId), "utf-8").trim();
|
|
18015
18028
|
const value = parseInt(content, 10);
|
|
18016
18029
|
return isNaN(value) ? 0 : value;
|
|
18017
18030
|
} catch {
|
|
@@ -18019,13 +18032,13 @@ function readHighWaterMark(stateDir, listId) {
|
|
|
18019
18032
|
}
|
|
18020
18033
|
}
|
|
18021
18034
|
function writeHighWaterMark(stateDir, listId, value) {
|
|
18022
|
-
|
|
18035
|
+
fs30.writeFileSync(getHighWaterMarkPath(stateDir, listId), String(value));
|
|
18023
18036
|
}
|
|
18024
18037
|
function findHighestTaskIdFromFiles(stateDir, listId) {
|
|
18025
18038
|
const dir = getTasksDir2(stateDir, listId);
|
|
18026
18039
|
let files;
|
|
18027
18040
|
try {
|
|
18028
|
-
files =
|
|
18041
|
+
files = fs30.readdirSync(dir);
|
|
18029
18042
|
} catch {
|
|
18030
18043
|
return 0;
|
|
18031
18044
|
}
|
|
@@ -18051,14 +18064,14 @@ function createTask(stateDir, listId, taskData) {
|
|
|
18051
18064
|
const id = String(highestId + 1);
|
|
18052
18065
|
const task = { id, ...taskData };
|
|
18053
18066
|
const filePath = getTaskPath(stateDir, listId, id);
|
|
18054
|
-
|
|
18067
|
+
fs30.writeFileSync(filePath, JSON.stringify(task, null, 2));
|
|
18055
18068
|
return id;
|
|
18056
18069
|
});
|
|
18057
18070
|
}
|
|
18058
18071
|
function getTask2(stateDir, listId, taskId) {
|
|
18059
18072
|
const filePath = getTaskPath(stateDir, listId, taskId);
|
|
18060
18073
|
try {
|
|
18061
|
-
const content =
|
|
18074
|
+
const content = fs30.readFileSync(filePath, "utf-8");
|
|
18062
18075
|
return JSON.parse(content);
|
|
18063
18076
|
} catch {
|
|
18064
18077
|
return null;
|
|
@@ -18068,7 +18081,7 @@ function listTasks2(stateDir, listId) {
|
|
|
18068
18081
|
const dir = getTasksDir2(stateDir, listId);
|
|
18069
18082
|
let files;
|
|
18070
18083
|
try {
|
|
18071
|
-
files =
|
|
18084
|
+
files = fs30.readdirSync(dir);
|
|
18072
18085
|
} catch {
|
|
18073
18086
|
return [];
|
|
18074
18087
|
}
|
|
@@ -18080,7 +18093,7 @@ function updateTask(stateDir, listId, taskId, updates) {
|
|
|
18080
18093
|
if (!existing) return null;
|
|
18081
18094
|
const updated = { ...existing, ...updates, id: taskId };
|
|
18082
18095
|
const filePath = getTaskPath(stateDir, listId, taskId);
|
|
18083
|
-
|
|
18096
|
+
fs30.writeFileSync(filePath, JSON.stringify(updated, null, 2));
|
|
18084
18097
|
return updated;
|
|
18085
18098
|
}
|
|
18086
18099
|
function deleteTask(stateDir, listId, taskId) {
|
|
@@ -18094,7 +18107,7 @@ function deleteTask(stateDir, listId, taskId) {
|
|
|
18094
18107
|
}
|
|
18095
18108
|
}
|
|
18096
18109
|
try {
|
|
18097
|
-
|
|
18110
|
+
fs30.unlinkSync(filePath);
|
|
18098
18111
|
} catch {
|
|
18099
18112
|
return false;
|
|
18100
18113
|
}
|
|
@@ -19527,10 +19540,10 @@ function ensureLoaded(workspace, configIds) {
|
|
|
19527
19540
|
if (!state.blockedUserIds.includes(id)) state.blockedUserIds.push(id);
|
|
19528
19541
|
}
|
|
19529
19542
|
}
|
|
19530
|
-
const
|
|
19543
|
+
const path44 = join28(workspace, ".reply-blocklist.json");
|
|
19531
19544
|
try {
|
|
19532
|
-
if (existsSync22(
|
|
19533
|
-
const raw = readFileSync21(
|
|
19545
|
+
if (existsSync22(path44)) {
|
|
19546
|
+
const raw = readFileSync21(path44, "utf-8");
|
|
19534
19547
|
const parsed = JSON.parse(raw);
|
|
19535
19548
|
if (parsed.blockedUserIds) {
|
|
19536
19549
|
for (const id of parsed.blockedUserIds) {
|
|
@@ -19546,9 +19559,9 @@ function ensureLoaded(workspace, configIds) {
|
|
|
19546
19559
|
loaded = true;
|
|
19547
19560
|
}
|
|
19548
19561
|
function save(workspace) {
|
|
19549
|
-
const
|
|
19562
|
+
const path44 = join28(workspace, ".reply-blocklist.json");
|
|
19550
19563
|
try {
|
|
19551
|
-
writeFileSync16(
|
|
19564
|
+
writeFileSync16(path44, JSON.stringify(state, null, 2), "utf-8");
|
|
19552
19565
|
} catch (err) {
|
|
19553
19566
|
console.warn(`[reply-blocklist] Failed to save: ${err.message}`);
|
|
19554
19567
|
}
|
|
@@ -20744,8 +20757,8 @@ var extractMemories_exports = {};
|
|
|
20744
20757
|
__export(extractMemories_exports, {
|
|
20745
20758
|
createMemoryExtractor: () => createMemoryExtractor
|
|
20746
20759
|
});
|
|
20747
|
-
import * as
|
|
20748
|
-
import * as
|
|
20760
|
+
import * as fs31 from "fs";
|
|
20761
|
+
import * as path31 from "path";
|
|
20749
20762
|
function isModelVisibleMessage(message) {
|
|
20750
20763
|
return message.role === "user" || message.role === "assistant";
|
|
20751
20764
|
}
|
|
@@ -20768,13 +20781,13 @@ function getMemoryTools() {
|
|
|
20768
20781
|
return allDefs.filter((d) => MEMORY_TOOL_NAMES.includes(d.function.name));
|
|
20769
20782
|
}
|
|
20770
20783
|
function getStatePath(workspace) {
|
|
20771
|
-
return
|
|
20784
|
+
return path31.join(workspace, STATE_FILE);
|
|
20772
20785
|
}
|
|
20773
20786
|
function loadPersistedState(workspace) {
|
|
20774
20787
|
try {
|
|
20775
20788
|
const p = getStatePath(workspace);
|
|
20776
|
-
if (
|
|
20777
|
-
const data = JSON.parse(
|
|
20789
|
+
if (fs31.existsSync(p)) {
|
|
20790
|
+
const data = JSON.parse(fs31.readFileSync(p, "utf-8"));
|
|
20778
20791
|
for (const [sid, ts] of Object.entries(data.lastTs ?? {})) {
|
|
20779
20792
|
lastTsMap.set(sid, ts);
|
|
20780
20793
|
}
|
|
@@ -20794,7 +20807,7 @@ function persistState(workspace) {
|
|
|
20794
20807
|
for (const [sid, ts] of lastTsMap.entries()) lastTs[sid] = ts;
|
|
20795
20808
|
for (const [sid, ts] of lastExtractTimeMap.entries()) timestamps[sid] = ts;
|
|
20796
20809
|
const data = JSON.stringify({ lastTs, timestamps }, null, 2);
|
|
20797
|
-
|
|
20810
|
+
fs31.writeFileSync(getStatePath(workspace), data, "utf-8");
|
|
20798
20811
|
} catch (e) {
|
|
20799
20812
|
console.warn(`[memory] failed to persist extract state: ${e?.message ?? e}`);
|
|
20800
20813
|
}
|
|
@@ -20835,11 +20848,11 @@ function createMemoryExtractor(workspace, enabled) {
|
|
|
20835
20848
|
const existingMemories = formatMemoryManifest(
|
|
20836
20849
|
await scanMemoryFiles2(memoryDir, new AbortController().signal)
|
|
20837
20850
|
);
|
|
20838
|
-
const extractOverridePath =
|
|
20851
|
+
const extractOverridePath = path31.join(workspace, "prompts", "extract.md");
|
|
20839
20852
|
let systemPrompt;
|
|
20840
20853
|
try {
|
|
20841
|
-
if (
|
|
20842
|
-
systemPrompt =
|
|
20854
|
+
if (fs31.existsSync(extractOverridePath)) {
|
|
20855
|
+
systemPrompt = fs31.readFileSync(extractOverridePath, { encoding: "utf-8" });
|
|
20843
20856
|
if (existingMemories.length > 0) {
|
|
20844
20857
|
systemPrompt += `
|
|
20845
20858
|
|
|
@@ -20965,8 +20978,8 @@ __export(ingest_exports, {
|
|
|
20965
20978
|
pushConversation: () => pushConversation,
|
|
20966
20979
|
toPayload: () => toPayload
|
|
20967
20980
|
});
|
|
20968
|
-
import
|
|
20969
|
-
import
|
|
20981
|
+
import fs32 from "node:fs";
|
|
20982
|
+
import path32 from "node:path";
|
|
20970
20983
|
async function readConfig() {
|
|
20971
20984
|
const defaults = {
|
|
20972
20985
|
url: "http://127.0.0.1:8100",
|
|
@@ -20996,9 +21009,9 @@ async function readConfig() {
|
|
|
20996
21009
|
}
|
|
20997
21010
|
function loadPushTs(workspace, sessionId) {
|
|
20998
21011
|
try {
|
|
20999
|
-
const p =
|
|
21000
|
-
if (
|
|
21001
|
-
const data = JSON.parse(
|
|
21012
|
+
const p = path32.join(workspace, PUSH_STATE_FILE);
|
|
21013
|
+
if (fs32.existsSync(p)) {
|
|
21014
|
+
const data = JSON.parse(fs32.readFileSync(p, "utf-8"));
|
|
21002
21015
|
return typeof data[sessionId] === "number" ? data[sessionId] : 0;
|
|
21003
21016
|
}
|
|
21004
21017
|
} catch (e) {
|
|
@@ -21008,14 +21021,14 @@ function loadPushTs(workspace, sessionId) {
|
|
|
21008
21021
|
}
|
|
21009
21022
|
function savePushTs(workspace, sessionId, ts) {
|
|
21010
21023
|
try {
|
|
21011
|
-
const p =
|
|
21024
|
+
const p = path32.join(workspace, PUSH_STATE_FILE);
|
|
21012
21025
|
let data = {};
|
|
21013
21026
|
try {
|
|
21014
|
-
if (
|
|
21027
|
+
if (fs32.existsSync(p)) data = JSON.parse(fs32.readFileSync(p, "utf-8"));
|
|
21015
21028
|
} catch {
|
|
21016
21029
|
}
|
|
21017
21030
|
data[sessionId] = ts;
|
|
21018
|
-
|
|
21031
|
+
fs32.writeFileSync(p, JSON.stringify(data, null, 2), "utf-8");
|
|
21019
21032
|
} catch (e) {
|
|
21020
21033
|
console.warn(`[everos-ingest] save pushTs failed: ${e?.message ?? e}`);
|
|
21021
21034
|
}
|
|
@@ -27940,11 +27953,11 @@ async function readLastConsolidatedAt(memoryDir) {
|
|
|
27940
27953
|
}
|
|
27941
27954
|
}
|
|
27942
27955
|
async function tryAcquireConsolidationLock(memoryDir) {
|
|
27943
|
-
const
|
|
27956
|
+
const path44 = lockPath(memoryDir);
|
|
27944
27957
|
let mtimeMs;
|
|
27945
27958
|
let holderPid;
|
|
27946
27959
|
try {
|
|
27947
|
-
const [s, raw] = await Promise.all([stat3(
|
|
27960
|
+
const [s, raw] = await Promise.all([stat3(path44), readFile5(path44, "utf8")]);
|
|
27948
27961
|
mtimeMs = s.mtimeMs;
|
|
27949
27962
|
const parsed = parseInt(raw.trim(), 10);
|
|
27950
27963
|
holderPid = Number.isFinite(parsed) ? parsed : void 0;
|
|
@@ -27957,10 +27970,10 @@ async function tryAcquireConsolidationLock(memoryDir) {
|
|
|
27957
27970
|
}
|
|
27958
27971
|
}
|
|
27959
27972
|
await mkdir3(memoryDir, { recursive: true });
|
|
27960
|
-
await writeFile4(
|
|
27973
|
+
await writeFile4(path44, String(process.pid));
|
|
27961
27974
|
let verify2;
|
|
27962
27975
|
try {
|
|
27963
|
-
verify2 = await readFile5(
|
|
27976
|
+
verify2 = await readFile5(path44, "utf8");
|
|
27964
27977
|
} catch {
|
|
27965
27978
|
return null;
|
|
27966
27979
|
}
|
|
@@ -27968,15 +27981,15 @@ async function tryAcquireConsolidationLock(memoryDir) {
|
|
|
27968
27981
|
return mtimeMs ?? 0;
|
|
27969
27982
|
}
|
|
27970
27983
|
async function rollbackConsolidationLock(memoryDir, priorMtime) {
|
|
27971
|
-
const
|
|
27984
|
+
const path44 = lockPath(memoryDir);
|
|
27972
27985
|
try {
|
|
27973
27986
|
if (priorMtime === 0) {
|
|
27974
|
-
await unlink(
|
|
27987
|
+
await unlink(path44);
|
|
27975
27988
|
return;
|
|
27976
27989
|
}
|
|
27977
|
-
await writeFile4(
|
|
27990
|
+
await writeFile4(path44, "");
|
|
27978
27991
|
const t = priorMtime / 1e3;
|
|
27979
|
-
await utimes(
|
|
27992
|
+
await utimes(path44, t, t);
|
|
27980
27993
|
} catch (e) {
|
|
27981
27994
|
console.log(`[autoDream] rollback failed: ${e.message} \u2014 next trigger delayed to minHours`);
|
|
27982
27995
|
}
|
|
@@ -28263,7 +28276,7 @@ __export(handle_query_exports, {
|
|
|
28263
28276
|
});
|
|
28264
28277
|
import { readFileSync as readFileSync37, existsSync as existsSync31, statSync as statSync13 } from "node:fs";
|
|
28265
28278
|
import { join as join48, resolve as resolve8 } from "node:path";
|
|
28266
|
-
import * as
|
|
28279
|
+
import * as path33 from "node:path";
|
|
28267
28280
|
function resolveSystemPrompt(v) {
|
|
28268
28281
|
return typeof v === "function" ? v() : v || "";
|
|
28269
28282
|
}
|
|
@@ -28271,18 +28284,18 @@ function resetSessionStartInjection(sessionId) {
|
|
|
28271
28284
|
sessionStartDone.delete(sessionId);
|
|
28272
28285
|
}
|
|
28273
28286
|
function loadExternalChanRules(workspace) {
|
|
28274
|
-
const
|
|
28275
|
-
if (externalChanRulesCache && externalChanRulesCache.path ===
|
|
28287
|
+
const path44 = join48(workspace, "prompts", "external-chan-rules.md");
|
|
28288
|
+
if (externalChanRulesCache && externalChanRulesCache.path === path44) return externalChanRulesCache;
|
|
28276
28289
|
let content = "";
|
|
28277
|
-
if (existsSync31(
|
|
28290
|
+
if (existsSync31(path44)) {
|
|
28278
28291
|
try {
|
|
28279
|
-
content = readFileSync37(
|
|
28292
|
+
content = readFileSync37(path44, "utf-8").trim();
|
|
28280
28293
|
} catch (e) {
|
|
28281
28294
|
console.warn(`[external-chan-rules] Failed to load: ${e}`);
|
|
28282
28295
|
}
|
|
28283
28296
|
}
|
|
28284
|
-
externalChanRulesCache = { path:
|
|
28285
|
-
console.log(`[external-chan-rules] Loaded ${content.length} chars from ${
|
|
28297
|
+
externalChanRulesCache = { path: path44, content };
|
|
28298
|
+
console.log(`[external-chan-rules] Loaded ${content.length} chars from ${path44}`);
|
|
28286
28299
|
return externalChanRulesCache;
|
|
28287
28300
|
}
|
|
28288
28301
|
function getExternalChanRulesBlock(inboundMeta, workspace) {
|
|
@@ -29097,7 +29110,7 @@ stack: ${err.stack ?? "(none)"}`);
|
|
|
29097
29110
|
}
|
|
29098
29111
|
} catch (err) {
|
|
29099
29112
|
try {
|
|
29100
|
-
(await import("node:fs")).appendFileSync(join48(process.env.ENGINE7_STATE_DIR ||
|
|
29113
|
+
(await import("node:fs")).appendFileSync(join48(process.env.ENGINE7_STATE_DIR || path33.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7"), "logs", "autoDream-debug.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] [handle-query] autoDream trigger TRY-CATCH: ${err.message}
|
|
29101
29114
|
stack: ${err.stack ?? "(none)"}
|
|
29102
29115
|
`);
|
|
29103
29116
|
} catch {
|
|
@@ -29785,8 +29798,8 @@ __export(free_tier_apply_exports, {
|
|
|
29785
29798
|
isFreeTierConfig: () => isFreeTierConfig,
|
|
29786
29799
|
resolveConfigPath: () => resolveConfigPath
|
|
29787
29800
|
});
|
|
29788
|
-
import * as
|
|
29789
|
-
import * as
|
|
29801
|
+
import * as fs33 from "node:fs";
|
|
29802
|
+
import * as path34 from "node:path";
|
|
29790
29803
|
function isFreeTierConfig(cfg) {
|
|
29791
29804
|
const hasProvider = !!cfg?.models?.providers?.[FREE_TIER_PROVIDER_ID];
|
|
29792
29805
|
const primary = String(cfg?.agents?.defaults?.model?.primary || "");
|
|
@@ -29835,18 +29848,18 @@ function applyFreeTier(cfg, opts = {}) {
|
|
|
29835
29848
|
return cfg;
|
|
29836
29849
|
}
|
|
29837
29850
|
function resolveConfigPath(stateDir, configName) {
|
|
29838
|
-
const configsDir =
|
|
29851
|
+
const configsDir = path34.join(stateDir, "configs");
|
|
29839
29852
|
if (configName) {
|
|
29840
|
-
const p =
|
|
29841
|
-
return
|
|
29842
|
-
}
|
|
29843
|
-
const main2 =
|
|
29844
|
-
if (
|
|
29845
|
-
if (!
|
|
29846
|
-
for (const f of
|
|
29847
|
-
const full =
|
|
29853
|
+
const p = path34.join(configsDir, configName);
|
|
29854
|
+
return fs33.existsSync(p) ? p : "";
|
|
29855
|
+
}
|
|
29856
|
+
const main2 = path34.join(configsDir, "main7.json");
|
|
29857
|
+
if (fs33.existsSync(main2)) return main2;
|
|
29858
|
+
if (!fs33.existsSync(configsDir)) return "";
|
|
29859
|
+
for (const f of fs33.readdirSync(configsDir).filter((x) => x.endsWith(".json"))) {
|
|
29860
|
+
const full = path34.join(configsDir, f);
|
|
29848
29861
|
try {
|
|
29849
|
-
if (JSON.parse(
|
|
29862
|
+
if (JSON.parse(fs33.readFileSync(full, "utf8")).models?.providers) return full;
|
|
29850
29863
|
} catch {
|
|
29851
29864
|
}
|
|
29852
29865
|
}
|
|
@@ -29855,16 +29868,16 @@ function resolveConfigPath(stateDir, configName) {
|
|
|
29855
29868
|
function applyFreeTierToConfig(configPath, opts = {}) {
|
|
29856
29869
|
let cfg;
|
|
29857
29870
|
try {
|
|
29858
|
-
cfg = JSON.parse(
|
|
29871
|
+
cfg = JSON.parse(fs33.readFileSync(configPath, "utf8"));
|
|
29859
29872
|
} catch (e) {
|
|
29860
29873
|
throw new Error(`\u8BFB\u53D6 config \u5931\u8D25: ${configPath}\uFF08${e?.message || e}\uFF09`);
|
|
29861
29874
|
}
|
|
29862
29875
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
29863
29876
|
const backupPath = `${configPath}.bak-${stamp}`;
|
|
29864
|
-
|
|
29877
|
+
fs33.copyFileSync(configPath, backupPath);
|
|
29865
29878
|
applyFreeTier(cfg, opts);
|
|
29866
29879
|
try {
|
|
29867
|
-
|
|
29880
|
+
fs33.writeFileSync(configPath, JSON.stringify(cfg, null, 2), "utf8");
|
|
29868
29881
|
} catch (e) {
|
|
29869
29882
|
throw new Error(`\u5199\u5165 config \u5931\u8D25: ${configPath}\uFF08${e?.message || e}\uFF09\uFF1B\u539F\u6587\u4EF6\u672A\u6539\u52A8\uFF0C\u5907\u4EFD\u5728 ${backupPath}`);
|
|
29870
29883
|
}
|
|
@@ -29894,15 +29907,15 @@ __export(cli_doctor_exports, {
|
|
|
29894
29907
|
resolveStateDirFromArgs: () => resolveStateDirFromArgs,
|
|
29895
29908
|
runDoctor: () => runDoctor
|
|
29896
29909
|
});
|
|
29897
|
-
import * as
|
|
29898
|
-
import * as
|
|
29910
|
+
import * as fs34 from "node:fs";
|
|
29911
|
+
import * as path35 from "node:path";
|
|
29899
29912
|
import * as net from "node:net";
|
|
29900
29913
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
29901
29914
|
function readVersion() {
|
|
29902
|
-
const here =
|
|
29903
|
-
for (const p of [
|
|
29915
|
+
const here = path35.dirname(fileURLToPath6(import.meta.url));
|
|
29916
|
+
for (const p of [path35.join(here, "..", "package.json"), path35.join(here, "..", "..", "package.json")]) {
|
|
29904
29917
|
try {
|
|
29905
|
-
return JSON.parse(
|
|
29918
|
+
return JSON.parse(fs34.readFileSync(p, "utf8")).version || "unknown";
|
|
29906
29919
|
} catch {
|
|
29907
29920
|
}
|
|
29908
29921
|
}
|
|
@@ -29932,7 +29945,7 @@ function probePort(port, timeoutMs) {
|
|
|
29932
29945
|
});
|
|
29933
29946
|
}
|
|
29934
29947
|
async function runDoctor(stateDir, opts) {
|
|
29935
|
-
const configPath =
|
|
29948
|
+
const configPath = path35.join(stateDir, "configs", "main7.json");
|
|
29936
29949
|
const report = {
|
|
29937
29950
|
version: readVersion(),
|
|
29938
29951
|
stateDir,
|
|
@@ -29948,10 +29961,10 @@ async function runDoctor(stateDir, opts) {
|
|
|
29948
29961
|
};
|
|
29949
29962
|
let config = null;
|
|
29950
29963
|
try {
|
|
29951
|
-
config = JSON.parse(
|
|
29964
|
+
config = JSON.parse(fs34.readFileSync(configPath, "utf8"));
|
|
29952
29965
|
report.configValid = true;
|
|
29953
29966
|
} catch (e) {
|
|
29954
|
-
report.configError =
|
|
29967
|
+
report.configError = fs34.existsSync(configPath) ? `\u89E3\u6790\u5931\u8D25: ${e.message}` : "config \u4E0D\u5B58\u5728\uFF08\u5148 engine7 init\uFF09";
|
|
29955
29968
|
}
|
|
29956
29969
|
if (config?.channels) {
|
|
29957
29970
|
for (const [name, conf] of Object.entries(config.channels)) {
|
|
@@ -29959,13 +29972,13 @@ async function runDoctor(stateDir, opts) {
|
|
|
29959
29972
|
report.channels.push({ name, enabled: !!c.enabled, hasCredentials: channelHasCredentials(name, c) });
|
|
29960
29973
|
}
|
|
29961
29974
|
}
|
|
29962
|
-
const cfgBase =
|
|
29975
|
+
const cfgBase = path35.basename(report.configPath, ".json") || "main7";
|
|
29963
29976
|
const candidates = secretsCandidates(stateDir, cfgBase);
|
|
29964
|
-
const secretsFile = candidates.find((p) =>
|
|
29977
|
+
const secretsFile = candidates.find((p) => fs34.existsSync(p)) || candidates[0];
|
|
29965
29978
|
report.secrets.file = secretsFile;
|
|
29966
|
-
if (
|
|
29979
|
+
if (fs34.existsSync(secretsFile)) {
|
|
29967
29980
|
report.secrets.exists = true;
|
|
29968
|
-
for (const line of
|
|
29981
|
+
for (const line of fs34.readFileSync(secretsFile, "utf8").split("\n")) {
|
|
29969
29982
|
const eq = line.indexOf("=");
|
|
29970
29983
|
if (eq > 0 && !line.startsWith("#")) report.secrets.keys.push(line.slice(0, eq).trim());
|
|
29971
29984
|
}
|
|
@@ -30005,10 +30018,10 @@ async function runDoctor(stateDir, opts) {
|
|
|
30005
30018
|
report.missingEnvKeys = [...missing].sort();
|
|
30006
30019
|
const stale = [];
|
|
30007
30020
|
for (const rel of ["workspace/SESSION-STATE.md", "SESSION-STATE.md"]) {
|
|
30008
|
-
const p =
|
|
30021
|
+
const p = path35.join(stateDir, rel);
|
|
30009
30022
|
try {
|
|
30010
|
-
if (!
|
|
30011
|
-
const head =
|
|
30023
|
+
if (!fs34.existsSync(p)) continue;
|
|
30024
|
+
const head = fs34.readFileSync(p, "utf8").split("\n").slice(0, 10).join("\n");
|
|
30012
30025
|
const m = head.match(/^#{1,3}\s*当前时间\s*$\n+\s*(\d{4}-\d{2}-\d{2})/m);
|
|
30013
30026
|
if (!m) continue;
|
|
30014
30027
|
const ageH = (Date.now() - (/* @__PURE__ */ new Date(`${m[1]}T00:00:00Z`)).getTime()) / 36e5;
|
|
@@ -30026,19 +30039,19 @@ function resolveStateDirFromArgs(args) {
|
|
|
30026
30039
|
for (let i = 0; i < args.length; i++) {
|
|
30027
30040
|
if (args[i] === "--state-dir" && args[i + 1]) stateDir = args[++i].trim();
|
|
30028
30041
|
}
|
|
30029
|
-
if (stateDir) return
|
|
30042
|
+
if (stateDir) return path35.resolve(stateDir);
|
|
30030
30043
|
const home = process.env.HOME || process.env.USERPROFILE || ".";
|
|
30031
|
-
const cwd =
|
|
30032
|
-
if (
|
|
30033
|
-
const pointer =
|
|
30034
|
-
if (
|
|
30044
|
+
const cwd = path35.resolve(process.cwd());
|
|
30045
|
+
if (fs34.existsSync(path35.join(cwd, "configs"))) return cwd;
|
|
30046
|
+
const pointer = path35.join(home, ".engine7.json");
|
|
30047
|
+
if (fs34.existsSync(pointer)) {
|
|
30035
30048
|
try {
|
|
30036
|
-
const ptrStateDir = JSON.parse(
|
|
30037
|
-
if (typeof ptrStateDir === "string" && ptrStateDir.trim()) return
|
|
30049
|
+
const ptrStateDir = JSON.parse(fs34.readFileSync(pointer, "utf8")).stateDir;
|
|
30050
|
+
if (typeof ptrStateDir === "string" && ptrStateDir.trim()) return path35.resolve(ptrStateDir);
|
|
30038
30051
|
} catch {
|
|
30039
30052
|
}
|
|
30040
30053
|
}
|
|
30041
|
-
return
|
|
30054
|
+
return path35.join(home, ".engine7");
|
|
30042
30055
|
}
|
|
30043
30056
|
var init_cli_doctor = __esm({
|
|
30044
30057
|
"src/cli-doctor.ts"() {
|
|
@@ -30051,8 +30064,8 @@ var init_cli_doctor = __esm({
|
|
|
30051
30064
|
});
|
|
30052
30065
|
|
|
30053
30066
|
// src/config/writer.ts
|
|
30054
|
-
import
|
|
30055
|
-
import
|
|
30067
|
+
import fs35 from "node:fs";
|
|
30068
|
+
import path36 from "node:path";
|
|
30056
30069
|
function isNormalized(text) {
|
|
30057
30070
|
if (text === "") return true;
|
|
30058
30071
|
if (text.includes("\r")) return false;
|
|
@@ -30067,13 +30080,13 @@ function isNormalized(text) {
|
|
|
30067
30080
|
return minIndent === 2 || minIndent === Infinity;
|
|
30068
30081
|
}
|
|
30069
30082
|
function rotateBaks(filePath) {
|
|
30070
|
-
const dir =
|
|
30071
|
-
const base =
|
|
30072
|
-
const baks =
|
|
30083
|
+
const dir = path36.dirname(filePath);
|
|
30084
|
+
const base = path36.basename(filePath);
|
|
30085
|
+
const baks = fs35.readdirSync(dir).filter((n) => n.startsWith(base + ".bak-")).sort();
|
|
30073
30086
|
while (baks.length >= KEEP_BAKS) {
|
|
30074
30087
|
const victim = baks.shift();
|
|
30075
30088
|
try {
|
|
30076
|
-
|
|
30089
|
+
fs35.unlinkSync(path36.join(dir, victim));
|
|
30077
30090
|
} catch {
|
|
30078
30091
|
}
|
|
30079
30092
|
}
|
|
@@ -30092,7 +30105,7 @@ function writeFailure(filePath, primary, extra) {
|
|
|
30092
30105
|
function renameWithRetry(from, to) {
|
|
30093
30106
|
for (let attempt = 1; ; attempt++) {
|
|
30094
30107
|
try {
|
|
30095
|
-
|
|
30108
|
+
fs35.renameSync(from, to);
|
|
30096
30109
|
return;
|
|
30097
30110
|
} catch (err) {
|
|
30098
30111
|
if (attempt >= RENAME_ATTEMPTS || !RETRYABLE_CODES.has(errCode(err))) throw err;
|
|
@@ -30107,32 +30120,32 @@ function commitFile(tmp, filePath) {
|
|
|
30107
30120
|
} catch (primaryErr) {
|
|
30108
30121
|
const old = `${filePath}.old`;
|
|
30109
30122
|
try {
|
|
30110
|
-
|
|
30123
|
+
fs35.renameSync(filePath, old);
|
|
30111
30124
|
} catch (err) {
|
|
30112
30125
|
throw writeFailure(filePath, primaryErr, `\u6539\u540D .old \u5907\u4EFD\u4E5F\u5931\u8D25\uFF08${errCode(err) || "\u672A\u77E5"}\uFF09`);
|
|
30113
30126
|
}
|
|
30114
30127
|
try {
|
|
30115
|
-
|
|
30128
|
+
fs35.renameSync(tmp, filePath);
|
|
30116
30129
|
} catch (err) {
|
|
30117
30130
|
try {
|
|
30118
|
-
|
|
30131
|
+
fs35.renameSync(old, filePath);
|
|
30119
30132
|
} catch {
|
|
30120
30133
|
throw writeFailure(filePath, primaryErr, `\u65B0\u5185\u5BB9\u843D\u76D8\u4E0E\u56DE\u6EDA\u90FD\u5931\u8D25\uFF0C\u65E7\u5185\u5BB9\u7559\u5728 ${old}`);
|
|
30121
30134
|
}
|
|
30122
30135
|
throw writeFailure(filePath, primaryErr, `\u6362\u540D\u843D\u76D8\u5931\u8D25\uFF08${errCode(err) || "\u672A\u77E5"}\uFF09`);
|
|
30123
30136
|
}
|
|
30124
30137
|
try {
|
|
30125
|
-
|
|
30138
|
+
fs35.unlinkSync(old);
|
|
30126
30139
|
} catch {
|
|
30127
30140
|
}
|
|
30128
30141
|
}
|
|
30129
30142
|
}
|
|
30130
30143
|
function writeConfigAtomic(filePath, obj) {
|
|
30131
|
-
const existed =
|
|
30144
|
+
const existed = fs35.existsSync(filePath);
|
|
30132
30145
|
let prevText = "";
|
|
30133
30146
|
if (existed) {
|
|
30134
30147
|
try {
|
|
30135
|
-
prevText =
|
|
30148
|
+
prevText = fs35.readFileSync(filePath, "utf-8");
|
|
30136
30149
|
} catch (err) {
|
|
30137
30150
|
throw writeFailure(filePath, err);
|
|
30138
30151
|
}
|
|
@@ -30140,27 +30153,27 @@ function writeConfigAtomic(filePath, obj) {
|
|
|
30140
30153
|
const normalized = !existed || !isNormalized(prevText);
|
|
30141
30154
|
if (prevText) {
|
|
30142
30155
|
try {
|
|
30143
|
-
|
|
30156
|
+
fs35.copyFileSync(filePath, `${filePath}.bak-${Date.now()}`);
|
|
30144
30157
|
} catch {
|
|
30145
30158
|
}
|
|
30146
30159
|
rotateBaks(filePath);
|
|
30147
30160
|
}
|
|
30148
30161
|
const content = JSON.stringify(obj, null, 2) + "\n";
|
|
30149
|
-
const tmp =
|
|
30162
|
+
const tmp = path36.join(path36.dirname(filePath), `.${path36.basename(filePath)}.tmp-${process.pid}`);
|
|
30150
30163
|
try {
|
|
30151
|
-
const fd =
|
|
30164
|
+
const fd = fs35.openSync(tmp, "w");
|
|
30152
30165
|
try {
|
|
30153
|
-
|
|
30154
|
-
|
|
30166
|
+
fs35.writeFileSync(fd, content, "utf-8");
|
|
30167
|
+
fs35.fsyncSync(fd);
|
|
30155
30168
|
} finally {
|
|
30156
|
-
|
|
30169
|
+
fs35.closeSync(fd);
|
|
30157
30170
|
}
|
|
30158
30171
|
commitFile(tmp, filePath);
|
|
30159
30172
|
} catch (err) {
|
|
30160
30173
|
throw err instanceof ConfigWriteError ? err : writeFailure(filePath, err);
|
|
30161
30174
|
} finally {
|
|
30162
30175
|
try {
|
|
30163
|
-
|
|
30176
|
+
fs35.unlinkSync(tmp);
|
|
30164
30177
|
} catch {
|
|
30165
30178
|
}
|
|
30166
30179
|
}
|
|
@@ -30186,18 +30199,18 @@ var init_writer2 = __esm({
|
|
|
30186
30199
|
});
|
|
30187
30200
|
|
|
30188
30201
|
// src/config/secrets-io.ts
|
|
30189
|
-
import
|
|
30190
|
-
import
|
|
30202
|
+
import fs36 from "node:fs";
|
|
30203
|
+
import path37 from "node:path";
|
|
30191
30204
|
function resolveSecretPath(stateDir, configName) {
|
|
30192
30205
|
return secretsCandidates(stateDir, configName)[0];
|
|
30193
30206
|
}
|
|
30194
30207
|
function resolveSecretReadPath(stateDir, configName) {
|
|
30195
|
-
return secretsCandidates(stateDir, configName).find((c) =>
|
|
30208
|
+
return secretsCandidates(stateDir, configName).find((c) => fs36.existsSync(c)) ?? null;
|
|
30196
30209
|
}
|
|
30197
30210
|
function readSecretStatus(stateDir, configName, names) {
|
|
30198
30211
|
const p = resolveSecretReadPath(stateDir, configName);
|
|
30199
30212
|
const out = {};
|
|
30200
|
-
const text = p ?
|
|
30213
|
+
const text = p ? fs36.readFileSync(p, "utf-8") : "";
|
|
30201
30214
|
const present = /* @__PURE__ */ new Set();
|
|
30202
30215
|
for (const line of text.split("\n")) {
|
|
30203
30216
|
const t = line.trim();
|
|
@@ -30210,7 +30223,7 @@ function readSecretStatus(stateDir, configName, names) {
|
|
|
30210
30223
|
return out;
|
|
30211
30224
|
}
|
|
30212
30225
|
function writeSecret(stateDir, configName, name, value) {
|
|
30213
|
-
writeSecretsValue(
|
|
30226
|
+
writeSecretsValue(path37.join(stateDir, "configs", `${configName}.json`), name, value);
|
|
30214
30227
|
}
|
|
30215
30228
|
var init_secrets_io = __esm({
|
|
30216
30229
|
"src/config/secrets-io.ts"() {
|
|
@@ -30220,8 +30233,8 @@ var init_secrets_io = __esm({
|
|
|
30220
30233
|
});
|
|
30221
30234
|
|
|
30222
30235
|
// src/config/migrations/index.ts
|
|
30223
|
-
import
|
|
30224
|
-
import
|
|
30236
|
+
import fs37 from "node:fs";
|
|
30237
|
+
import path38 from "node:path";
|
|
30225
30238
|
function registerMigration(m) {
|
|
30226
30239
|
if (REGISTRY.has(m.name)) {
|
|
30227
30240
|
throw new Error(`[migrations] \u8FC1\u79FB "${m.name}" \u91CD\u590D\u6CE8\u518C\u2014\u2014\u540C\u540D\u4F1A\u6309 import \u987A\u5E8F\u9759\u9ED8\u8986\u76D6`);
|
|
@@ -30237,21 +30250,21 @@ async function runMigration(name, ctx) {
|
|
|
30237
30250
|
return await m.run(ctx);
|
|
30238
30251
|
}
|
|
30239
30252
|
function rotateBaks2(filePath) {
|
|
30240
|
-
const dir =
|
|
30241
|
-
const base =
|
|
30242
|
-
const baks =
|
|
30253
|
+
const dir = path38.dirname(filePath);
|
|
30254
|
+
const base = path38.basename(filePath);
|
|
30255
|
+
const baks = fs37.readdirSync(dir).filter((n) => n.startsWith(base + ".bak-")).sort();
|
|
30243
30256
|
while (baks.length > KEEP_BAKS2) {
|
|
30244
30257
|
const victim = baks.shift();
|
|
30245
30258
|
try {
|
|
30246
|
-
|
|
30259
|
+
fs37.unlinkSync(path38.join(dir, victim));
|
|
30247
30260
|
} catch {
|
|
30248
30261
|
}
|
|
30249
30262
|
}
|
|
30250
30263
|
}
|
|
30251
30264
|
function backupFile(filePath) {
|
|
30252
|
-
if (!
|
|
30265
|
+
if (!fs37.existsSync(filePath)) return null;
|
|
30253
30266
|
const bak = `${filePath}.bak-${Date.now()}`;
|
|
30254
|
-
|
|
30267
|
+
fs37.copyFileSync(filePath, bak);
|
|
30255
30268
|
rotateBaks2(filePath);
|
|
30256
30269
|
return bak;
|
|
30257
30270
|
}
|
|
@@ -30265,11 +30278,11 @@ var init_migrations = __esm({
|
|
|
30265
30278
|
});
|
|
30266
30279
|
|
|
30267
30280
|
// src/config/migrations/persona.ts
|
|
30268
|
-
import
|
|
30269
|
-
import
|
|
30281
|
+
import fs38 from "node:fs";
|
|
30282
|
+
import path39 from "node:path";
|
|
30270
30283
|
function readFileOrNull(p) {
|
|
30271
30284
|
try {
|
|
30272
|
-
return
|
|
30285
|
+
return fs38.readFileSync(p, "utf-8");
|
|
30273
30286
|
} catch {
|
|
30274
30287
|
return null;
|
|
30275
30288
|
}
|
|
@@ -30289,22 +30302,22 @@ var init_persona = __esm({
|
|
|
30289
30302
|
run(ctx) {
|
|
30290
30303
|
const persona = ctx.values?.agents?.defaults?.persona;
|
|
30291
30304
|
if (typeof persona !== "string" || !persona) return { changed: [] };
|
|
30292
|
-
const dir =
|
|
30293
|
-
if (!
|
|
30305
|
+
const dir = path39.join(ctx.workspace, "personas", persona);
|
|
30306
|
+
if (!fs38.existsSync(dir)) {
|
|
30294
30307
|
return { changed: [] };
|
|
30295
30308
|
}
|
|
30296
30309
|
const changed = [];
|
|
30297
30310
|
for (const name of POINTER_FILES) {
|
|
30298
|
-
const src =
|
|
30311
|
+
const src = path39.join(dir, name);
|
|
30299
30312
|
const content = readFileOrNull(src);
|
|
30300
30313
|
if (content === null) continue;
|
|
30301
|
-
const legacy =
|
|
30314
|
+
const legacy = path39.join(ctx.workspace, LEGACY_PATHS[name]);
|
|
30302
30315
|
const legacyContent = readFileOrNull(legacy);
|
|
30303
30316
|
if (legacyContent !== null && legacyContent === content) {
|
|
30304
|
-
|
|
30317
|
+
fs38.renameSync(legacy, `${legacy}.migrated-${Date.now()}`);
|
|
30305
30318
|
changed.push(`${LEGACY_PATHS[name]} \u2192 personas/${persona}/${name}`);
|
|
30306
30319
|
} else if (legacyContent !== null) {
|
|
30307
|
-
|
|
30320
|
+
fs38.renameSync(legacy, `${legacy}.bak-${Date.now()}`);
|
|
30308
30321
|
changed.push(`${LEGACY_PATHS[name]} \u2192 .bak\uFF08\u5185\u5BB9\u4E0E\u6A21\u677F\u4E0D\u540C\uFF0C\u4FDD\u5B88\u4FDD\u7559\uFF09`);
|
|
30309
30322
|
}
|
|
30310
30323
|
}
|
|
@@ -30316,7 +30329,7 @@ var init_persona = __esm({
|
|
|
30316
30329
|
});
|
|
30317
30330
|
|
|
30318
30331
|
// src/config/migrations/channel-secrets.ts
|
|
30319
|
-
import
|
|
30332
|
+
import fs39 from "node:fs";
|
|
30320
30333
|
function envNameFor(dotPath) {
|
|
30321
30334
|
const declared = getField(dotPath)?.envKey;
|
|
30322
30335
|
if (declared) return declared;
|
|
@@ -30358,15 +30371,15 @@ function planChannelSecretMoves(config) {
|
|
|
30358
30371
|
}
|
|
30359
30372
|
function restoreEnv(envPath, before) {
|
|
30360
30373
|
try {
|
|
30361
|
-
if (before === null)
|
|
30362
|
-
else
|
|
30374
|
+
if (before === null) fs39.unlinkSync(envPath);
|
|
30375
|
+
else fs39.writeFileSync(envPath, before, "utf8");
|
|
30363
30376
|
} catch {
|
|
30364
30377
|
}
|
|
30365
30378
|
}
|
|
30366
30379
|
function dropBackup(backup) {
|
|
30367
30380
|
if (backup) {
|
|
30368
30381
|
try {
|
|
30369
|
-
|
|
30382
|
+
fs39.unlinkSync(backup);
|
|
30370
30383
|
} catch {
|
|
30371
30384
|
}
|
|
30372
30385
|
}
|
|
@@ -30375,7 +30388,7 @@ function migrateChannelSecrets(configPath, deps = {}) {
|
|
|
30375
30388
|
const writeConfig = deps.writeConfig ?? ((p, obj) => writeConfigAtomic(p, obj));
|
|
30376
30389
|
let text;
|
|
30377
30390
|
try {
|
|
30378
|
-
text =
|
|
30391
|
+
text = fs39.readFileSync(configPath, "utf-8");
|
|
30379
30392
|
} catch {
|
|
30380
30393
|
return { changed: [], backup: null, secretsFile: null };
|
|
30381
30394
|
}
|
|
@@ -30392,7 +30405,7 @@ function migrateChannelSecrets(configPath, deps = {}) {
|
|
|
30392
30405
|
if (moves.length === 0) return { changed: [], backup: null, secretsFile: null };
|
|
30393
30406
|
const { stateDir, configName } = resolveConfigIdentity(configPath);
|
|
30394
30407
|
const envPath = secretsCandidates(stateDir, configName)[0];
|
|
30395
|
-
const envBefore =
|
|
30408
|
+
const envBefore = fs39.existsSync(envPath) ? fs39.readFileSync(envPath, "utf-8") : null;
|
|
30396
30409
|
const backup = backupFile(configPath);
|
|
30397
30410
|
try {
|
|
30398
30411
|
for (const m of moves) writeSecret(stateDir, configName, m.envName, m.value);
|
|
@@ -30413,7 +30426,7 @@ function migrateChannelSecrets(configPath, deps = {}) {
|
|
|
30413
30426
|
const problem = verify(configPath, envPath, moves);
|
|
30414
30427
|
if (problem) {
|
|
30415
30428
|
try {
|
|
30416
|
-
if (backup)
|
|
30429
|
+
if (backup) fs39.copyFileSync(backup, configPath);
|
|
30417
30430
|
} catch {
|
|
30418
30431
|
}
|
|
30419
30432
|
restoreEnv(envPath, envBefore);
|
|
@@ -30425,7 +30438,7 @@ function migrateChannelSecrets(configPath, deps = {}) {
|
|
|
30425
30438
|
function verify(configPath, envPath, moves) {
|
|
30426
30439
|
let cfg;
|
|
30427
30440
|
try {
|
|
30428
|
-
cfg = JSON.parse(
|
|
30441
|
+
cfg = JSON.parse(fs39.readFileSync(configPath, "utf-8"));
|
|
30429
30442
|
} catch (e) {
|
|
30430
30443
|
return `config \u8BFB\u4E0D\u56DE\u6765\u4E86\uFF08${e?.message || String(e)}\uFF09`;
|
|
30431
30444
|
}
|
|
@@ -30435,7 +30448,7 @@ function verify(configPath, envPath, moves) {
|
|
|
30435
30448
|
}
|
|
30436
30449
|
let env = "";
|
|
30437
30450
|
try {
|
|
30438
|
-
env =
|
|
30451
|
+
env = fs39.readFileSync(envPath, "utf-8");
|
|
30439
30452
|
} catch (e) {
|
|
30440
30453
|
return `secrets \u6587\u4EF6\u8BFB\u4E0D\u56DE\u6765\uFF08${e?.message || String(e)}\uFF09`;
|
|
30441
30454
|
}
|
|
@@ -30473,14 +30486,14 @@ __export(cli_config_exports, {
|
|
|
30473
30486
|
isSafeConfigName: () => isSafeConfigName,
|
|
30474
30487
|
runConfigCommand: () => runConfigCommand
|
|
30475
30488
|
});
|
|
30476
|
-
import
|
|
30477
|
-
import
|
|
30489
|
+
import fs40 from "node:fs";
|
|
30490
|
+
import path40 from "node:path";
|
|
30478
30491
|
function isSafeConfigName(name) {
|
|
30479
30492
|
return /^[\w.-]+$/.test(name);
|
|
30480
30493
|
}
|
|
30481
30494
|
function sameDir(a, b) {
|
|
30482
30495
|
const norm = (s) => {
|
|
30483
|
-
const r =
|
|
30496
|
+
const r = path40.resolve(s);
|
|
30484
30497
|
return process.platform === "win32" ? r.toLowerCase() : r;
|
|
30485
30498
|
};
|
|
30486
30499
|
return norm(a) === norm(b);
|
|
@@ -30508,7 +30521,7 @@ function parseArgs(args) {
|
|
|
30508
30521
|
badArgs.push(a);
|
|
30509
30522
|
}
|
|
30510
30523
|
if (config) {
|
|
30511
|
-
const configPath =
|
|
30524
|
+
const configPath = path40.resolve(config);
|
|
30512
30525
|
if (!/\.json$/i.test(configPath)) {
|
|
30513
30526
|
return {
|
|
30514
30527
|
stateDir,
|
|
@@ -30532,9 +30545,9 @@ function parseArgs(args) {
|
|
|
30532
30545
|
}
|
|
30533
30546
|
return { stateDir: ident.stateDir, configPath, configName: ident.configName, file: file2, badArgs };
|
|
30534
30547
|
}
|
|
30535
|
-
if (!stateDir) stateDir = process.env.ENGINE_STATE_DIR ||
|
|
30548
|
+
if (!stateDir) stateDir = process.env.ENGINE_STATE_DIR || path40.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
30536
30549
|
const configName = CONFIG_NAME;
|
|
30537
|
-
return { stateDir, configPath:
|
|
30550
|
+
return { stateDir, configPath: path40.join(stateDir, "configs", `${configName}.json`), configName, file: file2, badArgs };
|
|
30538
30551
|
}
|
|
30539
30552
|
function emit2(obj) {
|
|
30540
30553
|
process.stdout.write(JSON.stringify(obj) + "\n");
|
|
@@ -30572,7 +30585,7 @@ function shapeOf(v) {
|
|
|
30572
30585
|
function readConfigObject(configPath) {
|
|
30573
30586
|
let text;
|
|
30574
30587
|
try {
|
|
30575
|
-
text =
|
|
30588
|
+
text = fs40.readFileSync(configPath, "utf-8");
|
|
30576
30589
|
} catch {
|
|
30577
30590
|
return { obj: {}, corrupt: false };
|
|
30578
30591
|
}
|
|
@@ -30630,7 +30643,7 @@ function findMaskedCredentials(value, prefix, out) {
|
|
|
30630
30643
|
function readEnvKeys(file2) {
|
|
30631
30644
|
const out = [];
|
|
30632
30645
|
try {
|
|
30633
|
-
for (const line of
|
|
30646
|
+
for (const line of fs40.readFileSync(file2, "utf-8").split("\n")) {
|
|
30634
30647
|
const t = line.trim();
|
|
30635
30648
|
if (!t || t.startsWith("#")) continue;
|
|
30636
30649
|
const eq = t.indexOf("=");
|
|
@@ -30686,7 +30699,7 @@ async function runConfigCommand(args) {
|
|
|
30686
30699
|
}
|
|
30687
30700
|
let parsedPayload;
|
|
30688
30701
|
try {
|
|
30689
|
-
parsedPayload = JSON.parse(
|
|
30702
|
+
parsedPayload = JSON.parse(fs40.readFileSync(p.file, "utf-8"));
|
|
30690
30703
|
} catch (e) {
|
|
30691
30704
|
process.stderr.write(`[config] \u8BFB\u4E0D\u4E86 payload: ${e.message}
|
|
30692
30705
|
`);
|
|
@@ -30792,7 +30805,7 @@ async function runConfigCommand(args) {
|
|
|
30792
30805
|
}
|
|
30793
30806
|
if (secretWrites.length > 0) {
|
|
30794
30807
|
const writePath2 = resolveSecretPath(p.stateDir, p.configName);
|
|
30795
|
-
const fallback =
|
|
30808
|
+
const fallback = fs40.existsSync(writePath2) ? void 0 : secretsCandidates(p.stateDir, p.configName).find((c) => fs40.existsSync(c));
|
|
30796
30809
|
if (fallback) {
|
|
30797
30810
|
const writing = new Set(secretWrites.map((s) => s.name));
|
|
30798
30811
|
const others = readEnvKeys(fallback).filter((k) => !writing.has(k));
|
|
@@ -30801,11 +30814,11 @@ async function runConfigCommand(args) {
|
|
|
30801
30814
|
}
|
|
30802
30815
|
}
|
|
30803
30816
|
}
|
|
30804
|
-
if (
|
|
30817
|
+
if (fs40.existsSync(p.configPath) && !isNormalized(fs40.readFileSync(p.configPath, "utf-8"))) {
|
|
30805
30818
|
warnings.push("config \u9996\u6B21\u89C4\u8303\u5316\uFF1A\u884C\u5C3E\u7EDF\u4E00\u4E3A LF\u3001\u7F29\u8FDB\u7EDF\u4E00\u4E3A 2 \u7A7A\u683C\uFF08\u4E00\u6B21\u6027\u5927 diff\uFF09");
|
|
30806
30819
|
}
|
|
30807
|
-
const configDir =
|
|
30808
|
-
if (!
|
|
30820
|
+
const configDir = path40.dirname(p.configPath);
|
|
30821
|
+
if (!fs40.existsSync(configDir)) fs40.mkdirSync(configDir, { recursive: true });
|
|
30809
30822
|
try {
|
|
30810
30823
|
writeConfigAtomic(p.configPath, merged);
|
|
30811
30824
|
} catch (e) {
|
|
@@ -30820,7 +30833,7 @@ async function runConfigCommand(args) {
|
|
|
30820
30833
|
warnings.push(`secrets \u5199\u5165\u5931\u8D25\uFF08${s.name}\uFF09\uFF1A${e?.message || String(e)}\u2014\u2014config \u5DF2\u5199\u5165`);
|
|
30821
30834
|
}
|
|
30822
30835
|
}
|
|
30823
|
-
const workspace =
|
|
30836
|
+
const workspace = path40.join(p.stateDir, "workspace");
|
|
30824
30837
|
const ctx = { workspace, stateDir: p.stateDir, values: nested, all: merged, configPath: p.configPath };
|
|
30825
30838
|
for (const dotPath of [...new Set(changed)]) {
|
|
30826
30839
|
const migrationName = getField(dotPath)?.migration;
|
|
@@ -30909,41 +30922,41 @@ __export(cli_reconfig_exports, {
|
|
|
30909
30922
|
doReconfigFeishu: () => doReconfigFeishu,
|
|
30910
30923
|
doReconfigWechat: () => doReconfigWechat
|
|
30911
30924
|
});
|
|
30912
|
-
import * as
|
|
30913
|
-
import * as
|
|
30925
|
+
import * as fs41 from "node:fs";
|
|
30926
|
+
import * as path41 from "node:path";
|
|
30914
30927
|
function scanForChannelsConfig(configsDir) {
|
|
30915
|
-
if (!
|
|
30916
|
-
for (const f of
|
|
30917
|
-
const full =
|
|
30928
|
+
if (!fs41.existsSync(configsDir)) return "";
|
|
30929
|
+
for (const f of fs41.readdirSync(configsDir).filter((x) => x.endsWith(".json"))) {
|
|
30930
|
+
const full = path41.join(configsDir, f);
|
|
30918
30931
|
try {
|
|
30919
|
-
if (JSON.parse(
|
|
30932
|
+
if (JSON.parse(fs41.readFileSync(full, "utf8")).channels) return full;
|
|
30920
30933
|
} catch {
|
|
30921
30934
|
}
|
|
30922
30935
|
}
|
|
30923
30936
|
return "";
|
|
30924
30937
|
}
|
|
30925
30938
|
function findFeishuConfigFile(stateDir, configName) {
|
|
30926
|
-
const configsDir =
|
|
30939
|
+
const configsDir = path41.join(stateDir, "configs");
|
|
30927
30940
|
if (configName) {
|
|
30928
|
-
const p =
|
|
30929
|
-
if (
|
|
30941
|
+
const p = path41.join(configsDir, configName);
|
|
30942
|
+
if (fs41.existsSync(p)) return p;
|
|
30930
30943
|
}
|
|
30931
30944
|
return scanForChannelsConfig(configsDir);
|
|
30932
30945
|
}
|
|
30933
30946
|
function findWechatConfigFile(stateDir, configName) {
|
|
30934
|
-
const configsDir =
|
|
30947
|
+
const configsDir = path41.join(stateDir, "configs");
|
|
30935
30948
|
if (configName) {
|
|
30936
|
-
const p =
|
|
30937
|
-
return
|
|
30949
|
+
const p = path41.join(configsDir, configName);
|
|
30950
|
+
return fs41.existsSync(p) ? p : "";
|
|
30938
30951
|
}
|
|
30939
30952
|
const scanned = scanForChannelsConfig(configsDir);
|
|
30940
30953
|
if (scanned) return scanned;
|
|
30941
|
-
if (
|
|
30942
|
-
const candidates =
|
|
30954
|
+
if (fs41.existsSync(configsDir)) {
|
|
30955
|
+
const candidates = fs41.readdirSync(configsDir).filter((f) => f.endsWith(".json"));
|
|
30943
30956
|
if (candidates.length) {
|
|
30944
|
-
const first =
|
|
30957
|
+
const first = path41.join(configsDir, candidates[0]);
|
|
30945
30958
|
try {
|
|
30946
|
-
JSON.parse(
|
|
30959
|
+
JSON.parse(fs41.readFileSync(first, "utf8"));
|
|
30947
30960
|
return first;
|
|
30948
30961
|
} catch {
|
|
30949
30962
|
}
|
|
@@ -30982,11 +30995,11 @@ async function doReconfigFeishu(opts) {
|
|
|
30982
30995
|
return 2;
|
|
30983
30996
|
}
|
|
30984
30997
|
const configFile = findFeishuConfigFile(stateDir, configName);
|
|
30985
|
-
if (configFile &&
|
|
30998
|
+
if (configFile && fs41.existsSync(configFile)) {
|
|
30986
30999
|
if (events) emit3?.({ event: "progress", step: "write_config" });
|
|
30987
31000
|
let j;
|
|
30988
31001
|
try {
|
|
30989
|
-
j = JSON.parse(
|
|
31002
|
+
j = JSON.parse(fs41.readFileSync(configFile, "utf8"));
|
|
30990
31003
|
} catch (err) {
|
|
30991
31004
|
if (events) emit3?.({ event: "error", message: `\u8BFB\u53D6 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09` });
|
|
30992
31005
|
else console.error(`\u274C \u8BFB\u53D6 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09`);
|
|
@@ -31004,7 +31017,7 @@ async function doReconfigFeishu(opts) {
|
|
|
31004
31017
|
}
|
|
31005
31018
|
j.channels.feishu = { enabled: true, appId: result.appId, appSecret: secretRef(feishuSecretEnv, result.appSecret), connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" };
|
|
31006
31019
|
try {
|
|
31007
|
-
|
|
31020
|
+
fs41.writeFileSync(configFile, JSON.stringify(j, null, 2), "utf8");
|
|
31008
31021
|
} catch (err) {
|
|
31009
31022
|
if (events) emit3?.({ event: "error", message: `\u5199\u5165 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09` });
|
|
31010
31023
|
else console.error(`\u274C \u5199\u5165 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09`);
|
|
@@ -31037,7 +31050,7 @@ async function doReconfigWechat(opts) {
|
|
|
31037
31050
|
return 2;
|
|
31038
31051
|
}
|
|
31039
31052
|
const configFile = findWechatConfigFile(stateDir, configName);
|
|
31040
|
-
if (!configFile || !
|
|
31053
|
+
if (!configFile || !fs41.existsSync(configFile)) {
|
|
31041
31054
|
console.log("\n\u26A0\uFE0F \u6CA1\u627E\u5230 config \u6587\u4EF6\uFF0C\u8BF7\u624B\u52A8\u628A\u4EE5\u4E0B\u6BB5\u52A0\u8FDB\u4F60\u7684 config \u7684 channels \u91CC\uFF1A");
|
|
31042
31055
|
console.log(JSON.stringify({ wechat: { enabled: true, token: cred.token, accountId: cred.accountId, dmPolicy: "pairing", group: { policy: "disabled" } } }, null, 2));
|
|
31043
31056
|
if (events) emit3?.({ event: "done", channel: "wechat", detail: cred.accountId, restart_required: true });
|
|
@@ -31046,7 +31059,7 @@ async function doReconfigWechat(opts) {
|
|
|
31046
31059
|
if (events) emit3?.({ event: "progress", step: "write_config" });
|
|
31047
31060
|
let j;
|
|
31048
31061
|
try {
|
|
31049
|
-
j = JSON.parse(
|
|
31062
|
+
j = JSON.parse(fs41.readFileSync(configFile, "utf8"));
|
|
31050
31063
|
} catch (err) {
|
|
31051
31064
|
if (events) emit3?.({ event: "error", message: `\u8BFB\u53D6 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09` });
|
|
31052
31065
|
else console.error(`\u274C \u8BFB\u53D6 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09`);
|
|
@@ -31064,7 +31077,7 @@ async function doReconfigWechat(opts) {
|
|
|
31064
31077
|
}
|
|
31065
31078
|
j.channels.wechat = { enabled: true, token: secretRef(wechatSecretEnv, cred.token), accountId: cred.accountId, dmPolicy: "pairing", group: { policy: "disabled" } };
|
|
31066
31079
|
try {
|
|
31067
|
-
|
|
31080
|
+
fs41.writeFileSync(configFile, JSON.stringify(j, null, 2), "utf8");
|
|
31068
31081
|
} catch (err) {
|
|
31069
31082
|
if (events) emit3?.({ event: "error", message: `\u5199\u5165 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09` });
|
|
31070
31083
|
else console.error(`\u274C \u5199\u5165 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09`);
|
|
@@ -31101,20 +31114,20 @@ __export(cli_travel_exports, {
|
|
|
31101
31114
|
resolveArchiveForTest: () => resolveArchiveForTest,
|
|
31102
31115
|
saveTravelConfig: () => saveTravelConfig
|
|
31103
31116
|
});
|
|
31104
|
-
import * as
|
|
31105
|
-
import * as
|
|
31117
|
+
import * as path42 from "node:path";
|
|
31118
|
+
import * as fs42 from "node:fs";
|
|
31106
31119
|
import * as os6 from "node:os";
|
|
31107
|
-
import { execSync as
|
|
31120
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
31108
31121
|
function loadTravelConfig() {
|
|
31109
31122
|
try {
|
|
31110
|
-
if (!
|
|
31111
|
-
return JSON.parse(
|
|
31123
|
+
if (!fs42.existsSync(CONFIG_PATH)) return null;
|
|
31124
|
+
return JSON.parse(fs42.readFileSync(CONFIG_PATH, "utf-8"));
|
|
31112
31125
|
} catch {
|
|
31113
31126
|
return null;
|
|
31114
31127
|
}
|
|
31115
31128
|
}
|
|
31116
31129
|
function saveTravelConfig(cfg) {
|
|
31117
|
-
|
|
31130
|
+
fs42.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
|
|
31118
31131
|
}
|
|
31119
31132
|
function sanitizeContent(content, dirs) {
|
|
31120
31133
|
let result = content;
|
|
@@ -31139,7 +31152,7 @@ function restoreContent(content, dirs) {
|
|
|
31139
31152
|
return result;
|
|
31140
31153
|
}
|
|
31141
31154
|
function isTextFile(filePath) {
|
|
31142
|
-
const ext =
|
|
31155
|
+
const ext = path42.extname(filePath).toLowerCase();
|
|
31143
31156
|
return TEXT_EXTENSIONS.has(ext);
|
|
31144
31157
|
}
|
|
31145
31158
|
function shouldExclude(name) {
|
|
@@ -31154,14 +31167,14 @@ function shouldExclude(name) {
|
|
|
31154
31167
|
}
|
|
31155
31168
|
function collectFiles(rootDir, includeSet, optionalSet) {
|
|
31156
31169
|
const files = [];
|
|
31157
|
-
const entries2 =
|
|
31170
|
+
const entries2 = fs42.readdirSync(rootDir, { withFileTypes: true });
|
|
31158
31171
|
for (const entry of entries2) {
|
|
31159
31172
|
if (shouldExclude(entry.name)) continue;
|
|
31160
|
-
const fullPath =
|
|
31161
|
-
const realPath =
|
|
31173
|
+
const fullPath = path42.join(rootDir, entry.name);
|
|
31174
|
+
const realPath = fs42.realpathSync(fullPath);
|
|
31162
31175
|
if (realPath !== fullPath) {
|
|
31163
31176
|
try {
|
|
31164
|
-
const lstat =
|
|
31177
|
+
const lstat = fs42.lstatSync(fullPath);
|
|
31165
31178
|
if (lstat.isSymbolicLink()) {
|
|
31166
31179
|
continue;
|
|
31167
31180
|
}
|
|
@@ -31182,12 +31195,12 @@ function collectFiles(rootDir, includeSet, optionalSet) {
|
|
|
31182
31195
|
function collectAllFiles(dir) {
|
|
31183
31196
|
const files = [];
|
|
31184
31197
|
try {
|
|
31185
|
-
const entries2 =
|
|
31198
|
+
const entries2 = fs42.readdirSync(dir, { withFileTypes: true });
|
|
31186
31199
|
for (const entry of entries2) {
|
|
31187
31200
|
if (shouldExclude(entry.name)) continue;
|
|
31188
|
-
const fullPath =
|
|
31201
|
+
const fullPath = path42.join(dir, entry.name);
|
|
31189
31202
|
try {
|
|
31190
|
-
if (
|
|
31203
|
+
if (fs42.lstatSync(fullPath).isSymbolicLink()) continue;
|
|
31191
31204
|
} catch {
|
|
31192
31205
|
}
|
|
31193
31206
|
if (entry.isDirectory()) {
|
|
@@ -31202,16 +31215,16 @@ function collectAllFiles(dir) {
|
|
|
31202
31215
|
}
|
|
31203
31216
|
function readMainEngineUuid(agentsDir) {
|
|
31204
31217
|
try {
|
|
31205
|
-
const platformMapPath =
|
|
31206
|
-
const indexMapPath =
|
|
31207
|
-
if (!
|
|
31208
|
-
const platformMap = JSON.parse(
|
|
31218
|
+
const platformMapPath = path42.join(agentsDir, "main", "sessions", "platform-map.json");
|
|
31219
|
+
const indexMapPath = path42.join(agentsDir, "main", "sessions", "session-index.json");
|
|
31220
|
+
if (!fs42.existsSync(platformMapPath) || !fs42.existsSync(indexMapPath)) return null;
|
|
31221
|
+
const platformMap = JSON.parse(fs42.readFileSync(platformMapPath, "utf-8"));
|
|
31209
31222
|
const mainPlatformId = platformMap["scope:main"] || platformMap["main"];
|
|
31210
31223
|
if (!mainPlatformId) return null;
|
|
31211
|
-
const indexMap = JSON.parse(
|
|
31224
|
+
const indexMap = JSON.parse(fs42.readFileSync(indexMapPath, "utf-8"));
|
|
31212
31225
|
const entry = indexMap[mainPlatformId];
|
|
31213
31226
|
if (!entry || !entry.file) return null;
|
|
31214
|
-
const basename10 =
|
|
31227
|
+
const basename10 = path42.basename(entry.file).replace(/\.jsonl$/, "");
|
|
31215
31228
|
return basename10;
|
|
31216
31229
|
} catch {
|
|
31217
31230
|
return null;
|
|
@@ -31219,13 +31232,13 @@ function readMainEngineUuid(agentsDir) {
|
|
|
31219
31232
|
}
|
|
31220
31233
|
function collectRecentSessions(agentsDir, _days = 7) {
|
|
31221
31234
|
const files = [];
|
|
31222
|
-
if (!
|
|
31235
|
+
if (!fs42.existsSync(agentsDir)) return files;
|
|
31223
31236
|
const sessionGroups = /* @__PURE__ */ new Map();
|
|
31224
31237
|
function scanSessionsDir(dir) {
|
|
31225
31238
|
try {
|
|
31226
|
-
const entries2 =
|
|
31239
|
+
const entries2 = fs42.readdirSync(dir, { withFileTypes: true });
|
|
31227
31240
|
for (const entry of entries2) {
|
|
31228
|
-
const fullPath =
|
|
31241
|
+
const fullPath = path42.join(dir, entry.name);
|
|
31229
31242
|
if (entry.isDirectory()) {
|
|
31230
31243
|
scanSessionsDir(fullPath);
|
|
31231
31244
|
continue;
|
|
@@ -31249,7 +31262,7 @@ function collectRecentSessions(agentsDir, _days = 7) {
|
|
|
31249
31262
|
if (entry.name.endsWith(".jsonl")) {
|
|
31250
31263
|
group.jsonl = fullPath;
|
|
31251
31264
|
} else {
|
|
31252
|
-
const stat4 =
|
|
31265
|
+
const stat4 = fs42.statSync(fullPath);
|
|
31253
31266
|
group.archived.push({ file: fullPath, mtime: stat4.mtimeMs });
|
|
31254
31267
|
}
|
|
31255
31268
|
}
|
|
@@ -31268,21 +31281,21 @@ function collectRecentSessions(agentsDir, _days = 7) {
|
|
|
31268
31281
|
}
|
|
31269
31282
|
function collectExportFileSet(stateDir, workspace) {
|
|
31270
31283
|
const wsFiles = collectFiles(workspace, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL);
|
|
31271
|
-
const sessionFiles = collectRecentSessions(
|
|
31272
|
-
const configsDir =
|
|
31284
|
+
const sessionFiles = collectRecentSessions(path42.join(stateDir, "agents"), 7);
|
|
31285
|
+
const configsDir = path42.join(stateDir, "configs");
|
|
31273
31286
|
const configFiles = [];
|
|
31274
|
-
if (
|
|
31287
|
+
if (fs42.existsSync(configsDir)) {
|
|
31275
31288
|
for (const f of collectAllFiles(configsDir)) {
|
|
31276
|
-
if (shouldExclude(
|
|
31289
|
+
if (shouldExclude(path42.basename(f))) continue;
|
|
31277
31290
|
configFiles.push(f);
|
|
31278
31291
|
}
|
|
31279
31292
|
}
|
|
31280
31293
|
const EVEROS_SKIP = /* @__PURE__ */ new Set([".tmp", ".lock", "import.log", "import_progress.json"]);
|
|
31281
|
-
const everosDir =
|
|
31294
|
+
const everosDir = path42.join(stateDir, ".everos");
|
|
31282
31295
|
const everosFiles = [];
|
|
31283
|
-
if (
|
|
31296
|
+
if (fs42.existsSync(everosDir)) {
|
|
31284
31297
|
for (const f of collectAllFiles(everosDir)) {
|
|
31285
|
-
if (EVEROS_SKIP.has(
|
|
31298
|
+
if (EVEROS_SKIP.has(path42.basename(f))) continue;
|
|
31286
31299
|
everosFiles.push(f);
|
|
31287
31300
|
}
|
|
31288
31301
|
}
|
|
@@ -31290,13 +31303,13 @@ function collectExportFileSet(stateDir, workspace) {
|
|
|
31290
31303
|
}
|
|
31291
31304
|
async function doExport(opts) {
|
|
31292
31305
|
const { agentName, stateDir, note, dryRun: dryRun2 } = opts;
|
|
31293
|
-
const workspace = (opts.workspace ||
|
|
31294
|
-
const engineHome =
|
|
31306
|
+
const workspace = (opts.workspace || path42.join(stateDir, "workspace")).replace(/[/\\]+$/, "");
|
|
31307
|
+
const engineHome = path42.join(os6.homedir(), ".engine7").replace(/[/\\]+$/, "");
|
|
31295
31308
|
console.log(`\u{1F4E6} engine7 export`);
|
|
31296
31309
|
console.log(` agent: ${agentName}`);
|
|
31297
31310
|
console.log(` state: ${stateDir}`);
|
|
31298
31311
|
console.log(` workspace: ${workspace}`);
|
|
31299
|
-
if (!
|
|
31312
|
+
if (!fs42.existsSync(workspace)) {
|
|
31300
31313
|
console.error(`\u274C workspace \u4E0D\u5B58\u5728: ${workspace}`);
|
|
31301
31314
|
process.exit(1);
|
|
31302
31315
|
}
|
|
@@ -31305,16 +31318,16 @@ async function doExport(opts) {
|
|
|
31305
31318
|
console.log(` workspace \u6587\u4EF6: ${wsFiles.length}`);
|
|
31306
31319
|
console.log(` session jsonl: ${sessionFiles.length} (\u6700\u8FD17\u5929)`);
|
|
31307
31320
|
console.log(` configs: ${configFiles.length}`);
|
|
31308
|
-
console.log(` everos: ${everosFiles.length} (${(everosFiles.reduce((s, f) => s +
|
|
31321
|
+
console.log(` everos: ${everosFiles.length} (${(everosFiles.reduce((s, f) => s + fs42.statSync(f).size, 0) / 1024 / 1024).toFixed(1)} MB)`);
|
|
31309
31322
|
if (dryRun2) {
|
|
31310
31323
|
console.log(`
|
|
31311
31324
|
[DRY RUN] \u4F1A\u6253\u5305\u4EE5\u4E0B\u6587\u4EF6:`);
|
|
31312
|
-
wsFiles.slice(0, 20).forEach((f) => console.log(` ${
|
|
31325
|
+
wsFiles.slice(0, 20).forEach((f) => console.log(` ${path42.relative(workspace, f)}`));
|
|
31313
31326
|
if (wsFiles.length > 20) console.log(` ... \u8FD8\u6709 ${wsFiles.length - 20} \u4E2A\u6587\u4EF6`);
|
|
31314
31327
|
if (everosFiles.length > 0) {
|
|
31315
31328
|
console.log(`
|
|
31316
31329
|
[DRY RUN] everos (${everosFiles.length} \u6587\u4EF6):`);
|
|
31317
|
-
everosFiles.slice(0, 10).forEach((f) => console.log(` ${
|
|
31330
|
+
everosFiles.slice(0, 10).forEach((f) => console.log(` ${path42.relative(stateDir, f)}`));
|
|
31318
31331
|
if (everosFiles.length > 10) console.log(` ... \u8FD8\u6709 ${everosFiles.length - 10} \u4E2A\u6587\u4EF6`);
|
|
31319
31332
|
}
|
|
31320
31333
|
console.log(`
|
|
@@ -31322,46 +31335,46 @@ async function doExport(opts) {
|
|
|
31322
31335
|
return;
|
|
31323
31336
|
}
|
|
31324
31337
|
const version = formatLog().replace(/[-: ]/g, "").slice(0, 12).replace(/(d{8})(d{4})/, "$1-$2");
|
|
31325
|
-
const tmpDir =
|
|
31326
|
-
|
|
31327
|
-
const stagingDir =
|
|
31328
|
-
|
|
31338
|
+
const tmpDir = path42.join(os6.tmpdir(), `engine7-export-${agentName}-${version}`);
|
|
31339
|
+
fs42.mkdirSync(tmpDir, { recursive: true });
|
|
31340
|
+
const stagingDir = path42.join(tmpDir, agentName);
|
|
31341
|
+
fs42.mkdirSync(stagingDir, { recursive: true });
|
|
31329
31342
|
let fileCount = 0;
|
|
31330
31343
|
let totalSize = 0;
|
|
31331
31344
|
let copyFail = 0;
|
|
31332
31345
|
const copyOne = (srcFile, relRoot, destRoot) => {
|
|
31333
|
-
const relPath =
|
|
31334
|
-
const destFile =
|
|
31335
|
-
|
|
31346
|
+
const relPath = path42.relative(relRoot, srcFile);
|
|
31347
|
+
const destFile = path42.join(destRoot, relPath);
|
|
31348
|
+
fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
|
|
31336
31349
|
try {
|
|
31337
31350
|
if (isTextFile(srcFile)) {
|
|
31338
|
-
const content =
|
|
31339
|
-
|
|
31351
|
+
const content = fs42.readFileSync(srcFile, "utf-8");
|
|
31352
|
+
fs42.writeFileSync(destFile, sanitizeContent(content, dirs));
|
|
31340
31353
|
} else {
|
|
31341
|
-
|
|
31354
|
+
fs42.copyFileSync(srcFile, destFile);
|
|
31342
31355
|
}
|
|
31343
31356
|
fileCount++;
|
|
31344
|
-
totalSize +=
|
|
31357
|
+
totalSize += fs42.statSync(srcFile).size;
|
|
31345
31358
|
} catch (e) {
|
|
31346
31359
|
copyFail++;
|
|
31347
31360
|
console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
|
|
31348
31361
|
}
|
|
31349
31362
|
};
|
|
31350
|
-
for (const srcFile of wsFiles) copyOne(srcFile, workspace,
|
|
31363
|
+
for (const srcFile of wsFiles) copyOne(srcFile, workspace, path42.join(stagingDir, "workspace"));
|
|
31351
31364
|
for (const srcFile of sessionFiles) {
|
|
31352
|
-
const relPath =
|
|
31353
|
-
const destFile =
|
|
31354
|
-
|
|
31365
|
+
const relPath = path42.relative(stateDir, srcFile);
|
|
31366
|
+
const destFile = path42.join(stagingDir, relPath);
|
|
31367
|
+
fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
|
|
31355
31368
|
try {
|
|
31356
|
-
let content =
|
|
31369
|
+
let content = fs42.readFileSync(srcFile, "utf-8");
|
|
31357
31370
|
content = sanitizeContent(content, dirs);
|
|
31358
|
-
const baseName =
|
|
31371
|
+
const baseName = path42.basename(srcFile);
|
|
31359
31372
|
if (baseName === "session-index.json" || baseName === "platform-map.json") {
|
|
31360
31373
|
content = content.split("\\\\").join("/");
|
|
31361
31374
|
}
|
|
31362
|
-
|
|
31375
|
+
fs42.writeFileSync(destFile, content);
|
|
31363
31376
|
fileCount++;
|
|
31364
|
-
totalSize +=
|
|
31377
|
+
totalSize += fs42.statSync(srcFile).size;
|
|
31365
31378
|
} catch (e) {
|
|
31366
31379
|
copyFail++;
|
|
31367
31380
|
console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
|
|
@@ -31383,13 +31396,13 @@ async function doExport(opts) {
|
|
|
31383
31396
|
totalSize,
|
|
31384
31397
|
note
|
|
31385
31398
|
};
|
|
31386
|
-
|
|
31387
|
-
const archiveFile =
|
|
31399
|
+
fs42.writeFileSync(path42.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2));
|
|
31400
|
+
const archiveFile = path42.join(tmpDir, `${agentName}-${version}.tar.gz`);
|
|
31388
31401
|
console.log(`
|
|
31389
31402
|
\u{1F5DC}\uFE0F \u6253\u5305\u4E2D...`);
|
|
31390
31403
|
const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
|
|
31391
|
-
|
|
31392
|
-
const archiveSize =
|
|
31404
|
+
execSync3(`"${tarExe}" -czf "${archiveFile}" -C "${tmpDir}" ${agentName}`, { stdio: "pipe" });
|
|
31405
|
+
const archiveSize = fs42.statSync(archiveFile).size;
|
|
31393
31406
|
console.log(`\u2705 \u6253\u5305\u5B8C\u6210: ${archiveFile} (${(archiveSize / 1024 / 1024).toFixed(1)} MB, ${fileCount} \u6587\u4EF6${copyFail ? `, \u5931\u8D25 ${copyFail}` : ""})`);
|
|
31394
31407
|
const cfg = loadTravelConfig();
|
|
31395
31408
|
if (!cfg || !cfg.githubToken) {
|
|
@@ -31415,12 +31428,12 @@ function parseImportArgs(args) {
|
|
|
31415
31428
|
else if (args[i] === "--dry-run") dryRun2 = true;
|
|
31416
31429
|
}
|
|
31417
31430
|
if (!stateDir) throw new Error("import \u9700\u8981 --state-dir <path>");
|
|
31418
|
-
if (!agentName) agentName =
|
|
31431
|
+
if (!agentName) agentName = path42.basename(stateDir);
|
|
31419
31432
|
return { stateDir, agentName, version, archiveFile, dryRun: dryRun2 };
|
|
31420
31433
|
}
|
|
31421
31434
|
async function resolveArchiveForTest(opts) {
|
|
31422
31435
|
if (opts.archiveFile) {
|
|
31423
|
-
if (!
|
|
31436
|
+
if (!fs42.existsSync(opts.archiveFile)) {
|
|
31424
31437
|
throw new Error(`\u672C\u5730\u5305\u4E0D\u5B58\u5728: ${opts.archiveFile}`);
|
|
31425
31438
|
}
|
|
31426
31439
|
return opts.archiveFile;
|
|
@@ -31432,8 +31445,8 @@ async function doImport(opts) {
|
|
|
31432
31445
|
console.log(`\u{1F4E5} engine7 import`);
|
|
31433
31446
|
console.log(` agent: ${agentName}`);
|
|
31434
31447
|
console.log(` target: ${stateDir}`);
|
|
31435
|
-
const tmpDir =
|
|
31436
|
-
|
|
31448
|
+
const tmpDir = path42.join(os6.tmpdir(), `engine7-import-${agentName}-${Date.now()}`);
|
|
31449
|
+
fs42.mkdirSync(tmpDir, { recursive: true });
|
|
31437
31450
|
const resolved = await resolveArchiveForTest({
|
|
31438
31451
|
archiveFile: archiveFile || "",
|
|
31439
31452
|
tmpDir,
|
|
@@ -31457,100 +31470,100 @@ async function doImport(opts) {
|
|
|
31457
31470
|
}
|
|
31458
31471
|
console.log(`\u{1F4C2} \u89E3\u5305\u4E2D...`);
|
|
31459
31472
|
const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
|
|
31460
|
-
|
|
31461
|
-
const stagingDir =
|
|
31462
|
-
const manifestPath =
|
|
31463
|
-
if (!
|
|
31473
|
+
execSync3(`"${tarExe}" -xzf "${finalArchive}" -C "${tmpDir}"`, { stdio: "pipe" });
|
|
31474
|
+
const stagingDir = path42.join(tmpDir, agentName);
|
|
31475
|
+
const manifestPath = path42.join(stagingDir, "manifest.json");
|
|
31476
|
+
if (!fs42.existsSync(manifestPath)) {
|
|
31464
31477
|
console.error(`\u274C manifest.json \u4E0D\u5B58\u5728\uFF0C\u6587\u4EF6\u53EF\u80FD\u635F\u574F`);
|
|
31465
31478
|
process.exit(1);
|
|
31466
31479
|
}
|
|
31467
|
-
const manifest = JSON.parse(
|
|
31468
|
-
const workspace =
|
|
31469
|
-
const engineHome =
|
|
31480
|
+
const manifest = JSON.parse(fs42.readFileSync(manifestPath, "utf-8"));
|
|
31481
|
+
const workspace = path42.join(stateDir, "workspace").replace(/\\/g, "/").replace(/[/\\]+$/, "");
|
|
31482
|
+
const engineHome = path42.join(os6.homedir(), ".engine7").replace(/\\/g, "/").replace(/[/\\]+$/, "");
|
|
31470
31483
|
const dirs = { workspace, stateDir: stateDir.replace(/\\/g, "/").replace(/[/\\]+$/, ""), engineHome };
|
|
31471
31484
|
console.log(` \u7248\u672C: ${manifest.version}`);
|
|
31472
31485
|
console.log(` \u521B\u5EFA: ${manifest.createdAt}`);
|
|
31473
31486
|
console.log(` \u6587\u4EF6\u6570: ${manifest.fileCount}`);
|
|
31474
|
-
const wsStaging =
|
|
31487
|
+
const wsStaging = path42.join(stagingDir, "workspace");
|
|
31475
31488
|
let restoredCount = 0;
|
|
31476
31489
|
let skipCount = 0;
|
|
31477
|
-
if (
|
|
31490
|
+
if (fs42.existsSync(wsStaging)) {
|
|
31478
31491
|
const allFiles = collectAllFiles(wsStaging);
|
|
31479
31492
|
for (const srcFile of allFiles) {
|
|
31480
|
-
const relPath =
|
|
31481
|
-
const destFile =
|
|
31482
|
-
|
|
31493
|
+
const relPath = path42.relative(wsStaging, srcFile);
|
|
31494
|
+
const destFile = path42.join(workspace, relPath);
|
|
31495
|
+
fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
|
|
31483
31496
|
try {
|
|
31484
31497
|
if (isTextFile(srcFile)) {
|
|
31485
|
-
const content =
|
|
31486
|
-
|
|
31498
|
+
const content = fs42.readFileSync(srcFile, "utf-8");
|
|
31499
|
+
fs42.writeFileSync(destFile, restoreContent(content, dirs));
|
|
31487
31500
|
} else {
|
|
31488
|
-
|
|
31501
|
+
fs42.copyFileSync(srcFile, destFile);
|
|
31489
31502
|
}
|
|
31490
31503
|
restoredCount++;
|
|
31491
31504
|
} catch (e) {
|
|
31492
31505
|
skipCount++;
|
|
31493
|
-
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${
|
|
31506
|
+
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path42.relative(wsStaging, srcFile)} (${e.code || e.message})`);
|
|
31494
31507
|
}
|
|
31495
31508
|
}
|
|
31496
31509
|
}
|
|
31497
|
-
const agentsStaging =
|
|
31498
|
-
if (
|
|
31510
|
+
const agentsStaging = path42.join(stagingDir, "agents");
|
|
31511
|
+
if (fs42.existsSync(agentsStaging)) {
|
|
31499
31512
|
const sessionFiles = collectAllFiles(agentsStaging);
|
|
31500
31513
|
for (const srcFile of sessionFiles) {
|
|
31501
|
-
const relPath =
|
|
31502
|
-
const destFile =
|
|
31503
|
-
|
|
31504
|
-
const content =
|
|
31505
|
-
|
|
31514
|
+
const relPath = path42.relative(stagingDir, srcFile);
|
|
31515
|
+
const destFile = path42.join(stateDir, relPath);
|
|
31516
|
+
fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
|
|
31517
|
+
const content = fs42.readFileSync(srcFile, "utf-8");
|
|
31518
|
+
fs42.writeFileSync(destFile, restoreContent(content, dirs));
|
|
31506
31519
|
restoredCount++;
|
|
31507
31520
|
}
|
|
31508
31521
|
}
|
|
31509
|
-
const configsStaging =
|
|
31510
|
-
if (
|
|
31522
|
+
const configsStaging = path42.join(stagingDir, "configs");
|
|
31523
|
+
if (fs42.existsSync(configsStaging)) {
|
|
31511
31524
|
const cfgFiles = collectAllFiles(configsStaging);
|
|
31512
31525
|
for (const srcFile of cfgFiles) {
|
|
31513
|
-
const relPath =
|
|
31514
|
-
const destFile =
|
|
31515
|
-
|
|
31526
|
+
const relPath = path42.relative(stagingDir, srcFile);
|
|
31527
|
+
const destFile = path42.join(stateDir, relPath);
|
|
31528
|
+
fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
|
|
31516
31529
|
if (isTextFile(srcFile)) {
|
|
31517
|
-
const content =
|
|
31518
|
-
|
|
31530
|
+
const content = fs42.readFileSync(srcFile, "utf-8");
|
|
31531
|
+
fs42.writeFileSync(destFile, restoreContent(content, dirs));
|
|
31519
31532
|
} else {
|
|
31520
|
-
|
|
31533
|
+
fs42.copyFileSync(srcFile, destFile);
|
|
31521
31534
|
}
|
|
31522
31535
|
restoredCount++;
|
|
31523
31536
|
}
|
|
31524
31537
|
}
|
|
31525
|
-
const everosStaging =
|
|
31526
|
-
if (
|
|
31538
|
+
const everosStaging = path42.join(stagingDir, ".everos");
|
|
31539
|
+
if (fs42.existsSync(everosStaging)) {
|
|
31527
31540
|
const everosFiles = collectAllFiles(everosStaging);
|
|
31528
31541
|
for (const srcFile of everosFiles) {
|
|
31529
|
-
const relPath =
|
|
31530
|
-
const destFile =
|
|
31531
|
-
|
|
31542
|
+
const relPath = path42.relative(stagingDir, srcFile);
|
|
31543
|
+
const destFile = path42.join(stateDir, relPath);
|
|
31544
|
+
fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
|
|
31532
31545
|
try {
|
|
31533
31546
|
if (isTextFile(srcFile)) {
|
|
31534
|
-
const content =
|
|
31535
|
-
|
|
31547
|
+
const content = fs42.readFileSync(srcFile, "utf-8");
|
|
31548
|
+
fs42.writeFileSync(destFile, restoreContent(content, dirs));
|
|
31536
31549
|
} else {
|
|
31537
|
-
|
|
31550
|
+
fs42.copyFileSync(srcFile, destFile);
|
|
31538
31551
|
}
|
|
31539
31552
|
restoredCount++;
|
|
31540
31553
|
} catch (e) {
|
|
31541
31554
|
skipCount++;
|
|
31542
|
-
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${
|
|
31555
|
+
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path42.relative(everosStaging, srcFile)} (${e.code || e.message})`);
|
|
31543
31556
|
}
|
|
31544
31557
|
}
|
|
31545
31558
|
console.log(` everos: ${everosFiles.length} \u6587\u4EF6\u5DF2\u6062\u590D`);
|
|
31546
31559
|
}
|
|
31547
31560
|
console.log(`\u2705 \u6062\u590D\u5B8C\u6210: ${restoredCount} \u6587\u4EF6 \u2192 ${stateDir}${skipCount ? ` (\u8DF3\u8FC7 ${skipCount})` : ""}`);
|
|
31548
31561
|
const platformConfigName = process.platform === "darwin" ? "xiaoke-mac.json" : "xiaoke-win.json";
|
|
31549
|
-
const restoredConfigPath =
|
|
31550
|
-
const configToUse =
|
|
31562
|
+
const restoredConfigPath = path42.join(stateDir, "configs", platformConfigName);
|
|
31563
|
+
const configToUse = fs42.existsSync(restoredConfigPath) ? restoredConfigPath : path42.join(stateDir, "configs", "xiaoke.json");
|
|
31551
31564
|
console.log(`
|
|
31552
31565
|
\u{1F4A1} \u4E0B\u4E00\u6B65: engine7 start --config "${configToUse}"`);
|
|
31553
|
-
|
|
31566
|
+
fs42.rmSync(tmpDir, { recursive: true, force: true });
|
|
31554
31567
|
}
|
|
31555
31568
|
async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
|
|
31556
31569
|
const repo = `${cfg.githubOwner}/${cfg.repoName}`;
|
|
@@ -31580,8 +31593,8 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
|
|
|
31580
31593
|
}
|
|
31581
31594
|
const release2 = await createRes.json();
|
|
31582
31595
|
const uploadUrl = release2.upload_url.replace("{?name,label}", "");
|
|
31583
|
-
const fileBuffer =
|
|
31584
|
-
const fileName =
|
|
31596
|
+
const fileBuffer = fs42.readFileSync(archiveFile);
|
|
31597
|
+
const fileName = path42.basename(archiveFile);
|
|
31585
31598
|
const uploadRes = await fetch(`${uploadUrl}?name=${fileName}`, {
|
|
31586
31599
|
method: "POST",
|
|
31587
31600
|
headers: {
|
|
@@ -31604,7 +31617,7 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
|
|
|
31604
31617
|
throw e;
|
|
31605
31618
|
}
|
|
31606
31619
|
try {
|
|
31607
|
-
|
|
31620
|
+
fs42.rmSync(path42.dirname(archiveFile), { recursive: true, force: true });
|
|
31608
31621
|
} catch {
|
|
31609
31622
|
}
|
|
31610
31623
|
}
|
|
@@ -31636,8 +31649,8 @@ async function downloadFromGitHub(cfg, agentName, version, destDir) {
|
|
|
31636
31649
|
throw new Error(`\u4E0B\u8F7D asset \u5931\u8D25: ${downloadRes.status}`);
|
|
31637
31650
|
}
|
|
31638
31651
|
const buffer = Buffer.from(await downloadRes.arrayBuffer());
|
|
31639
|
-
const archiveFile =
|
|
31640
|
-
|
|
31652
|
+
const archiveFile = path42.join(destDir, asset.name);
|
|
31653
|
+
fs42.writeFileSync(archiveFile, buffer);
|
|
31641
31654
|
return archiveFile;
|
|
31642
31655
|
}
|
|
31643
31656
|
async function getLatestReleaseTag(cfg, agentName) {
|
|
@@ -31663,7 +31676,7 @@ var init_cli_travel = __esm({
|
|
|
31663
31676
|
"src/cli-travel.ts"() {
|
|
31664
31677
|
"use strict";
|
|
31665
31678
|
init_clock();
|
|
31666
|
-
CONFIG_PATH =
|
|
31679
|
+
CONFIG_PATH = path42.join(os6.homedir(), ".engine7-travel.json");
|
|
31667
31680
|
PATH_PLACEHOLDERS = [
|
|
31668
31681
|
{ placeholder: "{{WORKSPACE}}", getOriginal: (d) => d.workspace },
|
|
31669
31682
|
{ placeholder: "{{ENGINE_HOME}}", getOriginal: (d) => d.engineHome },
|
|
@@ -31736,8 +31749,8 @@ var init_cli_travel = __esm({
|
|
|
31736
31749
|
});
|
|
31737
31750
|
|
|
31738
31751
|
// src/cli-init.ts
|
|
31739
|
-
import * as
|
|
31740
|
-
import * as
|
|
31752
|
+
import * as path43 from "node:path";
|
|
31753
|
+
import * as fs43 from "node:fs";
|
|
31741
31754
|
|
|
31742
31755
|
// src/cli-service.ts
|
|
31743
31756
|
function parseServiceArgs(args) {
|
|
@@ -31892,6 +31905,136 @@ function buildConfigValuesFromAnswers(stateDir, a, existing = {}) {
|
|
|
31892
31905
|
|
|
31893
31906
|
// src/cli-init.ts
|
|
31894
31907
|
init_secrets_env();
|
|
31908
|
+
|
|
31909
|
+
// src/pid-lock.ts
|
|
31910
|
+
import fs3 from "node:fs";
|
|
31911
|
+
import path3 from "node:path";
|
|
31912
|
+
import { execSync } from "node:child_process";
|
|
31913
|
+
function enginePidFile(stateDir) {
|
|
31914
|
+
return path3.join(stateDir, ".engine.pid");
|
|
31915
|
+
}
|
|
31916
|
+
function isEngineImage(text) {
|
|
31917
|
+
return /node|engine7|electron/i.test(text);
|
|
31918
|
+
}
|
|
31919
|
+
function isPidAlive(pid) {
|
|
31920
|
+
try {
|
|
31921
|
+
process.kill(pid, 0);
|
|
31922
|
+
return true;
|
|
31923
|
+
} catch {
|
|
31924
|
+
return false;
|
|
31925
|
+
}
|
|
31926
|
+
}
|
|
31927
|
+
function probeImage(pid) {
|
|
31928
|
+
try {
|
|
31929
|
+
if (process.platform === "win32") {
|
|
31930
|
+
return execSync(`tasklist /FI "PID eq ${pid}" /NH /FO CSV`, {
|
|
31931
|
+
encoding: "utf-8",
|
|
31932
|
+
timeout: 3e3,
|
|
31933
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
31934
|
+
});
|
|
31935
|
+
}
|
|
31936
|
+
if (process.platform === "darwin") {
|
|
31937
|
+
return execSync(`ps -p ${pid} -o comm=`, {
|
|
31938
|
+
encoding: "utf-8",
|
|
31939
|
+
timeout: 3e3,
|
|
31940
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
31941
|
+
});
|
|
31942
|
+
}
|
|
31943
|
+
return fs3.readFileSync(`/proc/${pid}/comm`, "utf-8");
|
|
31944
|
+
} catch {
|
|
31945
|
+
return null;
|
|
31946
|
+
}
|
|
31947
|
+
}
|
|
31948
|
+
function probeEngineImage(pid) {
|
|
31949
|
+
return isEngineImage(probeImage(pid) ?? "");
|
|
31950
|
+
}
|
|
31951
|
+
function isCliWrapperImage(text) {
|
|
31952
|
+
return /node/i.test(text);
|
|
31953
|
+
}
|
|
31954
|
+
function probeIsCliWrapper(pid) {
|
|
31955
|
+
return isCliWrapperImage(probeImage(pid) ?? "");
|
|
31956
|
+
}
|
|
31957
|
+
function readOwnEnginePidText(stateDir) {
|
|
31958
|
+
try {
|
|
31959
|
+
return fs3.readFileSync(enginePidFile(stateDir), "utf-8");
|
|
31960
|
+
} catch (err) {
|
|
31961
|
+
if (err?.code !== "ENOENT") console.warn(`[pid-lock] read lock failed: ${err.message}`);
|
|
31962
|
+
return null;
|
|
31963
|
+
}
|
|
31964
|
+
}
|
|
31965
|
+
function pickOwnEnginePid(probe) {
|
|
31966
|
+
const pid = parseInt((probe.pidFileContent ?? "").trim(), 10);
|
|
31967
|
+
if (!Number.isInteger(pid) || pid <= 0) return null;
|
|
31968
|
+
if (pid === probe.myPid) return null;
|
|
31969
|
+
if (!probe.isAlive(pid)) return null;
|
|
31970
|
+
if (!probe.isEngineImage(pid)) return null;
|
|
31971
|
+
return pid;
|
|
31972
|
+
}
|
|
31973
|
+
function ownEnginePid(stateDir, myPid = process.pid) {
|
|
31974
|
+
return pickOwnEnginePid({
|
|
31975
|
+
pidFileContent: readOwnEnginePidText(stateDir),
|
|
31976
|
+
myPid,
|
|
31977
|
+
isAlive: isPidAlive,
|
|
31978
|
+
isEngineImage: probeEngineImage
|
|
31979
|
+
});
|
|
31980
|
+
}
|
|
31981
|
+
function killOwnEngineForStateDir(stateDir) {
|
|
31982
|
+
const pid = ownEnginePid(stateDir);
|
|
31983
|
+
if (pid === null) return null;
|
|
31984
|
+
killTree(pid);
|
|
31985
|
+
return pid;
|
|
31986
|
+
}
|
|
31987
|
+
async function waitForPidGone(pid, timeoutMs = 5e3) {
|
|
31988
|
+
const t0 = Date.now();
|
|
31989
|
+
while (Date.now() - t0 < timeoutMs) {
|
|
31990
|
+
if (!isPidAlive(pid)) return true;
|
|
31991
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
31992
|
+
}
|
|
31993
|
+
return !isPidAlive(pid);
|
|
31994
|
+
}
|
|
31995
|
+
function pickParentPid(procStatus, psOutput) {
|
|
31996
|
+
const fromProc = Number(/PPid:\s*(\d+)/.exec(procStatus ?? "")?.[1] ?? NaN);
|
|
31997
|
+
if (Number.isInteger(fromProc) && fromProc > 0) return fromProc;
|
|
31998
|
+
const fromPs = Number((psOutput ?? "").trim());
|
|
31999
|
+
return Number.isInteger(fromPs) && fromPs > 0 ? fromPs : 0;
|
|
32000
|
+
}
|
|
32001
|
+
function killTree(pid) {
|
|
32002
|
+
try {
|
|
32003
|
+
if (process.platform === "win32") {
|
|
32004
|
+
execSync(`taskkill /PID ${pid} /T /F`, { stdio: "ignore", timeout: 8e3 });
|
|
32005
|
+
try {
|
|
32006
|
+
const parentPid = parseInt(execSync(`wmic process where ProcessId=${pid} get ParentProcessId /value`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).match(/ParentProcessId=(\d+)/)?.[1] ?? "0", 10);
|
|
32007
|
+
if (parentPid && parentPid !== process.ppid && probeIsCliWrapper(parentPid)) {
|
|
32008
|
+
execSync(`taskkill /PID ${parentPid} /F`, { stdio: "ignore", timeout: 3e3 });
|
|
32009
|
+
}
|
|
32010
|
+
} catch {
|
|
32011
|
+
}
|
|
32012
|
+
} else {
|
|
32013
|
+
process.kill(pid, "SIGKILL");
|
|
32014
|
+
let parentPid = 0;
|
|
32015
|
+
try {
|
|
32016
|
+
parentPid = pickParentPid(fs3.readFileSync(`/proc/${pid}/status`, "utf-8"), null);
|
|
32017
|
+
} catch {
|
|
32018
|
+
}
|
|
32019
|
+
if (!parentPid) {
|
|
32020
|
+
try {
|
|
32021
|
+
parentPid = pickParentPid(null, execSync(`ps -p ${pid} -o ppid=`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }));
|
|
32022
|
+
} catch {
|
|
32023
|
+
}
|
|
32024
|
+
}
|
|
32025
|
+
if (parentPid > 1 && parentPid !== process.ppid && probeIsCliWrapper(parentPid)) {
|
|
32026
|
+
try {
|
|
32027
|
+
process.kill(parentPid, "SIGKILL");
|
|
32028
|
+
} catch {
|
|
32029
|
+
}
|
|
32030
|
+
}
|
|
32031
|
+
}
|
|
32032
|
+
} catch (err) {
|
|
32033
|
+
console.warn(`[pid-lock] kill ${pid} failed: ${err.message}`);
|
|
32034
|
+
}
|
|
32035
|
+
}
|
|
32036
|
+
|
|
32037
|
+
// src/cli-init.ts
|
|
31895
32038
|
init_clock();
|
|
31896
32039
|
init_cli_init_config();
|
|
31897
32040
|
init_registry();
|
|
@@ -31910,7 +32053,7 @@ function describeCurrentToken(v) {
|
|
|
31910
32053
|
return /^(?:env:|{{\s*)[A-Z0-9_]+/.test(v) ? "\u5DF2\u5B58\u5728 secrets \u4E2D" : v.slice(0, 12) + "...";
|
|
31911
32054
|
}
|
|
31912
32055
|
var __filename2 = fileURLToPath7(import.meta.url);
|
|
31913
|
-
var __dirname =
|
|
32056
|
+
var __dirname = path43.dirname(__filename2);
|
|
31914
32057
|
function parseArgs2() {
|
|
31915
32058
|
const args = process.argv.slice(2);
|
|
31916
32059
|
let stateDir = "";
|
|
@@ -31937,10 +32080,10 @@ function parseArgs2() {
|
|
|
31937
32080
|
}
|
|
31938
32081
|
}
|
|
31939
32082
|
if (!stateDir) {
|
|
31940
|
-
stateDir =
|
|
32083
|
+
stateDir = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
31941
32084
|
console.log(` \u4F7F\u7528\u9ED8\u8BA4\u76EE\u5F55: ${stateDir}`);
|
|
31942
32085
|
}
|
|
31943
|
-
stateDir =
|
|
32086
|
+
stateDir = path43.resolve(stateDir);
|
|
31944
32087
|
return { stateDir, quick, dryRun: dryRun2, force, answersPath };
|
|
31945
32088
|
}
|
|
31946
32089
|
function printHelp() {
|
|
@@ -32061,16 +32204,16 @@ function getDefaultValues(stateDir) {
|
|
|
32061
32204
|
};
|
|
32062
32205
|
}
|
|
32063
32206
|
function loadExistingValues(stateDir) {
|
|
32064
|
-
const configPath =
|
|
32207
|
+
const configPath = path43.join(stateDir, "configs", "main7.json");
|
|
32065
32208
|
try {
|
|
32066
|
-
if (!
|
|
32067
|
-
const j = JSON.parse(
|
|
32209
|
+
if (!fs43.existsSync(configPath)) return {};
|
|
32210
|
+
const j = JSON.parse(fs43.readFileSync(configPath, "utf8"));
|
|
32068
32211
|
const out = {};
|
|
32069
32212
|
if (typeof j.timezone === "string" && j.timezone) out.timezone = j.timezone;
|
|
32070
32213
|
if (j.agents?.defaults?.name) out.agentName = j.agents.defaults.name;
|
|
32071
32214
|
if (j.agents?.defaults?.persona) out.persona = j.agents.defaults.persona;
|
|
32072
32215
|
try {
|
|
32073
|
-
const wm =
|
|
32216
|
+
const wm = fs43.readFileSync(path43.join(stateDir, "workspace", ".work-mode"), "utf8").trim();
|
|
32074
32217
|
if (wm === "on") out.chatMode = "work";
|
|
32075
32218
|
else if (wm === "off") out.chatMode = "emotion";
|
|
32076
32219
|
} catch {
|
|
@@ -32127,8 +32270,8 @@ function readSecretsValue(stateDir, envName) {
|
|
|
32127
32270
|
try {
|
|
32128
32271
|
const cfgBase = "main7";
|
|
32129
32272
|
for (const p of secretsCandidates(stateDir, cfgBase)) {
|
|
32130
|
-
if (
|
|
32131
|
-
for (const line of
|
|
32273
|
+
if (fs43.existsSync(p)) {
|
|
32274
|
+
for (const line of fs43.readFileSync(p, "utf8").split("\n")) {
|
|
32132
32275
|
const eq = line.indexOf("=");
|
|
32133
32276
|
if (eq > 0 && line.slice(0, eq).trim() === envName) {
|
|
32134
32277
|
return line.slice(eq + 1).trim();
|
|
@@ -32362,29 +32505,29 @@ async function configureWechat(rl, v) {
|
|
|
32362
32505
|
}
|
|
32363
32506
|
function buildDirTree(v) {
|
|
32364
32507
|
const d = v.stateDir;
|
|
32365
|
-
const w =
|
|
32508
|
+
const w = path43.join(d, "workspace");
|
|
32366
32509
|
return [
|
|
32367
32510
|
// 目录
|
|
32368
|
-
{ path:
|
|
32369
|
-
{ path:
|
|
32370
|
-
{ path:
|
|
32371
|
-
{ path:
|
|
32372
|
-
{ path:
|
|
32373
|
-
{ path:
|
|
32374
|
-
{ path:
|
|
32375
|
-
{ path:
|
|
32376
|
-
{ path:
|
|
32377
|
-
{ path:
|
|
32378
|
-
{ path:
|
|
32511
|
+
{ path: path43.join(d, "configs"), type: "dir" },
|
|
32512
|
+
{ path: path43.join(d, "state", "agents", "main", "sessions"), type: "dir" },
|
|
32513
|
+
{ path: path43.join(w, "prompts"), type: "dir" },
|
|
32514
|
+
{ path: path43.join(w, "memory", "daily"), type: "dir" },
|
|
32515
|
+
{ path: path43.join(w, "docs", "research"), type: "dir" },
|
|
32516
|
+
{ path: path43.join(w, "docs", "todo"), type: "dir" },
|
|
32517
|
+
{ path: path43.join(w, "docs", "decisions"), type: "dir" },
|
|
32518
|
+
{ path: path43.join(w, "docs", "knowledge"), type: "dir" },
|
|
32519
|
+
{ path: path43.join(w, "docs", "sop"), type: "dir" },
|
|
32520
|
+
{ path: path43.join(d, "logs"), type: "dir" },
|
|
32521
|
+
{ path: path43.join(d, "media", "inbound"), type: "dir" },
|
|
32379
32522
|
// workspace 文件
|
|
32380
32523
|
{
|
|
32381
|
-
path:
|
|
32524
|
+
path: path43.join(w, "SESSION-STATE.md"),
|
|
32382
32525
|
type: "file",
|
|
32383
32526
|
content: readTemplate("workspace/SESSION-STATE.md")
|
|
32384
32527
|
},
|
|
32385
|
-
{ path:
|
|
32528
|
+
{ path: path43.join(w, "HEARTBEAT.md"), type: "file", content: readTemplate("workspace/HEARTBEAT.md") },
|
|
32386
32529
|
{
|
|
32387
|
-
path:
|
|
32530
|
+
path: path43.join(w, "SOUL.md"),
|
|
32388
32531
|
type: "file",
|
|
32389
32532
|
// 0917:SOUL 按人设取模板(templates/workspace/souls/<persona>.md),
|
|
32390
32533
|
// 单一人设模板缺失时回退通用骨架(workspace/SOUL.md)
|
|
@@ -32396,12 +32539,12 @@ function buildDirTree(v) {
|
|
|
32396
32539
|
}
|
|
32397
32540
|
})()
|
|
32398
32541
|
},
|
|
32399
|
-
{ path:
|
|
32542
|
+
{ path: path43.join(w, "AGENTS.md"), type: "file", content: readTemplate("workspace/AGENTS.md") },
|
|
32400
32543
|
{
|
|
32401
32544
|
// 0920 翀哥拍板:EMOTION.md 模板按人设装(templates/workspace/emotion/<persona>.md)
|
|
32402
32545
|
// 冷启动默认带"想 TA 了就直接发(msg_send)"那段(写在每份模板 §一)
|
|
32403
32546
|
// 单一人设模板缺失时回退通用骨架(emotion/_default.md)
|
|
32404
|
-
path:
|
|
32547
|
+
path: path43.join(w, "EMOTION.md"),
|
|
32405
32548
|
type: "file",
|
|
32406
32549
|
content: (() => {
|
|
32407
32550
|
try {
|
|
@@ -32412,39 +32555,39 @@ function buildDirTree(v) {
|
|
|
32412
32555
|
})()
|
|
32413
32556
|
},
|
|
32414
32557
|
{
|
|
32415
|
-
path:
|
|
32558
|
+
path: path43.join(w, "prompts", "contacts.md"),
|
|
32416
32559
|
type: "file",
|
|
32417
32560
|
content: readTemplate("workspace/prompts/contacts.md").replace("{{DISCORD_USER_ID}}", v.discordUserId || "YOUR_DISCORD_ID").replace("{{FEISHU_OPEN_ID}}", v.feishuOpenId || "YOUR_FEISHU_OPEN_ID")
|
|
32418
32561
|
},
|
|
32419
|
-
{ path:
|
|
32562
|
+
{ path: path43.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
|
|
32420
32563
|
{
|
|
32421
32564
|
// 0925:proactive 到期处理规则。此前仓内**零模板**——那份规则只在私有部署的
|
|
32422
32565
|
// stateDir 里手工存在,装机用户吃的是引擎内置兜底文案(那份也没点名工具)。
|
|
32423
32566
|
// 结果:agent 用正文写判定、不调工具,判定全部不落库。
|
|
32424
32567
|
// 注意 readTemplate 找不到模板会 **throw**,所以本文件与 templates/ 下那份必须成对存在。
|
|
32425
|
-
path:
|
|
32568
|
+
path: path43.join(w, "prompts", "proactive.md"),
|
|
32426
32569
|
type: "file",
|
|
32427
32570
|
content: readTemplate("workspace/prompts/proactive.md")
|
|
32428
32571
|
},
|
|
32429
32572
|
{
|
|
32430
32573
|
// 0917:inner-voice 定制 prompt 按人设装(templates/workspace/inner-voice/<persona>.md)
|
|
32431
|
-
path:
|
|
32574
|
+
path: path43.join(w, "prompts", "my-inner-voice.md"),
|
|
32432
32575
|
type: "file",
|
|
32433
32576
|
content: readTemplate(`workspace/inner-voice/${v.persona}.md`).replace(/\{\{AGENT_NAME\}\}/g, v.agentName)
|
|
32434
32577
|
},
|
|
32435
|
-
{ path:
|
|
32436
|
-
{ path:
|
|
32578
|
+
{ path: path43.join(w, "MEMORY.md"), type: "file", content: "# MEMORY.md \u2014 \u8BB0\u5FC6\u6587\u4EF6\u7D22\u5F15\n\n> \u6700\u540E\u66F4\u65B0\uFF1A\u521D\u59CB\u5316\n" },
|
|
32579
|
+
{ path: path43.join(w, "USER.md"), type: "file", content: "# USER.md \u2014 \u7528\u6237\u4FE1\u606F\n\n\uFF08\u5728\u8FD9\u91CC\u8BB0\u5F55\u7528\u6237\u7684\u504F\u597D\u3001\u80CC\u666F\u7B49\uFF09\n" },
|
|
32437
32580
|
// 情绪状态机(0917):脚本 + hook 接线 + 人设情绪表(用户在 init 选的 persona)
|
|
32438
32581
|
//
|
|
32439
32582
|
// 0920 起装的是 **.mjs 版**(原来是 .py,见下面 hook 命令那段)。老装机的 workspace
|
|
32440
32583
|
// 里那份 .py 不动它——没被引用就不会跑,删了反而无据可查。
|
|
32441
32584
|
{
|
|
32442
|
-
path:
|
|
32585
|
+
path: path43.join(w, "scripts", "emotion_state_machine.mjs"),
|
|
32443
32586
|
type: "file",
|
|
32444
32587
|
content: readTemplate("workspace/scripts/emotion_state_machine.mjs")
|
|
32445
32588
|
},
|
|
32446
32589
|
{
|
|
32447
|
-
path:
|
|
32590
|
+
path: path43.join(w, ".hooks.json"),
|
|
32448
32591
|
type: "file",
|
|
32449
32592
|
content: JSON.stringify({
|
|
32450
32593
|
hooks: {
|
|
@@ -32459,26 +32602,26 @@ function buildDirTree(v) {
|
|
|
32459
32602
|
// (hook 的 env 是 {...process.env} 继承的),所以它就是个 node。
|
|
32460
32603
|
// 与 `service install --node-exe` 同一个路子。
|
|
32461
32604
|
// 路径两侧都加引号:stateDir 可能带空格(C:\Users\Foo Bar\...)。
|
|
32462
|
-
{ hooks: [{ type: "command", command: '"${E7_NODE}" "' +
|
|
32605
|
+
{ hooks: [{ type: "command", command: '"${E7_NODE}" "' + path43.join(w, "scripts", "emotion_state_machine.mjs") + '"' }] }
|
|
32463
32606
|
]
|
|
32464
32607
|
}
|
|
32465
32608
|
}, null, 2) + "\n"
|
|
32466
32609
|
},
|
|
32467
32610
|
{
|
|
32468
|
-
path:
|
|
32611
|
+
path: path43.join(w, ".emotion_states.json"),
|
|
32469
32612
|
type: "file",
|
|
32470
32613
|
content: readTemplate(`workspace/emotion-states/${v.persona}.json`)
|
|
32471
32614
|
},
|
|
32472
32615
|
// 模式档位(0920):与 /work 命令写的是同一个文件,读端只认 on/off,
|
|
32473
32616
|
// 没有这个键就是 auto。auto 刻意不写——写个 "auto" 进去反而多一种除了这里没人认得的状态。
|
|
32474
32617
|
...v.chatMode === "work" || v.chatMode === "emotion" ? [{
|
|
32475
|
-
path:
|
|
32618
|
+
path: path43.join(w, ".work-mode"),
|
|
32476
32619
|
type: "file",
|
|
32477
32620
|
content: v.chatMode === "work" ? "on" : "off"
|
|
32478
32621
|
}] : [],
|
|
32479
32622
|
// package.json — 让 agent 目录成为独立 npm 项目根,防止 npm hoisting
|
|
32480
32623
|
{
|
|
32481
|
-
path:
|
|
32624
|
+
path: path43.join(d, "package.json"),
|
|
32482
32625
|
type: "file",
|
|
32483
32626
|
content: JSON.stringify({
|
|
32484
32627
|
name: v.agentName.toLowerCase().replace(/[^a-z0-9-]/g, "-") || "agent",
|
|
@@ -32489,7 +32632,7 @@ function buildDirTree(v) {
|
|
|
32489
32632
|
},
|
|
32490
32633
|
// 启动脚本(根据 OS 生成)
|
|
32491
32634
|
...process.platform === "win32" ? [{
|
|
32492
|
-
path:
|
|
32635
|
+
path: path43.join(d, "start.cmd"),
|
|
32493
32636
|
type: "file",
|
|
32494
32637
|
content: `@echo off
|
|
32495
32638
|
rem Engine 7 startup script
|
|
@@ -32521,7 +32664,7 @@ if %ERRORLEVEL% NEQ 0 (
|
|
|
32521
32664
|
)
|
|
32522
32665
|
`
|
|
32523
32666
|
}] : [{
|
|
32524
|
-
path:
|
|
32667
|
+
path: path43.join(d, "start.sh"),
|
|
32525
32668
|
type: "file",
|
|
32526
32669
|
content: `#!/bin/bash
|
|
32527
32670
|
# Engine 7 startup script
|
|
@@ -32555,24 +32698,24 @@ node "$ENGINE7_BIN" --engine-config "$CFG_ABS"
|
|
|
32555
32698
|
}
|
|
32556
32699
|
function readTemplate(relativePath) {
|
|
32557
32700
|
const candidates = [
|
|
32558
|
-
|
|
32559
|
-
|
|
32560
|
-
|
|
32701
|
+
path43.join(__dirname, "..", "templates", relativePath),
|
|
32702
|
+
path43.join(__dirname, "..", "..", "templates", relativePath),
|
|
32703
|
+
path43.join(process.cwd(), "templates", relativePath)
|
|
32561
32704
|
];
|
|
32562
32705
|
for (const p of candidates) {
|
|
32563
|
-
if (
|
|
32564
|
-
return
|
|
32706
|
+
if (fs43.existsSync(p)) {
|
|
32707
|
+
return fs43.readFileSync(p, "utf-8");
|
|
32565
32708
|
}
|
|
32566
32709
|
}
|
|
32567
32710
|
throw new Error(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${relativePath}\uFF08\u627E\u4E86: ${candidates.join(", ")}\uFF09`);
|
|
32568
32711
|
}
|
|
32569
32712
|
function looksLikeAppInstall(dir) {
|
|
32570
|
-
return ["", "install"].some((sub) =>
|
|
32713
|
+
return ["", "install"].some((sub) => fs43.existsSync(path43.join(dir, sub, "Engine7.exe")) && fs43.existsSync(path43.join(dir, sub, "resources", "engine7", "dist", "cli.mjs")));
|
|
32571
32714
|
}
|
|
32572
32715
|
var PHOTO_EXTS = [".png", ".jpg", ".jpeg", ".webp"];
|
|
32573
32716
|
function hasOnlyEngineBookkeeping(dir) {
|
|
32574
32717
|
try {
|
|
32575
|
-
const entries2 =
|
|
32718
|
+
const entries2 = fs43.readdirSync(dir);
|
|
32576
32719
|
return entries2.length > 0 && entries2.every((e) => e === "install-identity.json");
|
|
32577
32720
|
} catch {
|
|
32578
32721
|
return false;
|
|
@@ -32588,11 +32731,11 @@ function dryRun(entries2) {
|
|
|
32588
32731
|
function execute(entries2) {
|
|
32589
32732
|
for (const e of entries2) {
|
|
32590
32733
|
if (e.type === "dir") {
|
|
32591
|
-
|
|
32734
|
+
fs43.mkdirSync(e.path, { recursive: true });
|
|
32592
32735
|
console.log(` \u{1F4C1} ${e.path}`);
|
|
32593
32736
|
} else {
|
|
32594
|
-
|
|
32595
|
-
|
|
32737
|
+
fs43.mkdirSync(path43.dirname(e.path), { recursive: true });
|
|
32738
|
+
fs43.writeFileSync(e.path, e.content || "", "utf-8");
|
|
32596
32739
|
console.log(` \u{1F4C4} ${e.path}`);
|
|
32597
32740
|
}
|
|
32598
32741
|
}
|
|
@@ -32626,8 +32769,8 @@ async function main() {
|
|
|
32626
32769
|
if (subcommand === "--version" || subcommand === "-v") {
|
|
32627
32770
|
let ver = "unknown";
|
|
32628
32771
|
try {
|
|
32629
|
-
const pkgPath =
|
|
32630
|
-
ver = JSON.parse(
|
|
32772
|
+
const pkgPath = path43.join(path43.dirname(__filename2), "..", "package.json");
|
|
32773
|
+
ver = JSON.parse(fs43.readFileSync(pkgPath, "utf8")).version || "unknown";
|
|
32631
32774
|
} catch {
|
|
32632
32775
|
}
|
|
32633
32776
|
console.log(`engine7 ${ver}`);
|
|
@@ -32656,14 +32799,14 @@ async function main() {
|
|
|
32656
32799
|
relay = resolveRelayUrl(relay, process.env);
|
|
32657
32800
|
if (!relayFromArg) console.error(` \u4E2D\u8F6C\u7AD9: ${relay}\uFF08\u8981\u6362\u5730\u5740\u7528 --relay <\u5730\u5740>\uFF09`);
|
|
32658
32801
|
const { resolveStateDirFromArgs: resolveStateDirFromArgs2 } = await Promise.resolve().then(() => (init_cli_doctor(), cli_doctor_exports));
|
|
32659
|
-
stateDir = stateDir ?
|
|
32802
|
+
stateDir = stateDir ? path43.resolve(stateDir) : resolveStateDirFromArgs2(args.slice(1));
|
|
32660
32803
|
try {
|
|
32661
32804
|
const { provisionFreeToken: provisionFreeToken2 } = await Promise.resolve().then(() => (init_provision_free(), provision_free_exports));
|
|
32662
32805
|
const result = await provisionFreeToken2({
|
|
32663
32806
|
relayBaseUrl: relay,
|
|
32664
32807
|
stateDir,
|
|
32665
32808
|
// 和 init 写 config 的路径一致(cli-init.ts 里 configPath 就是这么拼的)
|
|
32666
|
-
configPath:
|
|
32809
|
+
configPath: path43.join(stateDir, "configs", "main7.json")
|
|
32667
32810
|
});
|
|
32668
32811
|
console.log(JSON.stringify(result, null, 2));
|
|
32669
32812
|
process.exit(0);
|
|
@@ -32690,18 +32833,18 @@ async function main() {
|
|
|
32690
32833
|
else if (args[i] === "--base-url" && args[i + 1]) relayBaseUrl = args[++i].trim();
|
|
32691
32834
|
}
|
|
32692
32835
|
if (!stateDir) {
|
|
32693
|
-
const cwd =
|
|
32694
|
-
if (
|
|
32836
|
+
const cwd = path43.resolve(process.cwd());
|
|
32837
|
+
if (fs43.existsSync(path43.join(cwd, "configs"))) {
|
|
32695
32838
|
stateDir = cwd;
|
|
32696
32839
|
} else {
|
|
32697
|
-
const pointer =
|
|
32698
|
-
if (
|
|
32840
|
+
const pointer = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
|
|
32841
|
+
if (fs43.existsSync(pointer)) {
|
|
32699
32842
|
try {
|
|
32700
|
-
stateDir = JSON.parse(
|
|
32843
|
+
stateDir = JSON.parse(fs43.readFileSync(pointer, "utf8")).stateDir || "";
|
|
32701
32844
|
} catch {
|
|
32702
32845
|
}
|
|
32703
32846
|
}
|
|
32704
|
-
if (!stateDir) stateDir =
|
|
32847
|
+
if (!stateDir) stateDir = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
32705
32848
|
}
|
|
32706
32849
|
}
|
|
32707
32850
|
if (!target && !isLegacyAddchannel) {
|
|
@@ -32721,12 +32864,12 @@ async function main() {
|
|
|
32721
32864
|
process.exit(0);
|
|
32722
32865
|
}
|
|
32723
32866
|
if (channel === "channels") {
|
|
32724
|
-
const configsDir =
|
|
32725
|
-
if (
|
|
32726
|
-
const files =
|
|
32867
|
+
const configsDir = path43.join(stateDir, "configs");
|
|
32868
|
+
if (fs43.existsSync(configsDir)) {
|
|
32869
|
+
const files = fs43.readdirSync(configsDir).filter((f) => f.endsWith(".json"));
|
|
32727
32870
|
for (const f of files) {
|
|
32728
32871
|
try {
|
|
32729
|
-
const j = JSON.parse(
|
|
32872
|
+
const j = JSON.parse(fs43.readFileSync(path43.join(configsDir, f), "utf8"));
|
|
32730
32873
|
if (!j.channels) continue;
|
|
32731
32874
|
console.log(`
|
|
32732
32875
|
\u{1F4C4} ${f}:`);
|
|
@@ -32763,7 +32906,7 @@ async function main() {
|
|
|
32763
32906
|
}
|
|
32764
32907
|
const configFile = resolveConfigPath2(stateDir, configName);
|
|
32765
32908
|
if (!configFile) {
|
|
32766
|
-
fail2(`\u6CA1\u627E\u5230\u53EF\u6539\u7684 config\uFF1A\u5728 ${
|
|
32909
|
+
fail2(`\u6CA1\u627E\u5230\u53EF\u6539\u7684 config\uFF1A\u5728 ${path43.join(stateDir, "configs")} \u4E0B\u65E2\u6CA1\u6709 main7.json\uFF0C\u4E5F\u6CA1\u6709\u542B models.providers \u7684 json\u3002\u7528 --config <\u6587\u4EF6\u540D> \u6307\u5B9A\u3002`);
|
|
32767
32910
|
}
|
|
32768
32911
|
if (!readSecretsValue(stateDir, FREE_TIER_ENV_KEY2)) {
|
|
32769
32912
|
fail2(`\u514D\u8D39\u6863\u7F3A\u5C11\u4EE4\u724C\uFF1Asecrets \u91CC\u6CA1\u6709 ${FREE_TIER_ENV_KEY2}\u3002\u5148\u9886\u53F7\uFF1A
|
|
@@ -32830,8 +32973,8 @@ async function main() {
|
|
|
32830
32973
|
else if (args[i] === "--note" && args[i + 1]) note = args[++i];
|
|
32831
32974
|
else if (args[i] === "--dry-run") dryRun2 = true;
|
|
32832
32975
|
}
|
|
32833
|
-
if (!exportStateDir) exportStateDir =
|
|
32834
|
-
if (!agentName) agentName =
|
|
32976
|
+
if (!exportStateDir) exportStateDir = path43.resolve(process.cwd());
|
|
32977
|
+
if (!agentName) agentName = path43.basename(exportStateDir);
|
|
32835
32978
|
await doExport2({ agentName, stateDir: exportStateDir, note, dryRun: dryRun2 });
|
|
32836
32979
|
process.exit(0);
|
|
32837
32980
|
}
|
|
@@ -32853,7 +32996,7 @@ async function main() {
|
|
|
32853
32996
|
console.error("\u274C import \u9700\u8981 --state-dir <path>");
|
|
32854
32997
|
process.exit(1);
|
|
32855
32998
|
}
|
|
32856
|
-
if (!agentName) agentName =
|
|
32999
|
+
if (!agentName) agentName = path43.basename(importStateDir);
|
|
32857
33000
|
await doImport2({ agentName, stateDir: importStateDir, version, archiveFile: archiveFile || void 0, dryRun: dryRun2 });
|
|
32858
33001
|
process.exit(0);
|
|
32859
33002
|
}
|
|
@@ -32881,18 +33024,18 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
32881
33024
|
}
|
|
32882
33025
|
}
|
|
32883
33026
|
if (!configPath2) {
|
|
32884
|
-
const defaultCfg =
|
|
32885
|
-
const homeCfg =
|
|
32886
|
-
if (
|
|
33027
|
+
const defaultCfg = path43.join("configs", "main7.json");
|
|
33028
|
+
const homeCfg = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
|
|
33029
|
+
if (fs43.existsSync(defaultCfg)) {
|
|
32887
33030
|
configPath2 = defaultCfg;
|
|
32888
|
-
} else if (
|
|
33031
|
+
} else if (fs43.existsSync(homeCfg)) {
|
|
32889
33032
|
configPath2 = homeCfg;
|
|
32890
33033
|
console.log(` \u4F7F\u7528\u9ED8\u8BA4 config: ${homeCfg}`);
|
|
32891
33034
|
} else {
|
|
32892
33035
|
const ptr = readHomePointer();
|
|
32893
33036
|
if (ptr?.stateDir) {
|
|
32894
|
-
const ptrCfg =
|
|
32895
|
-
if (
|
|
33037
|
+
const ptrCfg = path43.join(ptr.stateDir, "configs", "main7.json");
|
|
33038
|
+
if (fs43.existsSync(ptrCfg)) {
|
|
32896
33039
|
configPath2 = ptrCfg;
|
|
32897
33040
|
console.log(` \u4F7F\u7528 config: ${ptrCfg}`);
|
|
32898
33041
|
}
|
|
@@ -32905,26 +33048,26 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
32905
33048
|
}
|
|
32906
33049
|
}
|
|
32907
33050
|
}
|
|
32908
|
-
if (configPath2 && !
|
|
33051
|
+
if (configPath2 && !fs43.existsSync(configPath2)) {
|
|
32909
33052
|
console.error(`\u274C config \u6587\u4EF6\u4E0D\u5B58\u5728: ${configPath2}`);
|
|
32910
33053
|
console.error(" \u7528\u6CD5: engine7 start [configs/xxx.json | --config <path>]");
|
|
32911
33054
|
process.exit(1);
|
|
32912
33055
|
}
|
|
32913
|
-
const { execSync:
|
|
33056
|
+
const { execSync: execSync4, spawn: spawn5 } = await import("node:child_process");
|
|
32914
33057
|
let enginePath;
|
|
32915
|
-
const localPath =
|
|
32916
|
-
if (
|
|
33058
|
+
const localPath = path43.join("node_modules", "engine7", "dist", "main.mjs");
|
|
33059
|
+
if (fs43.existsSync(localPath)) {
|
|
32917
33060
|
enginePath = localPath;
|
|
32918
33061
|
} else {
|
|
32919
|
-
const cliPath =
|
|
32920
|
-
const distDir =
|
|
32921
|
-
const candidate =
|
|
32922
|
-
if (
|
|
33062
|
+
const cliPath = path43.resolve(process.argv[1]);
|
|
33063
|
+
const distDir = path43.dirname(cliPath);
|
|
33064
|
+
const candidate = path43.join(distDir, "main.mjs");
|
|
33065
|
+
if (fs43.existsSync(candidate)) {
|
|
32923
33066
|
enginePath = candidate;
|
|
32924
33067
|
} else {
|
|
32925
33068
|
try {
|
|
32926
|
-
const globalRoot =
|
|
32927
|
-
enginePath =
|
|
33069
|
+
const globalRoot = execSync4("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
33070
|
+
enginePath = path43.join(globalRoot, "engine7", "dist", "main.mjs");
|
|
32928
33071
|
} catch {
|
|
32929
33072
|
console.error("\u274C \u627E\u4E0D\u5230 engine7 main.mjs");
|
|
32930
33073
|
process.exit(1);
|
|
@@ -32934,29 +33077,23 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
32934
33077
|
console.log(label);
|
|
32935
33078
|
console.log(` config: ${configPath2}`);
|
|
32936
33079
|
console.log(` engine: ${enginePath}`);
|
|
32937
|
-
const
|
|
32938
|
-
const configAbs = path42.resolve(configPath2);
|
|
32939
|
-
const myPid = process.pid;
|
|
33080
|
+
const configAbs = path43.resolve(configPath2);
|
|
32940
33081
|
try {
|
|
32941
|
-
|
|
32942
|
-
|
|
32943
|
-
|
|
32944
|
-
|
|
32945
|
-
|
|
32946
|
-
if (otherPids) {
|
|
32947
|
-
console.log(`[start] Killing existing engine (PID: ${otherPids})...`);
|
|
32948
|
-
execSync3(`echo "${otherPids}" | xargs kill -9 2>/dev/null || true`);
|
|
32949
|
-
await new Promise((r) => setTimeout(r, 2e3));
|
|
32950
|
-
}
|
|
33082
|
+
const stateDir = engineStateDirOfConfig(configAbs);
|
|
33083
|
+
const killed = stateDir ? killOwnEngineForStateDir(stateDir) : null;
|
|
33084
|
+
if (killed !== null) {
|
|
33085
|
+
console.log(`[start] Killing existing engine (PID: ${killed})...`);
|
|
33086
|
+
await waitForPidGone(killed);
|
|
32951
33087
|
}
|
|
32952
|
-
} catch {
|
|
33088
|
+
} catch (err) {
|
|
33089
|
+
console.warn(`[start] \u6740\u65E7\u8FDB\u7A0B\u5931\u8D25\uFF08\u4E0D\u6321\u542F\u52A8\uFF09\uFF1A${err.message}`);
|
|
32953
33090
|
}
|
|
32954
33091
|
console.log("");
|
|
32955
33092
|
const envForChild = { ...process.env };
|
|
32956
33093
|
const { stateDir: secretsStateDir, configName: secretsCfgName } = resolveConfigIdentity(configPath2);
|
|
32957
33094
|
for (const secretPath of secretsCandidates(secretsStateDir, secretsCfgName)) {
|
|
32958
|
-
if (
|
|
32959
|
-
const content =
|
|
33095
|
+
if (fs43.existsSync(secretPath)) {
|
|
33096
|
+
const content = fs43.readFileSync(secretPath, "utf-8");
|
|
32960
33097
|
for (const line of content.split("\n")) {
|
|
32961
33098
|
const trimmed = line.trim();
|
|
32962
33099
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -33004,7 +33141,6 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
33004
33141
|
process.exit(0);
|
|
33005
33142
|
}
|
|
33006
33143
|
if (action === "reset") {
|
|
33007
|
-
const { execSync: execSync3 } = await import("node:child_process");
|
|
33008
33144
|
let configPath2 = "";
|
|
33009
33145
|
let mode = "archive";
|
|
33010
33146
|
let dropN = 3;
|
|
@@ -33031,14 +33167,14 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
33031
33167
|
console.error(`\u274C \u672A\u77E5\u6A21\u5F0F: ${mode}\uFF08\u53EF\u9009: archive / drop-last / strip-images\uFF09`);
|
|
33032
33168
|
process.exit(1);
|
|
33033
33169
|
}
|
|
33034
|
-
const configRaw = JSON.parse(
|
|
33170
|
+
const configRaw = JSON.parse(fs43.readFileSync(configPath2, "utf-8"));
|
|
33035
33171
|
const stateDir = configRaw.stateDir;
|
|
33036
33172
|
if (!stateDir) {
|
|
33037
33173
|
console.error("\u274C config \u91CC\u6CA1\u6709 stateDir");
|
|
33038
33174
|
process.exit(1);
|
|
33039
33175
|
}
|
|
33040
|
-
const sessionsDir =
|
|
33041
|
-
if (!
|
|
33176
|
+
const sessionsDir = path43.join(stateDir, "agents", "main", "sessions");
|
|
33177
|
+
if (!fs43.existsSync(sessionsDir)) {
|
|
33042
33178
|
console.error(`\u274C sessions \u76EE\u5F55\u4E0D\u5B58\u5728: ${sessionsDir}`);
|
|
33043
33179
|
process.exit(1);
|
|
33044
33180
|
}
|
|
@@ -33046,56 +33182,54 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
33046
33182
|
console.log(` config: ${configPath2}`);
|
|
33047
33183
|
console.log(` mode: ${mode}`);
|
|
33048
33184
|
if (mode === "drop-last") console.log(` n: ${dropN}`);
|
|
33049
|
-
const platformMapPath =
|
|
33050
|
-
const indexPath =
|
|
33185
|
+
const platformMapPath = path43.join(sessionsDir, "platform-map.json");
|
|
33186
|
+
const indexPath = path43.join(sessionsDir, "session-index.json");
|
|
33051
33187
|
let sessionFileUUID = null;
|
|
33052
|
-
if (
|
|
33053
|
-
const index = JSON.parse(
|
|
33188
|
+
if (fs43.existsSync(indexPath)) {
|
|
33189
|
+
const index = JSON.parse(fs43.readFileSync(indexPath, "utf-8"));
|
|
33054
33190
|
const entries2 = Object.values(index);
|
|
33055
33191
|
if (entries2.length > 0) {
|
|
33056
33192
|
const fileVal = entries2[0].file || "";
|
|
33057
|
-
sessionFileUUID =
|
|
33193
|
+
sessionFileUUID = path43.isAbsolute(fileVal) ? path43.basename(fileVal, ".jsonl") : fileVal.replace(".jsonl", "");
|
|
33058
33194
|
}
|
|
33059
33195
|
}
|
|
33060
33196
|
if (!sessionFileUUID) {
|
|
33061
|
-
const jsonlFiles =
|
|
33197
|
+
const jsonlFiles = fs43.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs43.statSync(path43.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
33062
33198
|
if (jsonlFiles.length === 0) {
|
|
33063
33199
|
console.error("\u274C \u627E\u4E0D\u5230\u6D3B\u8DC3\u7684 session JSONL \u6587\u4EF6");
|
|
33064
33200
|
process.exit(1);
|
|
33065
33201
|
}
|
|
33066
33202
|
sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
|
|
33067
33203
|
}
|
|
33068
|
-
let jsonlPath =
|
|
33069
|
-
if (!
|
|
33070
|
-
const jsonlFiles =
|
|
33204
|
+
let jsonlPath = path43.join(sessionsDir, `${sessionFileUUID}.jsonl`);
|
|
33205
|
+
if (!fs43.existsSync(jsonlPath)) {
|
|
33206
|
+
const jsonlFiles = fs43.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs43.statSync(path43.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
33071
33207
|
if (jsonlFiles.length === 0) {
|
|
33072
33208
|
console.error(`\u274C JSONL \u6587\u4EF6\u4E0D\u5B58\u5728: ${jsonlPath}`);
|
|
33073
33209
|
process.exit(1);
|
|
33074
33210
|
}
|
|
33075
33211
|
sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
|
|
33076
|
-
jsonlPath =
|
|
33212
|
+
jsonlPath = path43.join(sessionsDir, `${sessionFileUUID}.jsonl`);
|
|
33077
33213
|
}
|
|
33078
33214
|
console.log(` file: ${jsonlPath}`);
|
|
33079
|
-
const configName = path42.basename(configPath2);
|
|
33080
33215
|
if (autoRestart) {
|
|
33081
33216
|
try {
|
|
33082
|
-
const
|
|
33083
|
-
const
|
|
33084
|
-
|
|
33085
|
-
if (otherPids) {
|
|
33217
|
+
const stateDir2 = engineStateDirOfConfig(path43.resolve(configPath2));
|
|
33218
|
+
const killed = stateDir2 ? killOwnEngineForStateDir(stateDir2) : null;
|
|
33219
|
+
if (killed !== null) {
|
|
33086
33220
|
console.log(`
|
|
33087
|
-
Killing engine (PID: ${
|
|
33088
|
-
|
|
33089
|
-
await new Promise((r) => setTimeout(r, 2e3));
|
|
33221
|
+
Killing engine (PID: ${killed})...`);
|
|
33222
|
+
await waitForPidGone(killed);
|
|
33090
33223
|
}
|
|
33091
|
-
} catch {
|
|
33224
|
+
} catch (err) {
|
|
33225
|
+
console.warn(`[session] \u6740\u65E7\u8FDB\u7A0B\u5931\u8D25\uFF08\u4E0D\u6321\u91CD\u7F6E\uFF09\uFF1A${err.message}`);
|
|
33092
33226
|
}
|
|
33093
33227
|
}
|
|
33094
33228
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
33095
|
-
const { readFileSync: readFileSync45, writeFileSync: writeFileSync26, renameSync: renameSync5 } =
|
|
33229
|
+
const { readFileSync: readFileSync45, writeFileSync: writeFileSync26, renameSync: renameSync5 } = fs43;
|
|
33096
33230
|
if (mode === "archive") {
|
|
33097
33231
|
const archiveName = `${sessionFileUUID}.jsonl.archived.${timestamp}`;
|
|
33098
|
-
renameSync5(jsonlPath,
|
|
33232
|
+
renameSync5(jsonlPath, path43.join(sessionsDir, archiveName));
|
|
33099
33233
|
console.log(`
|
|
33100
33234
|
\u2705 \u5F52\u6863\u5B8C\u6210: ${archiveName}`);
|
|
33101
33235
|
console.log(` \u91CD\u542F\u540E\u5C06\u4ECE\u7A7A\u767D\u4F1A\u8BDD\u5F00\u59CB`);
|
|
@@ -33170,12 +33304,12 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
33170
33304
|
\u2705 \u6458\u9664 ${stripped} \u884C\u56FE\u7247\u76F8\u5173\u5185\u5BB9`);
|
|
33171
33305
|
}
|
|
33172
33306
|
if (autoRestart) {
|
|
33173
|
-
const realCliPath =
|
|
33174
|
-
const cliDir =
|
|
33175
|
-
const pkgRoot =
|
|
33176
|
-
let enginePath =
|
|
33177
|
-
if (!
|
|
33178
|
-
enginePath =
|
|
33307
|
+
const realCliPath = fs43.realpathSync(process.argv[1]);
|
|
33308
|
+
const cliDir = path43.dirname(realCliPath);
|
|
33309
|
+
const pkgRoot = path43.resolve(cliDir, "..");
|
|
33310
|
+
let enginePath = path43.join(pkgRoot, "dist", "main.mjs");
|
|
33311
|
+
if (!fs43.existsSync(enginePath)) {
|
|
33312
|
+
enginePath = path43.join(cliDir, "main.mjs");
|
|
33179
33313
|
}
|
|
33180
33314
|
console.log(`
|
|
33181
33315
|
\u{1F680} \u62C9\u8D77 engine...`);
|
|
@@ -33215,18 +33349,18 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
|
|
|
33215
33349
|
let configPath2 = cfg;
|
|
33216
33350
|
let cwd = svcCwd;
|
|
33217
33351
|
if (!configPath2) {
|
|
33218
|
-
const defaultCfg =
|
|
33219
|
-
const homeCfg =
|
|
33220
|
-
if (
|
|
33352
|
+
const defaultCfg = path43.join(cwd, "configs", "main7.json");
|
|
33353
|
+
const homeCfg = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
|
|
33354
|
+
if (fs43.existsSync(defaultCfg)) {
|
|
33221
33355
|
configPath2 = defaultCfg;
|
|
33222
|
-
} else if (
|
|
33356
|
+
} else if (fs43.existsSync(homeCfg)) {
|
|
33223
33357
|
configPath2 = homeCfg;
|
|
33224
|
-
cwd =
|
|
33358
|
+
cwd = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
33225
33359
|
} else {
|
|
33226
33360
|
const ptr = readHomePointer();
|
|
33227
33361
|
if (ptr?.stateDir) {
|
|
33228
|
-
const ptrCfg =
|
|
33229
|
-
if (
|
|
33362
|
+
const ptrCfg = path43.join(ptr.stateDir, "configs", "main7.json");
|
|
33363
|
+
if (fs43.existsSync(ptrCfg)) {
|
|
33230
33364
|
configPath2 = ptrCfg;
|
|
33231
33365
|
cwd = ptr.stateDir;
|
|
33232
33366
|
}
|
|
@@ -33239,32 +33373,32 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
|
|
|
33239
33373
|
}
|
|
33240
33374
|
}
|
|
33241
33375
|
}
|
|
33242
|
-
const { execSync:
|
|
33376
|
+
const { execSync: execSync4 } = await import("node:child_process");
|
|
33243
33377
|
const engine7Bin = process.argv[1];
|
|
33244
33378
|
if (action === "install") {
|
|
33245
33379
|
if (process.platform === "win32") {
|
|
33246
33380
|
const taskName = "Engine7";
|
|
33247
|
-
const wrapperPath =
|
|
33381
|
+
const wrapperPath = path43.join(cwd, "engine7-start.cmd");
|
|
33248
33382
|
const wrapperContent = buildServiceWrapper({
|
|
33249
33383
|
cwd,
|
|
33250
33384
|
nodeExe: nodeExe || void 0,
|
|
33251
|
-
cliMjs:
|
|
33252
|
-
configPath:
|
|
33385
|
+
cliMjs: path43.resolve(engine7Bin),
|
|
33386
|
+
configPath: path43.resolve(configPath2)
|
|
33253
33387
|
});
|
|
33254
|
-
|
|
33255
|
-
const startupDir =
|
|
33256
|
-
process.env.APPDATA ||
|
|
33388
|
+
fs43.writeFileSync(wrapperPath, wrapperContent);
|
|
33389
|
+
const startupDir = path43.join(
|
|
33390
|
+
process.env.APPDATA || path43.join(process.env.USERPROFILE || "", "AppData", "Roaming"),
|
|
33257
33391
|
"Microsoft",
|
|
33258
33392
|
"Windows",
|
|
33259
33393
|
"Start Menu",
|
|
33260
33394
|
"Programs",
|
|
33261
33395
|
"Startup"
|
|
33262
33396
|
);
|
|
33263
|
-
|
|
33264
|
-
const vbsPath =
|
|
33397
|
+
fs43.mkdirSync(startupDir, { recursive: true });
|
|
33398
|
+
const vbsPath = path43.join(startupDir, "Engine7.vbs");
|
|
33265
33399
|
const nodeExePath = nodeExe || process.execPath;
|
|
33266
|
-
const cliMjsPath =
|
|
33267
|
-
const absCfg =
|
|
33400
|
+
const cliMjsPath = path43.resolve(engine7Bin);
|
|
33401
|
+
const absCfg = path43.resolve(configPath2);
|
|
33268
33402
|
const vbs = [
|
|
33269
33403
|
"' Engine 7 \u5F00\u673A\u81EA\u542F\uFF08\u542F\u52A8\u6587\u4EF6\u5939\uFF0C\u514D\u7BA1\u7406\u5458\uFF09",
|
|
33270
33404
|
'Set fso = CreateObject("Scripting.FileSystemObject")',
|
|
@@ -33280,15 +33414,15 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
|
|
|
33280
33414
|
's.Run """' + nodeExePath + '"" ""' + cliMjsPath + '"" start --config ""' + absCfg + '""", 0, False',
|
|
33281
33415
|
""
|
|
33282
33416
|
].join(String.fromCharCode(13) + String.fromCharCode(10));
|
|
33283
|
-
|
|
33417
|
+
fs43.writeFileSync(vbsPath, vbs);
|
|
33284
33418
|
console.log(`\u2705 \u5F00\u673A\u81EA\u542F\u52A8\u5DF2\u6CE8\u518C\uFF08\u542F\u52A8\u6587\u4EF6\u5939: ${vbsPath}\uFF09`);
|
|
33285
33419
|
} else if (process.platform === "darwin") {
|
|
33286
33420
|
const label = "com.engine7.agent";
|
|
33287
|
-
const plistDir =
|
|
33288
|
-
|
|
33289
|
-
const plistPath =
|
|
33290
|
-
const localCli =
|
|
33291
|
-
const cliMjs =
|
|
33421
|
+
const plistDir = path43.join(process.env.HOME, "Library", "LaunchAgents");
|
|
33422
|
+
fs43.mkdirSync(plistDir, { recursive: true });
|
|
33423
|
+
const plistPath = path43.join(plistDir, `${label}.plist`);
|
|
33424
|
+
const localCli = path43.join("node_modules", "engine7", "dist", "cli.mjs");
|
|
33425
|
+
const cliMjs = fs43.existsSync(localCli) ? path43.resolve(localCli) : path43.join(path43.dirname(path43.dirname(engine7Bin)), "lib", "node_modules", "engine7", "dist", "cli.mjs");
|
|
33292
33426
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
33293
33427
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
33294
33428
|
<plist version="1.0">
|
|
@@ -33300,16 +33434,16 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
|
|
|
33300
33434
|
<string>${cliMjs}</string>
|
|
33301
33435
|
<string>start</string>
|
|
33302
33436
|
<string>--config</string>
|
|
33303
|
-
<string>${
|
|
33437
|
+
<string>${path43.resolve(configPath2)}</string>
|
|
33304
33438
|
</array>
|
|
33305
33439
|
<key>WorkingDirectory</key><string>${cwd}</string>
|
|
33306
33440
|
<key>RunAtLoad</key><true/>
|
|
33307
33441
|
<key>KeepAlive</key><true/>
|
|
33308
33442
|
</dict>
|
|
33309
33443
|
</plist>`;
|
|
33310
|
-
|
|
33444
|
+
fs43.writeFileSync(plistPath, plist);
|
|
33311
33445
|
try {
|
|
33312
|
-
|
|
33446
|
+
execSync4(`launchctl load "${plistPath}"`, { stdio: "inherit" });
|
|
33313
33447
|
console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
|
|
33314
33448
|
console.log(` ${plistPath}`);
|
|
33315
33449
|
} catch {
|
|
@@ -33318,9 +33452,9 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
|
|
|
33318
33452
|
}
|
|
33319
33453
|
} else {
|
|
33320
33454
|
const svcName = "engine7";
|
|
33321
|
-
const svcDir =
|
|
33322
|
-
|
|
33323
|
-
const svcPath =
|
|
33455
|
+
const svcDir = path43.join(process.env.HOME, ".config", "systemd", "user");
|
|
33456
|
+
fs43.mkdirSync(svcDir, { recursive: true });
|
|
33457
|
+
const svcPath = path43.join(svcDir, `${svcName}.service`);
|
|
33324
33458
|
const svc = `[Unit]
|
|
33325
33459
|
Description=Engine 7 Agent
|
|
33326
33460
|
After=network.target
|
|
@@ -33328,16 +33462,16 @@ After=network.target
|
|
|
33328
33462
|
[Service]
|
|
33329
33463
|
Type=simple
|
|
33330
33464
|
WorkingDirectory=${cwd}
|
|
33331
|
-
ExecStart=${process.execPath} ${engine7Bin} start --config ${
|
|
33465
|
+
ExecStart=${process.execPath} ${engine7Bin} start --config ${path43.resolve(configPath2)}
|
|
33332
33466
|
Restart=on-failure
|
|
33333
33467
|
RestartSec=10
|
|
33334
33468
|
|
|
33335
33469
|
[Install]
|
|
33336
33470
|
WantedBy=default.target`;
|
|
33337
|
-
|
|
33471
|
+
fs43.writeFileSync(svcPath, svc);
|
|
33338
33472
|
try {
|
|
33339
|
-
|
|
33340
|
-
|
|
33473
|
+
execSync4(`systemctl --user daemon-reload`, { stdio: "inherit" });
|
|
33474
|
+
execSync4(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
|
|
33341
33475
|
console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
|
|
33342
33476
|
console.log(` ${svcPath}`);
|
|
33343
33477
|
} catch {
|
|
@@ -33347,8 +33481,8 @@ WantedBy=default.target`;
|
|
|
33347
33481
|
}
|
|
33348
33482
|
} else if (action === "uninstall") {
|
|
33349
33483
|
if (process.platform === "win32") {
|
|
33350
|
-
const vbsPath =
|
|
33351
|
-
process.env.APPDATA ||
|
|
33484
|
+
const vbsPath = path43.join(
|
|
33485
|
+
process.env.APPDATA || path43.join(process.env.USERPROFILE || "", "AppData", "Roaming"),
|
|
33352
33486
|
"Microsoft",
|
|
33353
33487
|
"Windows",
|
|
33354
33488
|
"Start Menu",
|
|
@@ -33357,46 +33491,46 @@ WantedBy=default.target`;
|
|
|
33357
33491
|
"Engine7.vbs"
|
|
33358
33492
|
);
|
|
33359
33493
|
try {
|
|
33360
|
-
|
|
33494
|
+
execSync4(`schtasks /delete /tn "Engine7" /f`, { stdio: "ignore" });
|
|
33361
33495
|
} catch {
|
|
33362
33496
|
}
|
|
33363
|
-
if (
|
|
33364
|
-
|
|
33497
|
+
if (fs43.existsSync(vbsPath)) {
|
|
33498
|
+
fs43.rmSync(vbsPath, { force: true });
|
|
33365
33499
|
console.log(`\u2705 \u5F00\u673A\u81EA\u542F\u52A8\u5DF2\u79FB\u9664\uFF08${vbsPath}\uFF09`);
|
|
33366
33500
|
} else {
|
|
33367
33501
|
console.log("\uFF08\u5F00\u673A\u81EA\u542F\u52A8\u672C\u6765\u5C31\u6CA1\u6CE8\u518C\uFF09");
|
|
33368
33502
|
}
|
|
33369
33503
|
} else if (process.platform === "darwin") {
|
|
33370
|
-
const plistPath =
|
|
33504
|
+
const plistPath = path43.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
|
|
33371
33505
|
try {
|
|
33372
|
-
|
|
33506
|
+
execSync4(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
|
|
33373
33507
|
} catch {
|
|
33374
33508
|
}
|
|
33375
33509
|
try {
|
|
33376
|
-
|
|
33510
|
+
fs43.unlinkSync(plistPath);
|
|
33377
33511
|
} catch {
|
|
33378
33512
|
}
|
|
33379
33513
|
console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u5220\u9664`);
|
|
33380
33514
|
} else {
|
|
33381
33515
|
try {
|
|
33382
|
-
|
|
33516
|
+
execSync4(`systemctl --user disable engine7`, { stdio: "inherit" });
|
|
33383
33517
|
} catch {
|
|
33384
33518
|
}
|
|
33385
|
-
const svcPath =
|
|
33519
|
+
const svcPath = path43.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
|
|
33386
33520
|
try {
|
|
33387
|
-
|
|
33521
|
+
fs43.unlinkSync(svcPath);
|
|
33388
33522
|
} catch {
|
|
33389
33523
|
}
|
|
33390
33524
|
try {
|
|
33391
|
-
|
|
33525
|
+
execSync4(`systemctl --user daemon-reload`, { stdio: "inherit" });
|
|
33392
33526
|
} catch {
|
|
33393
33527
|
}
|
|
33394
33528
|
console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u5220\u9664`);
|
|
33395
33529
|
}
|
|
33396
33530
|
} else if (action === "status") {
|
|
33397
33531
|
if (process.platform === "win32") {
|
|
33398
|
-
const vbsPath =
|
|
33399
|
-
process.env.APPDATA ||
|
|
33532
|
+
const vbsPath = path43.join(
|
|
33533
|
+
process.env.APPDATA || path43.join(process.env.USERPROFILE || "", "AppData", "Roaming"),
|
|
33400
33534
|
"Microsoft",
|
|
33401
33535
|
"Windows",
|
|
33402
33536
|
"Start Menu",
|
|
@@ -33404,17 +33538,17 @@ WantedBy=default.target`;
|
|
|
33404
33538
|
"Startup",
|
|
33405
33539
|
"Engine7.vbs"
|
|
33406
33540
|
);
|
|
33407
|
-
console.log(
|
|
33541
|
+
console.log(fs43.existsSync(vbsPath) ? `\u2705 \u5DF2\u6CE8\u518C\uFF08\u542F\u52A8\u6587\u4EF6\u5939\uFF09: ${vbsPath}` : "\u274C \u672A\u6CE8\u518C");
|
|
33408
33542
|
} else if (process.platform === "darwin") {
|
|
33409
|
-
const plistPath =
|
|
33410
|
-
if (
|
|
33543
|
+
const plistPath = path43.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
|
|
33544
|
+
if (fs43.existsSync(plistPath)) {
|
|
33411
33545
|
console.log("\u2705 \u5DF2\u5B89\u88C5\uFF08launchd\uFF09");
|
|
33412
33546
|
} else {
|
|
33413
33547
|
console.log("\u274C \u672A\u5B89\u88C5");
|
|
33414
33548
|
}
|
|
33415
33549
|
} else {
|
|
33416
33550
|
try {
|
|
33417
|
-
|
|
33551
|
+
execSync4(`systemctl --user is-enabled engine7`, { stdio: "inherit" });
|
|
33418
33552
|
} catch {
|
|
33419
33553
|
console.log("\u274C \u672A\u5B89\u88C5");
|
|
33420
33554
|
}
|
|
@@ -33440,8 +33574,8 @@ WantedBy=default.target`;
|
|
|
33440
33574
|
console.log(`
|
|
33441
33575
|
\u{1F680} engine7 init`);
|
|
33442
33576
|
console.log(` state-dir: ${opts.stateDir}`);
|
|
33443
|
-
if (
|
|
33444
|
-
const files =
|
|
33577
|
+
if (fs43.existsSync(opts.stateDir) && !opts.dryRun) {
|
|
33578
|
+
const files = fs43.readdirSync(opts.stateDir);
|
|
33445
33579
|
if (files.length > 0) {
|
|
33446
33580
|
if (opts.force) {
|
|
33447
33581
|
if (looksLikeAppInstall(opts.stateDir)) {
|
|
@@ -33454,10 +33588,10 @@ WantedBy=default.target`;
|
|
|
33454
33588
|
}
|
|
33455
33589
|
console.log(`
|
|
33456
33590
|
\u26A0\uFE0F --force: \u6E05\u7A7A\u5DF2\u6709\u76EE\u5F55 ${opts.stateDir}`);
|
|
33457
|
-
|
|
33591
|
+
fs43.rmSync(opts.stateDir, { recursive: true, force: true });
|
|
33458
33592
|
} else {
|
|
33459
|
-
const existingConfig =
|
|
33460
|
-
if (
|
|
33593
|
+
const existingConfig = path43.join(opts.stateDir, "configs", "main7.json");
|
|
33594
|
+
if (fs43.existsSync(existingConfig)) {
|
|
33461
33595
|
console.log(`
|
|
33462
33596
|
\u267B\uFE0F \u68C0\u6D4B\u5230\u5DF2\u6709\u914D\u7F6E: ${existingConfig}`);
|
|
33463
33597
|
console.log(` \u2192 \u590D\u8DD1\u6A21\u5F0F\uFF1A\u663E\u793A\u73B0\u6709\u914D\u7F6E\uFF0C\u56DE\u8F66\u4FDD\u7559\uFF0C\u6539\u4E86\u624D\u751F\u6548\uFF08\u4E0D\u4F1A\u6E05\u7A7A\u76EE\u5F55\uFF09`);
|
|
@@ -33538,12 +33672,12 @@ WantedBy=default.target`;
|
|
|
33538
33672
|
let photoSrc = "";
|
|
33539
33673
|
if (answers?.selfie?.photoPath) {
|
|
33540
33674
|
const { dimsOf: dimsOf2 } = await Promise.resolve().then(() => (init_my_selfie(), my_selfie_exports));
|
|
33541
|
-
const src =
|
|
33542
|
-
const ext =
|
|
33675
|
+
const src = path43.resolve(answers.selfie.photoPath.trim());
|
|
33676
|
+
const ext = path43.extname(src).toLowerCase();
|
|
33543
33677
|
if (!PHOTO_EXTS.includes(ext)) {
|
|
33544
33678
|
throw new Error(`\u7167\u7247\u683C\u5F0F\u4E0D\u652F\u6301\uFF1A${ext || "(\u6CA1\u6709\u540E\u7F00)"}\u3002\u8BF7\u7528 PNG / JPEG / WebP\u3002`);
|
|
33545
33679
|
}
|
|
33546
|
-
if (!
|
|
33680
|
+
if (!fs43.existsSync(src)) {
|
|
33547
33681
|
throw new Error(`\u7167\u7247\u4E0D\u5B58\u5728\uFF1A${src}`);
|
|
33548
33682
|
}
|
|
33549
33683
|
const dims = dimsOf2(src);
|
|
@@ -33554,7 +33688,7 @@ WantedBy=default.target`;
|
|
|
33554
33688
|
photoSrc = src;
|
|
33555
33689
|
}
|
|
33556
33690
|
const config = generateConfig(values);
|
|
33557
|
-
const configPath =
|
|
33691
|
+
const configPath = path43.join(opts.stateDir, "configs", "main7.json");
|
|
33558
33692
|
const tree = buildDirTree(values);
|
|
33559
33693
|
if (headlessEmit) headlessEmit({ event: "progress", step: "write_config" });
|
|
33560
33694
|
tree.push({
|
|
@@ -33566,22 +33700,22 @@ WantedBy=default.target`;
|
|
|
33566
33700
|
dryRun(tree);
|
|
33567
33701
|
const skillsSrc = findTemplateDir("skills");
|
|
33568
33702
|
if (skillsSrc) {
|
|
33569
|
-
const skills =
|
|
33703
|
+
const skills = fs43.readdirSync(skillsSrc);
|
|
33570
33704
|
for (const s of skills) {
|
|
33571
|
-
console.log(` \u{1F4C1} ${
|
|
33705
|
+
console.log(` \u{1F4C1} ${path43.join(opts.stateDir, "workspace", "skills", s)}`);
|
|
33572
33706
|
}
|
|
33573
33707
|
}
|
|
33574
33708
|
} else {
|
|
33575
33709
|
if (values.chatMode === "auto") {
|
|
33576
33710
|
try {
|
|
33577
|
-
|
|
33711
|
+
fs43.unlinkSync(path43.join(opts.stateDir, "workspace", ".work-mode"));
|
|
33578
33712
|
} catch {
|
|
33579
33713
|
}
|
|
33580
33714
|
}
|
|
33581
33715
|
if (photoSrc && values.selfiePhotoRelPath) {
|
|
33582
|
-
const dest =
|
|
33583
|
-
|
|
33584
|
-
|
|
33716
|
+
const dest = path43.join(opts.stateDir, "workspace", values.selfiePhotoRelPath);
|
|
33717
|
+
fs43.mkdirSync(path43.dirname(dest), { recursive: true });
|
|
33718
|
+
fs43.copyFileSync(photoSrc, dest);
|
|
33585
33719
|
console.log(` \u{1F5BC} \u5F62\u8C61: ${dest}`);
|
|
33586
33720
|
}
|
|
33587
33721
|
if (headlessEmit) headlessEmit({ event: "progress", step: "create_dirs" });
|
|
@@ -33610,58 +33744,58 @@ WantedBy=default.target`;
|
|
|
33610
33744
|
if (headlessEmit) headlessEmit({ event: "progress", step: "copy_skills" });
|
|
33611
33745
|
const skillsSrc = findTemplateDir("skills");
|
|
33612
33746
|
if (skillsSrc) {
|
|
33613
|
-
const skillsDest =
|
|
33614
|
-
|
|
33615
|
-
const skills =
|
|
33747
|
+
const skillsDest = path43.join(opts.stateDir, "workspace", "skills");
|
|
33748
|
+
fs43.mkdirSync(skillsDest, { recursive: true });
|
|
33749
|
+
const skills = fs43.readdirSync(skillsSrc);
|
|
33616
33750
|
for (const s of skills) {
|
|
33617
|
-
copyDirRecursive(
|
|
33751
|
+
copyDirRecursive(path43.join(skillsSrc, s), path43.join(skillsDest, s));
|
|
33618
33752
|
console.log(` \u{1F4E6} skill: ${s}`);
|
|
33619
33753
|
}
|
|
33620
33754
|
}
|
|
33621
33755
|
console.log(`
|
|
33622
33756
|
\u2705 \u521D\u59CB\u5316\u5B8C\u6210\uFF01
|
|
33623
33757
|
`);
|
|
33624
|
-
const homePointer =
|
|
33758
|
+
const homePointer = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
|
|
33625
33759
|
const pointerData = { stateDir: opts.stateDir };
|
|
33626
|
-
|
|
33760
|
+
fs43.writeFileSync(homePointer, JSON.stringify(pointerData, null, 2) + "\n");
|
|
33627
33761
|
console.log(` \u{1F4C4} ${homePointer}\uFF08\u4ECE\u4EFB\u610F\u76EE\u5F55\u90FD\u80FD\u627E\u5230\u6B64 agent\uFF09`);
|
|
33628
33762
|
console.log(`\u4E0B\u4E00\u6B65\uFF1A`);
|
|
33629
33763
|
console.log(` 1. \u68C0\u67E5\u5E76\u4FEE\u6539 ${opts.stateDir}/configs/main7.json`);
|
|
33630
33764
|
console.log(` 2. \u542F\u52A8 Engine: engine7 start\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
|
|
33631
33765
|
console.log(` 3. \u5F00\u673A\u81EA\u542F: engine7 service install\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
|
|
33632
|
-
console.log(` 4. \u67E5\u770B workspace: ${
|
|
33766
|
+
console.log(` 4. \u67E5\u770B workspace: ${path43.join(opts.stateDir, "workspace")}`);
|
|
33633
33767
|
if (headlessEmit) {
|
|
33634
33768
|
headlessEmit({ event: "done", stateDir: opts.stateDir.replace(/\\/g, "/"), configPath: configPath.replace(/\\/g, "/") });
|
|
33635
33769
|
}
|
|
33636
33770
|
}
|
|
33637
33771
|
}
|
|
33638
33772
|
function copyDirRecursive(src, dest) {
|
|
33639
|
-
|
|
33640
|
-
for (const entry of
|
|
33641
|
-
const srcPath =
|
|
33642
|
-
const destPath =
|
|
33773
|
+
fs43.mkdirSync(dest, { recursive: true });
|
|
33774
|
+
for (const entry of fs43.readdirSync(src, { withFileTypes: true })) {
|
|
33775
|
+
const srcPath = path43.join(src, entry.name);
|
|
33776
|
+
const destPath = path43.join(dest, entry.name);
|
|
33643
33777
|
if (entry.isDirectory()) {
|
|
33644
33778
|
copyDirRecursive(srcPath, destPath);
|
|
33645
33779
|
} else {
|
|
33646
|
-
|
|
33780
|
+
fs43.copyFileSync(srcPath, destPath);
|
|
33647
33781
|
}
|
|
33648
33782
|
}
|
|
33649
33783
|
}
|
|
33650
33784
|
function findTemplateDir(name) {
|
|
33651
33785
|
const candidates = [
|
|
33652
|
-
|
|
33653
|
-
|
|
33654
|
-
|
|
33786
|
+
path43.join(__dirname, "..", "templates", name),
|
|
33787
|
+
path43.join(__dirname, "..", "..", "templates", name),
|
|
33788
|
+
path43.join(process.cwd(), "templates", name)
|
|
33655
33789
|
];
|
|
33656
33790
|
for (const p of candidates) {
|
|
33657
|
-
if (
|
|
33791
|
+
if (fs43.existsSync(p)) return p;
|
|
33658
33792
|
}
|
|
33659
33793
|
return null;
|
|
33660
33794
|
}
|
|
33661
33795
|
function readHomePointer() {
|
|
33662
|
-
const ptrPath =
|
|
33796
|
+
const ptrPath = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
|
|
33663
33797
|
try {
|
|
33664
|
-
return JSON.parse(
|
|
33798
|
+
return JSON.parse(fs43.readFileSync(ptrPath, "utf-8"));
|
|
33665
33799
|
} catch {
|
|
33666
33800
|
return null;
|
|
33667
33801
|
}
|