engine7 7.1.67 → 7.1.68
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 +1158 -870
- package/dist/engine-startup.mjs +2869 -1299
- package/dist/main.mjs +2864 -1294
- package/package.json +15 -2
package/dist/cli.mjs
CHANGED
|
@@ -1254,14 +1254,14 @@ var init_live = __esm({
|
|
|
1254
1254
|
}
|
|
1255
1255
|
/** 把改动写回 config 文件对应段(找不到文件路径则只内存生效) */
|
|
1256
1256
|
async persistToFile(dotPath, val) {
|
|
1257
|
-
const
|
|
1257
|
+
const fs29 = await import("node:fs");
|
|
1258
1258
|
const cfgPath = this.current?._configFilePath;
|
|
1259
|
-
if (!cfgPath || !
|
|
1259
|
+
if (!cfgPath || !fs29.existsSync(cfgPath)) {
|
|
1260
1260
|
console.warn(`[liveConfig] set: no config file path, in-memory only (${dotPath})`);
|
|
1261
1261
|
return;
|
|
1262
1262
|
}
|
|
1263
1263
|
try {
|
|
1264
|
-
const raw = JSON.parse(
|
|
1264
|
+
const raw = JSON.parse(fs29.readFileSync(cfgPath, "utf-8"));
|
|
1265
1265
|
const keys = dotPath.split(".");
|
|
1266
1266
|
let o = raw;
|
|
1267
1267
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -1269,7 +1269,7 @@ var init_live = __esm({
|
|
|
1269
1269
|
o = o[keys[i]];
|
|
1270
1270
|
}
|
|
1271
1271
|
o[keys[keys.length - 1]] = val;
|
|
1272
|
-
|
|
1272
|
+
fs29.writeFileSync(cfgPath, JSON.stringify(raw, null, 2) + "\n", "utf-8");
|
|
1273
1273
|
console.log(`[liveConfig] persisted ${dotPath} = ${JSON.stringify(val)} to ${cfgPath}`);
|
|
1274
1274
|
markSelfWrite();
|
|
1275
1275
|
} catch (e) {
|
|
@@ -1515,7 +1515,6 @@ function loadConfig(configPath) {
|
|
|
1515
1515
|
services: raw.services,
|
|
1516
1516
|
commands: raw.commands,
|
|
1517
1517
|
compaction: raw.compaction,
|
|
1518
|
-
cognifold: raw.cognifold,
|
|
1519
1518
|
everos: raw.everos,
|
|
1520
1519
|
// 保留原始 agents 段,供 liveConfig.get('agents.defaults.*') 读取(如 privateTools 开关)
|
|
1521
1520
|
agents: raw.agents,
|
|
@@ -1684,6 +1683,130 @@ var init_registry = __esm({
|
|
|
1684
1683
|
}
|
|
1685
1684
|
});
|
|
1686
1685
|
|
|
1686
|
+
// src/calendar/db.ts
|
|
1687
|
+
import * as path3 from "node:path";
|
|
1688
|
+
import * as fs3 from "node:fs";
|
|
1689
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
1690
|
+
function getSqlite() {
|
|
1691
|
+
if (!_sqlite) _sqlite = createRequire2(import.meta.url)("node:sqlite");
|
|
1692
|
+
return _sqlite;
|
|
1693
|
+
}
|
|
1694
|
+
function openDb(workspace) {
|
|
1695
|
+
const dir = path3.join(workspace, ".calendar");
|
|
1696
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
1697
|
+
const dbPath = path3.join(dir, "calendar.db");
|
|
1698
|
+
const db2 = new DatabaseSync(dbPath);
|
|
1699
|
+
db2.exec("PRAGMA journal_mode=WAL");
|
|
1700
|
+
db2.exec(`CREATE TABLE IF NOT EXISTS events (
|
|
1701
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1702
|
+
type TEXT NOT NULL,
|
|
1703
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
1704
|
+
event TEXT NOT NULL,
|
|
1705
|
+
day TEXT,
|
|
1706
|
+
time TEXT,
|
|
1707
|
+
date_str TEXT,
|
|
1708
|
+
created_at TEXT NOT NULL,
|
|
1709
|
+
done_at TEXT,
|
|
1710
|
+
archived_at TEXT
|
|
1711
|
+
)`);
|
|
1712
|
+
migrate(db2);
|
|
1713
|
+
return db2;
|
|
1714
|
+
}
|
|
1715
|
+
function migrate(db2) {
|
|
1716
|
+
const cols = new Set(
|
|
1717
|
+
db2.prepare("PRAGMA table_info(events)").all().map((r) => r.name)
|
|
1718
|
+
);
|
|
1719
|
+
if (!cols.has("remind_before_min")) {
|
|
1720
|
+
db2.exec("ALTER TABLE events ADD COLUMN remind_before_min INTEGER DEFAULT 60");
|
|
1721
|
+
}
|
|
1722
|
+
if (!cols.has("remind_at")) {
|
|
1723
|
+
db2.exec("ALTER TABLE events ADD COLUMN remind_at TEXT");
|
|
1724
|
+
}
|
|
1725
|
+
if (!cols.has("reminded")) {
|
|
1726
|
+
db2.exec("ALTER TABLE events ADD COLUMN reminded INTEGER DEFAULT 0");
|
|
1727
|
+
}
|
|
1728
|
+
if (!cols.has("time_exact")) {
|
|
1729
|
+
db2.exec("ALTER TABLE events ADD COLUMN time_exact TEXT");
|
|
1730
|
+
}
|
|
1731
|
+
if (!cols.has("start_time")) {
|
|
1732
|
+
db2.exec("ALTER TABLE events ADD COLUMN start_time TEXT");
|
|
1733
|
+
}
|
|
1734
|
+
if (!cols.has("duration_min")) {
|
|
1735
|
+
db2.exec("ALTER TABLE events ADD COLUMN duration_min INTEGER");
|
|
1736
|
+
}
|
|
1737
|
+
if (!cols.has("created_channel")) {
|
|
1738
|
+
db2.exec("ALTER TABLE events ADD COLUMN created_channel TEXT");
|
|
1739
|
+
}
|
|
1740
|
+
if (!cols.has("created_channel_target")) {
|
|
1741
|
+
db2.exec("ALTER TABLE events ADD COLUMN created_channel_target TEXT");
|
|
1742
|
+
}
|
|
1743
|
+
if (!cols.has("repeat_type")) {
|
|
1744
|
+
db2.exec("ALTER TABLE events ADD COLUMN repeat_type TEXT DEFAULT 'once'");
|
|
1745
|
+
}
|
|
1746
|
+
if (!cols.has("doc_path")) {
|
|
1747
|
+
db2.exec("ALTER TABLE events ADD COLUMN doc_path TEXT");
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
var _sqlite, DatabaseSync, TZ_OFFSET_MS;
|
|
1751
|
+
var init_db = __esm({
|
|
1752
|
+
"src/calendar/db.ts"() {
|
|
1753
|
+
"use strict";
|
|
1754
|
+
_sqlite = null;
|
|
1755
|
+
DatabaseSync = new Proxy(function() {
|
|
1756
|
+
}, {
|
|
1757
|
+
construct(_t, args) {
|
|
1758
|
+
return new (getSqlite()).DatabaseSync(...args);
|
|
1759
|
+
},
|
|
1760
|
+
get(_t, prop) {
|
|
1761
|
+
return getSqlite().DatabaseSync[prop];
|
|
1762
|
+
}
|
|
1763
|
+
});
|
|
1764
|
+
TZ_OFFSET_MS = 8 * 60 * 60 * 1e3;
|
|
1765
|
+
}
|
|
1766
|
+
});
|
|
1767
|
+
|
|
1768
|
+
// src/goals/store.ts
|
|
1769
|
+
import fs4 from "node:fs";
|
|
1770
|
+
import path4 from "node:path";
|
|
1771
|
+
function file(stateDir) {
|
|
1772
|
+
return path4.join(stateDir, "goals.json");
|
|
1773
|
+
}
|
|
1774
|
+
function db(stateDir) {
|
|
1775
|
+
const d = openDb(stateDir);
|
|
1776
|
+
d.exec(`CREATE TABLE IF NOT EXISTS goals (id TEXT PRIMARY KEY, objective TEXT NOT NULL, status TEXT NOT NULL, steps_json TEXT NOT NULL, current_step INTEGER NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL, blocker TEXT)`);
|
|
1777
|
+
d.exec(`CREATE TABLE IF NOT EXISTS goal_events (event_id TEXT PRIMARY KEY, goal_id TEXT NOT NULL, type TEXT NOT NULL, payload_json TEXT NOT NULL, created_at TEXT NOT NULL)`);
|
|
1778
|
+
return d;
|
|
1779
|
+
}
|
|
1780
|
+
function read(stateDir) {
|
|
1781
|
+
try {
|
|
1782
|
+
const v = JSON.parse(fs4.readFileSync(file(stateDir), "utf8"));
|
|
1783
|
+
return Array.isArray(v) ? v : [];
|
|
1784
|
+
} catch {
|
|
1785
|
+
return [];
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
function rowToGoal(r) {
|
|
1789
|
+
return { id: r.id, objective: r.objective, status: r.status, steps: JSON.parse(r.steps_json), currentStep: r.current_step, createdAt: r.created_at, updatedAt: r.updated_at, ...r.blocker ? { blocker: r.blocker } : {} };
|
|
1790
|
+
}
|
|
1791
|
+
function migrateLegacy(stateDir, d) {
|
|
1792
|
+
const count = Number(d.prepare("SELECT COUNT(*) AS n FROM goals").get()?.n ?? 0);
|
|
1793
|
+
if (count > 0) return;
|
|
1794
|
+
for (const g of read(stateDir)) d.prepare("INSERT OR IGNORE INTO goals VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(g.id, g.objective, g.status, JSON.stringify(g.steps), g.currentStep, g.createdAt, g.updatedAt, g.blocker ?? null);
|
|
1795
|
+
}
|
|
1796
|
+
function listGoals(stateDir) {
|
|
1797
|
+
const d = db(stateDir);
|
|
1798
|
+
migrateLegacy(stateDir, d);
|
|
1799
|
+
const rows = d.prepare("SELECT * FROM goals ORDER BY created_at").all().map(rowToGoal);
|
|
1800
|
+
d.close?.();
|
|
1801
|
+
return rows;
|
|
1802
|
+
}
|
|
1803
|
+
var init_store = __esm({
|
|
1804
|
+
"src/goals/store.ts"() {
|
|
1805
|
+
"use strict";
|
|
1806
|
+
init_db();
|
|
1807
|
+
}
|
|
1808
|
+
});
|
|
1809
|
+
|
|
1687
1810
|
// src/memory/memdir/paths.ts
|
|
1688
1811
|
var paths_exports = {};
|
|
1689
1812
|
__export(paths_exports, {
|
|
@@ -1695,26 +1818,26 @@ __export(paths_exports, {
|
|
|
1695
1818
|
isAutoMemPath: () => isAutoMemPath,
|
|
1696
1819
|
setMemoryDirOverride: () => setMemoryDirOverride
|
|
1697
1820
|
});
|
|
1698
|
-
import { join as
|
|
1821
|
+
import { join as join4, normalize, sep, isAbsolute, resolve as resolve2 } from "node:path";
|
|
1699
1822
|
function setMemoryDirOverride(dir) {
|
|
1700
1823
|
_overrideMemoryDir = dir;
|
|
1701
1824
|
}
|
|
1702
1825
|
function getAutoMemPath(workspace) {
|
|
1703
|
-
const dir = _overrideMemoryDir ? isAbsolute(_overrideMemoryDir) ? _overrideMemoryDir : resolve2(workspace, _overrideMemoryDir) :
|
|
1826
|
+
const dir = _overrideMemoryDir ? isAbsolute(_overrideMemoryDir) ? _overrideMemoryDir : resolve2(workspace, _overrideMemoryDir) : join4(workspace, AUTO_MEM_DIRNAME);
|
|
1704
1827
|
const normalized = normalize(dir);
|
|
1705
1828
|
return (normalized + sep).normalize("NFC");
|
|
1706
1829
|
}
|
|
1707
1830
|
function getAutoMemEntrypoint(workspace) {
|
|
1708
|
-
return
|
|
1831
|
+
return join4(getAutoMemPath(workspace), ENTRYPOINT_NAME);
|
|
1709
1832
|
}
|
|
1710
1833
|
function isAutoMemPath(absolutePath, workspace) {
|
|
1711
1834
|
const normalizedPath = normalize(absolutePath);
|
|
1712
1835
|
return normalizedPath.startsWith(getAutoMemPath(workspace));
|
|
1713
1836
|
}
|
|
1714
1837
|
async function ensureMemoryDirExists(memoryDir) {
|
|
1715
|
-
const
|
|
1838
|
+
const fs29 = await import("node:fs");
|
|
1716
1839
|
try {
|
|
1717
|
-
await
|
|
1840
|
+
await fs29.promises.mkdir(memoryDir, { recursive: true });
|
|
1718
1841
|
} catch (e) {
|
|
1719
1842
|
const code = e?.code;
|
|
1720
1843
|
if (code !== "EEXIST") {
|
|
@@ -1899,7 +2022,7 @@ __export(memdir_exports, {
|
|
|
1899
2022
|
truncateEntrypointContent: () => truncateEntrypointContent
|
|
1900
2023
|
});
|
|
1901
2024
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
1902
|
-
import { join as
|
|
2025
|
+
import { join as join5 } from "node:path";
|
|
1903
2026
|
function truncateEntrypointContent(raw) {
|
|
1904
2027
|
const trimmed = raw.trim();
|
|
1905
2028
|
const contentLines = trimmed.split("\n");
|
|
@@ -1992,7 +2115,7 @@ function buildMemoryLines(displayName, memoryDir, extraGuidelines, skipIndex = f
|
|
|
1992
2115
|
}
|
|
1993
2116
|
function buildMemoryPrompt(params) {
|
|
1994
2117
|
const { displayName, memoryDir, extraGuidelines } = params;
|
|
1995
|
-
const entrypoint =
|
|
2118
|
+
const entrypoint = join5(memoryDir, ENTRYPOINT_NAME);
|
|
1996
2119
|
let entrypointContent = "";
|
|
1997
2120
|
try {
|
|
1998
2121
|
entrypointContent = readFileSync3(entrypoint, { encoding: "utf-8" });
|
|
@@ -2044,13 +2167,13 @@ __export(prompt_exports, {
|
|
|
2044
2167
|
buildSystemPrompt: () => buildSystemPrompt,
|
|
2045
2168
|
buildVolatileRuntimeContext: () => buildVolatileRuntimeContext
|
|
2046
2169
|
});
|
|
2047
|
-
import * as
|
|
2048
|
-
import * as
|
|
2170
|
+
import * as path5 from "node:path";
|
|
2171
|
+
import * as fs5 from "node:fs";
|
|
2049
2172
|
import * as os2 from "node:os";
|
|
2050
2173
|
function readFileIfExists(filePath) {
|
|
2051
2174
|
try {
|
|
2052
|
-
if (
|
|
2053
|
-
return
|
|
2175
|
+
if (fs5.existsSync(filePath)) {
|
|
2176
|
+
return fs5.readFileSync(filePath, "utf-8");
|
|
2054
2177
|
}
|
|
2055
2178
|
} catch {
|
|
2056
2179
|
}
|
|
@@ -2205,8 +2328,8 @@ function getEnvInfoSection(workspace) {
|
|
|
2205
2328
|
function loadStaticFiles(workspace, staticFiles) {
|
|
2206
2329
|
if (!staticFiles || staticFiles.length === 0) return null;
|
|
2207
2330
|
const parts = [];
|
|
2208
|
-
for (const
|
|
2209
|
-
const filePath =
|
|
2331
|
+
for (const file2 of staticFiles) {
|
|
2332
|
+
const filePath = path5.isAbsolute(file2) ? file2 : path5.join(workspace, file2);
|
|
2210
2333
|
const content = readFileIfExists(filePath);
|
|
2211
2334
|
if (content) parts.push(content);
|
|
2212
2335
|
}
|
|
@@ -2225,7 +2348,7 @@ function loadMemoryInstructions(workspace) {
|
|
|
2225
2348
|
}
|
|
2226
2349
|
}
|
|
2227
2350
|
function resolveBlockContent(block, ctx) {
|
|
2228
|
-
const overridePath =
|
|
2351
|
+
const overridePath = path5.join(ctx.workspace, "prompts", `${block.name}.md`);
|
|
2229
2352
|
const override = readFileIfExists(overridePath);
|
|
2230
2353
|
if (override) return override;
|
|
2231
2354
|
return block.generate(ctx);
|
|
@@ -2274,7 +2397,7 @@ function buildCustomPrompt(workspace, config) {
|
|
|
2274
2397
|
continue;
|
|
2275
2398
|
}
|
|
2276
2399
|
if (name.endsWith(".md")) {
|
|
2277
|
-
const filePath =
|
|
2400
|
+
const filePath = path5.isAbsolute(name) ? name : path5.join(workspace, name);
|
|
2278
2401
|
const content = readFileIfExists(filePath);
|
|
2279
2402
|
if (content) {
|
|
2280
2403
|
parts.push(content);
|
|
@@ -2316,6 +2439,18 @@ ${skillsListing}`);
|
|
|
2316
2439
|
loaded2.push("session-guidance");
|
|
2317
2440
|
}
|
|
2318
2441
|
parts.push(getEnvInfoSection(options.workspace));
|
|
2442
|
+
const activeGoals = listGoals(options.workspace).filter((g) => g.status === "active" || g.status === "waiting" || g.status === "blocked");
|
|
2443
|
+
if (activeGoals.length > 0) {
|
|
2444
|
+
const summary = activeGoals.map((g) => {
|
|
2445
|
+
const step = g.steps[g.currentStep];
|
|
2446
|
+
return `- ${g.id} [${g.status}] ${g.objective}${step ? ` | current: ${step.title}` : ""}${g.blocker ? ` | blocker: ${g.blocker}` : ""}`;
|
|
2447
|
+
}).join("\n");
|
|
2448
|
+
parts.push(`# Active Goals
|
|
2449
|
+
${summary}
|
|
2450
|
+
|
|
2451
|
+
Continue active goals across turns. Do not claim a goal is complete without updating its state.`);
|
|
2452
|
+
loaded2.push("active-goals");
|
|
2453
|
+
}
|
|
2319
2454
|
console.log(`[dynamic-prompt] Loaded: ${loaded2.length > 0 ? loaded2.join(", ") : "(none)"}`);
|
|
2320
2455
|
return parts.join("\n\n");
|
|
2321
2456
|
}
|
|
@@ -2341,6 +2476,7 @@ var init_prompt = __esm({
|
|
|
2341
2476
|
"src/prompt.ts"() {
|
|
2342
2477
|
"use strict";
|
|
2343
2478
|
init_registry();
|
|
2479
|
+
init_store();
|
|
2344
2480
|
init_memdir();
|
|
2345
2481
|
init_paths();
|
|
2346
2482
|
BASH_TOOL_NAME = "exec";
|
|
@@ -2366,7 +2502,7 @@ var init_prompt = __esm({
|
|
|
2366
2502
|
{ name: "tone-style", description: "\u8BED\u6C14\u98CE\u683C\uFF08\u7B80\u6D01\u3001\u4E0D\u7528emoji\uFF09", generate: (_) => getToneAndStyleSection() },
|
|
2367
2503
|
{ name: "output-efficiency", description: "\u8F93\u51FA\u6548\u7387\uFF08\u76F4\u5954\u4E3B\u9898\uFF09", generate: (_) => getOutputEfficiencySection() },
|
|
2368
2504
|
// OpenClaw 叠加层
|
|
2369
|
-
{ name: "soul", description: "SOUL.md \u4EBA\u683C\u8EAB\u4EFD", generate: (ctx) => readFileIfExists(
|
|
2505
|
+
{ name: "soul", description: "SOUL.md \u4EBA\u683C\u8EAB\u4EFD", generate: (ctx) => readFileIfExists(path5.join(ctx.workspace, "SOUL.md")) },
|
|
2370
2506
|
{ 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) },
|
|
2371
2507
|
{ name: "auto-memory-instructions", description: "auto memory \u5B8C\u6574\u6307\u4EE4\uFF08\u5B58+\u8BFB+recall\u8BF4\u660E\uFF09", generate: (ctx) => loadMemoryInstructions(ctx.workspace) },
|
|
2372
2508
|
// Boundary(永远在最后)
|
|
@@ -4150,7 +4286,10 @@ async function executePreToolUseHooks(toolName, toolInput, ctx, signal) {
|
|
|
4150
4286
|
transcript_path: "",
|
|
4151
4287
|
cwd: ctx.cwd,
|
|
4152
4288
|
tool_name: toolName,
|
|
4153
|
-
tool_input: toolInput
|
|
4289
|
+
tool_input: toolInput,
|
|
4290
|
+
channel: ctx.channel,
|
|
4291
|
+
// 让 callback hook 能判断来源(0905 skill-gate:channel allowlist 依赖此字段)
|
|
4292
|
+
source: ctx.source || ""
|
|
4154
4293
|
};
|
|
4155
4294
|
return executeHooks("PreToolUse", hookInput, ctx, signal, toolName);
|
|
4156
4295
|
}
|
|
@@ -4217,7 +4356,9 @@ async function executeUserPromptSubmitHooks(prompt, ctx, signal) {
|
|
|
4217
4356
|
prompt,
|
|
4218
4357
|
sender_id: ctx.senderId || "",
|
|
4219
4358
|
channel_type: ctx.channelType || "",
|
|
4220
|
-
source: ctx.source || ""
|
|
4359
|
+
source: ctx.source || "",
|
|
4360
|
+
channel: ctx.channel
|
|
4361
|
+
// 让 callback hook 能判断来源(0905 skill-gate prompt 注入依赖)
|
|
4221
4362
|
};
|
|
4222
4363
|
return executeHooks("UserPromptSubmit", hookInput, ctx, signal);
|
|
4223
4364
|
}
|
|
@@ -4664,8 +4805,8 @@ var init_attachments = __esm({
|
|
|
4664
4805
|
});
|
|
4665
4806
|
|
|
4666
4807
|
// src/utils/context-dump.ts
|
|
4667
|
-
import * as
|
|
4668
|
-
import * as
|
|
4808
|
+
import * as fs6 from "node:fs";
|
|
4809
|
+
import * as path6 from "node:path";
|
|
4669
4810
|
function dumpApiRequest(opts) {
|
|
4670
4811
|
const lines = [
|
|
4671
4812
|
"=== API Request Debug\uFF08\u53D1\u7ED9 LLM \u7684\u6700\u7EC8\u8BF7\u6C42\u4F53\uFF0C\u6BCF\u6B21\u8986\u76D6\u5199\uFF09===",
|
|
@@ -4698,7 +4839,7 @@ function dumpApiRequest(opts) {
|
|
|
4698
4839
|
lines.push(`[${i}] ${m.role}: (empty)`);
|
|
4699
4840
|
}
|
|
4700
4841
|
}
|
|
4701
|
-
|
|
4842
|
+
fs6.writeFileSync(path6.join(opts.workspace, ".context-debug.txt"), lines.join("\n") + "\n", "utf-8");
|
|
4702
4843
|
}
|
|
4703
4844
|
var init_context_dump = __esm({
|
|
4704
4845
|
"src/utils/context-dump.ts"() {
|
|
@@ -5668,6 +5809,23 @@ var init_compact2 = __esm({
|
|
|
5668
5809
|
}
|
|
5669
5810
|
});
|
|
5670
5811
|
|
|
5812
|
+
// src/skills/skill-gate.ts
|
|
5813
|
+
function beginSkillGate(sessionId) {
|
|
5814
|
+
if (loadedBySession.size >= MAX_TRACKED_SESSIONS && !loadedBySession.has(sessionId)) {
|
|
5815
|
+
const oldest = loadedBySession.keys().next().value;
|
|
5816
|
+
if (oldest !== void 0) loadedBySession.delete(oldest);
|
|
5817
|
+
}
|
|
5818
|
+
loadedBySession.set(sessionId, /* @__PURE__ */ new Set());
|
|
5819
|
+
}
|
|
5820
|
+
var loadedBySession, MAX_TRACKED_SESSIONS;
|
|
5821
|
+
var init_skill_gate = __esm({
|
|
5822
|
+
"src/skills/skill-gate.ts"() {
|
|
5823
|
+
"use strict";
|
|
5824
|
+
loadedBySession = /* @__PURE__ */ new Map();
|
|
5825
|
+
MAX_TRACKED_SESSIONS = 100;
|
|
5826
|
+
}
|
|
5827
|
+
});
|
|
5828
|
+
|
|
5671
5829
|
// src/utils/context-analyzer.ts
|
|
5672
5830
|
var context_analyzer_exports = {};
|
|
5673
5831
|
__export(context_analyzer_exports, {
|
|
@@ -5676,8 +5834,8 @@ __export(context_analyzer_exports, {
|
|
|
5676
5834
|
formatContextReport: () => formatContextReport,
|
|
5677
5835
|
scanMemoryFiles: () => scanMemoryFiles
|
|
5678
5836
|
});
|
|
5679
|
-
import * as
|
|
5680
|
-
import * as
|
|
5837
|
+
import * as fs7 from "node:fs";
|
|
5838
|
+
import * as path7 from "node:path";
|
|
5681
5839
|
function estimateMessageTokens2(m) {
|
|
5682
5840
|
let tokens = 0;
|
|
5683
5841
|
if (typeof m.content === "string") {
|
|
@@ -5787,9 +5945,9 @@ function breakdownMessages(messages) {
|
|
|
5787
5945
|
}
|
|
5788
5946
|
async function scanMemoryFiles(workspace) {
|
|
5789
5947
|
const files = [];
|
|
5790
|
-
const soul = readFileIfExists2(
|
|
5948
|
+
const soul = readFileIfExists2(path7.join(workspace, "SOUL.md"));
|
|
5791
5949
|
if (soul) files.push({ path: "SOUL.md", tokens: roughTokenCountEstimation(soul), stable: true });
|
|
5792
|
-
const agents = readFileIfExists2(
|
|
5950
|
+
const agents = readFileIfExists2(path7.join(workspace, "AGENTS.md"));
|
|
5793
5951
|
if (agents) files.push({ path: "AGENTS.md", tokens: roughTokenCountEstimation(agents), stable: true });
|
|
5794
5952
|
try {
|
|
5795
5953
|
const { buildMemoryPrompt: buildMemoryPrompt2 } = await Promise.resolve().then(() => (init_memdir(), memdir_exports));
|
|
@@ -5805,7 +5963,7 @@ async function scanMemoryFiles(workspace) {
|
|
|
5805
5963
|
}
|
|
5806
5964
|
function readFileIfExists2(filePath) {
|
|
5807
5965
|
try {
|
|
5808
|
-
if (
|
|
5966
|
+
if (fs7.existsSync(filePath)) return fs7.readFileSync(filePath, "utf-8");
|
|
5809
5967
|
} catch {
|
|
5810
5968
|
}
|
|
5811
5969
|
return null;
|
|
@@ -5932,8 +6090,8 @@ function formatContextReport(report) {
|
|
|
5932
6090
|
`;
|
|
5933
6091
|
output += `|------|--------|
|
|
5934
6092
|
`;
|
|
5935
|
-
for (const
|
|
5936
|
-
output += `| ${
|
|
6093
|
+
for (const file2 of stableFiles) {
|
|
6094
|
+
output += `| ${file2.path} | ${formatTokens(file2.tokens)} |
|
|
5937
6095
|
`;
|
|
5938
6096
|
}
|
|
5939
6097
|
output += "\n";
|
|
@@ -5947,8 +6105,8 @@ function formatContextReport(report) {
|
|
|
5947
6105
|
`;
|
|
5948
6106
|
output += `|------|--------|
|
|
5949
6107
|
`;
|
|
5950
|
-
for (const
|
|
5951
|
-
output += `| ${
|
|
6108
|
+
for (const file2 of dynamicFiles) {
|
|
6109
|
+
output += `| ${file2.path} | ${formatTokens(file2.tokens)} |
|
|
5952
6110
|
`;
|
|
5953
6111
|
}
|
|
5954
6112
|
output += "\n";
|
|
@@ -6014,6 +6172,7 @@ var init_query = __esm({
|
|
|
6014
6172
|
init_deferred();
|
|
6015
6173
|
init_hooks();
|
|
6016
6174
|
init_live();
|
|
6175
|
+
init_skill_gate();
|
|
6017
6176
|
QueryEngine = class _QueryEngine {
|
|
6018
6177
|
constructor(provider, options) {
|
|
6019
6178
|
this.provider = provider;
|
|
@@ -6140,6 +6299,7 @@ var init_query = __esm({
|
|
|
6140
6299
|
let ac = new AbortController();
|
|
6141
6300
|
this.abortController = ac;
|
|
6142
6301
|
this.preQueryAbort = null;
|
|
6302
|
+
beginSkillGate(context?.sessionId || "default");
|
|
6143
6303
|
if (signal) {
|
|
6144
6304
|
signal.addEventListener("abort", () => ac.abort(), { once: true });
|
|
6145
6305
|
}
|
|
@@ -6456,6 +6616,7 @@ ${perTurnSystemDynamic}` : deferredHint || perTurnSystemDynamic;
|
|
|
6456
6616
|
channel: context?.channel || "",
|
|
6457
6617
|
cwd: context?.workspace || ""
|
|
6458
6618
|
};
|
|
6619
|
+
const gatedCalls = [];
|
|
6459
6620
|
for (const tc of toolCalls) {
|
|
6460
6621
|
const toolName = tc.function?.name || tc.name || "unknown";
|
|
6461
6622
|
let toolInput = {};
|
|
@@ -6470,11 +6631,35 @@ ${perTurnSystemDynamic}` : deferredHint || perTurnSystemDynamic;
|
|
|
6470
6631
|
}
|
|
6471
6632
|
if (preResult.preventContinuation) {
|
|
6472
6633
|
console.log(`[hook] PreToolUse ${toolName}: blocked - ${preResult.stopReason || "no reason"}`);
|
|
6634
|
+
gatedCalls.push({
|
|
6635
|
+
call: tc,
|
|
6636
|
+
text: preResult.additionalContexts?.join("\n") || preResult.stopReason || `Tool ${toolName} was blocked by a hook.`
|
|
6637
|
+
});
|
|
6473
6638
|
}
|
|
6474
6639
|
} catch (e) {
|
|
6475
6640
|
console.warn(`[hook] PreToolUse ${toolName} error: ${e.message}`);
|
|
6476
6641
|
}
|
|
6477
6642
|
}
|
|
6643
|
+
if (gatedCalls.length > 0) {
|
|
6644
|
+
const gatedTexts = new Map(gatedCalls.map((g) => [g.call.id, g.text]));
|
|
6645
|
+
const blockResults = toolCalls.map(
|
|
6646
|
+
(tc) => msg.tool(tc.id, gatedTexts.get(tc.id) || "\u672C\u8F6E\u6709\u5176\u4ED6\u8C03\u7528\u88AB\u95E8\u7981\u62E6\u4E0B\uFF0C\u6574\u6279\u672A\u6267\u884C\uFF1B\u8BF7\u5148\u6309\u63D0\u793A\u52A0\u8F7D Skill \u518D\u91CD\u8BD5\u3002", true)
|
|
6647
|
+
);
|
|
6648
|
+
const gateAssistant = msg.assistant(textContent, toolCalls);
|
|
6649
|
+
if (turnThinking) {
|
|
6650
|
+
gateAssistant.reasoning_content = turnThinking;
|
|
6651
|
+
if (turnThinkingSig) gateAssistant.thinking_signature = turnThinkingSig;
|
|
6652
|
+
}
|
|
6653
|
+
turnThinking = "";
|
|
6654
|
+
turnThinkingSig = "";
|
|
6655
|
+
currentMessages.push(gateAssistant);
|
|
6656
|
+
currentMessages.push(...blockResults);
|
|
6657
|
+
for (const g of gatedCalls) {
|
|
6658
|
+
yield { type: "tool_result", tool: g.call.function?.name, tool_call_id: g.call.id, summary: g.text.slice(0, 200), isError: true };
|
|
6659
|
+
}
|
|
6660
|
+
yield { type: "history", messages: [msg.assistant(textContent, toolCalls), ...blockResults] };
|
|
6661
|
+
continue;
|
|
6662
|
+
}
|
|
6478
6663
|
const vcPlaceholderOn = context?.channel === "voice-chat" && (liveConfig.get("voiceChat.placeholder.enabled") ?? true);
|
|
6479
6664
|
const vcTimer = vcPlaceholderOn ? setTimeout(() => {
|
|
6480
6665
|
_QueryEngine.tryVoicePlaceholder(context).catch(() => {
|
|
@@ -6634,8 +6819,8 @@ ${perTurnSystemDynamic}` : deferredHint || perTurnSystemDynamic;
|
|
|
6634
6819
|
});
|
|
6635
6820
|
|
|
6636
6821
|
// src/session/writer.ts
|
|
6637
|
-
import * as
|
|
6638
|
-
import * as
|
|
6822
|
+
import * as fs8 from "node:fs";
|
|
6823
|
+
import * as path8 from "node:path";
|
|
6639
6824
|
import * as crypto2 from "node:crypto";
|
|
6640
6825
|
var SessionWriter;
|
|
6641
6826
|
var init_writer = __esm({
|
|
@@ -6658,7 +6843,7 @@ var init_writer = __esm({
|
|
|
6658
6843
|
this.sessionId = sessionId || crypto2.randomUUID();
|
|
6659
6844
|
this.engineSessionId = "";
|
|
6660
6845
|
const filename = `${this.sessionId}.jsonl`;
|
|
6661
|
-
this.filePath =
|
|
6846
|
+
this.filePath = path8.join(sessionsDir, filename);
|
|
6662
6847
|
}
|
|
6663
6848
|
get id() {
|
|
6664
6849
|
return this.sessionId;
|
|
@@ -6669,9 +6854,9 @@ var init_writer = __esm({
|
|
|
6669
6854
|
/** 打开文件写入 header(新文件才写 header) */
|
|
6670
6855
|
open(cwd, engineSessionId) {
|
|
6671
6856
|
this.engineSessionId = engineSessionId || "";
|
|
6672
|
-
|
|
6673
|
-
const fileExists =
|
|
6674
|
-
this.stream =
|
|
6857
|
+
fs8.mkdirSync(path8.dirname(this.filePath), { recursive: true });
|
|
6858
|
+
const fileExists = fs8.existsSync(this.filePath) && fs8.statSync(this.filePath).size > 0;
|
|
6859
|
+
this.stream = fs8.createWriteStream(this.filePath, { flags: "a" });
|
|
6675
6860
|
this.stream.on("error", (err) => {
|
|
6676
6861
|
console.error(`[SessionWriter] write error on ${this.filePath}:`, err.message);
|
|
6677
6862
|
});
|
|
@@ -6871,17 +7056,17 @@ var init_writer = __esm({
|
|
|
6871
7056
|
this.stream.end();
|
|
6872
7057
|
this.stream = null;
|
|
6873
7058
|
}
|
|
6874
|
-
if (!
|
|
6875
|
-
const fileSize =
|
|
7059
|
+
if (!fs8.existsSync(this.filePath)) return null;
|
|
7060
|
+
const fileSize = fs8.statSync(this.filePath).size;
|
|
6876
7061
|
if (fileSize === 0) return null;
|
|
6877
7062
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-");
|
|
6878
7063
|
const archivedPath = `${this.filePath}.${reason}.${ts}`;
|
|
6879
|
-
|
|
7064
|
+
fs8.renameSync(this.filePath, archivedPath);
|
|
6880
7065
|
const sizeMB = (fileSize / 1024 / 1024).toFixed(1);
|
|
6881
|
-
console.log(`[SessionWriter] Archived JSONL: ${
|
|
7066
|
+
console.log(`[SessionWriter] Archived JSONL: ${path8.basename(this.filePath)} \u2192 ${path8.basename(archivedPath)} (${sizeMB}MB)`);
|
|
6882
7067
|
const postBoundaryData = this.readPostBoundaryFromArchived(archivedPath);
|
|
6883
|
-
const dir =
|
|
6884
|
-
|
|
7068
|
+
const dir = path8.dirname(this.filePath);
|
|
7069
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
6885
7070
|
const header = {
|
|
6886
7071
|
type: "session",
|
|
6887
7072
|
version: 3,
|
|
@@ -6895,8 +7080,8 @@ var init_writer = __esm({
|
|
|
6895
7080
|
if (postBoundaryData.length > 0) {
|
|
6896
7081
|
initialData += postBoundaryData.toString("utf-8");
|
|
6897
7082
|
}
|
|
6898
|
-
|
|
6899
|
-
this.stream =
|
|
7083
|
+
fs8.writeFileSync(this.filePath, initialData, "utf-8");
|
|
7084
|
+
this.stream = fs8.createWriteStream(this.filePath, { flags: "a" });
|
|
6900
7085
|
this.stream.on("error", (err) => {
|
|
6901
7086
|
console.error(`[SessionWriter] write error on ${this.filePath}:`, err.message);
|
|
6902
7087
|
});
|
|
@@ -6906,10 +7091,10 @@ var init_writer = __esm({
|
|
|
6906
7091
|
* 从归档文件中读取最后一个 compact_boundary 之后的内容
|
|
6907
7092
|
*/
|
|
6908
7093
|
readPostBoundaryFromArchived(archivedPath) {
|
|
6909
|
-
const fileSize =
|
|
7094
|
+
const fileSize = fs8.statSync(archivedPath).size;
|
|
6910
7095
|
if (fileSize === 0) return Buffer.alloc(0);
|
|
6911
7096
|
if (fileSize <= 5 * 1024 * 1024) {
|
|
6912
|
-
const content =
|
|
7097
|
+
const content = fs8.readFileSync(archivedPath, "utf-8");
|
|
6913
7098
|
const lines = content.split("\n");
|
|
6914
7099
|
let lastBoundaryIdx = -1;
|
|
6915
7100
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -6926,11 +7111,11 @@ var init_writer = __esm({
|
|
|
6926
7111
|
{
|
|
6927
7112
|
const probeSize = Math.min(fileSize, 1024 * 1024);
|
|
6928
7113
|
const probeBuf = Buffer.allocUnsafe(probeSize);
|
|
6929
|
-
const probeFd =
|
|
7114
|
+
const probeFd = fs8.openSync(archivedPath, "r");
|
|
6930
7115
|
let hasBoundary = false;
|
|
6931
7116
|
let probed = 0;
|
|
6932
7117
|
while (probed < fileSize) {
|
|
6933
|
-
const n =
|
|
7118
|
+
const n = fs8.readSync(probeFd, probeBuf, 0, Math.min(probeSize, fileSize - probed), probed);
|
|
6934
7119
|
if (n === 0) break;
|
|
6935
7120
|
if (probeBuf.subarray(0, n).includes(Buffer.from(boundaryMarker))) {
|
|
6936
7121
|
hasBoundary = true;
|
|
@@ -6938,19 +7123,19 @@ var init_writer = __esm({
|
|
|
6938
7123
|
}
|
|
6939
7124
|
probed += n;
|
|
6940
7125
|
}
|
|
6941
|
-
|
|
7126
|
+
fs8.closeSync(probeFd);
|
|
6942
7127
|
if (!hasBoundary) return Buffer.alloc(0);
|
|
6943
7128
|
}
|
|
6944
7129
|
const outBuf = Buffer.allocUnsafe(Math.min(fileSize, 8 * 1024 * 1024));
|
|
6945
7130
|
let outLen = 0;
|
|
6946
7131
|
const chunk = Buffer.allocUnsafe(CHUNK_SIZE);
|
|
6947
|
-
const fd =
|
|
7132
|
+
const fd = fs8.openSync(archivedPath, "r");
|
|
6948
7133
|
try {
|
|
6949
7134
|
let filePos = 0;
|
|
6950
7135
|
let carryBuf;
|
|
6951
7136
|
let carryLen = 0;
|
|
6952
7137
|
while (filePos < fileSize) {
|
|
6953
|
-
const bytesRead =
|
|
7138
|
+
const bytesRead = fs8.readSync(fd, chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
|
|
6954
7139
|
if (bytesRead === 0) break;
|
|
6955
7140
|
filePos += bytesRead;
|
|
6956
7141
|
let scanBuf;
|
|
@@ -6999,7 +7184,7 @@ var init_writer = __esm({
|
|
|
6999
7184
|
}
|
|
7000
7185
|
}
|
|
7001
7186
|
} finally {
|
|
7002
|
-
|
|
7187
|
+
fs8.closeSync(fd);
|
|
7003
7188
|
}
|
|
7004
7189
|
return outBuf.subarray(0, outLen);
|
|
7005
7190
|
}
|
|
@@ -7011,15 +7196,15 @@ var init_writer = __esm({
|
|
|
7011
7196
|
*/
|
|
7012
7197
|
readLastId() {
|
|
7013
7198
|
try {
|
|
7014
|
-
const stat4 =
|
|
7199
|
+
const stat4 = fs8.statSync(this.filePath);
|
|
7015
7200
|
if (stat4.size === 0) return null;
|
|
7016
7201
|
const readSize = Math.min(stat4.size, 4096);
|
|
7017
7202
|
const buf = Buffer.alloc(readSize);
|
|
7018
|
-
const fd =
|
|
7203
|
+
const fd = fs8.openSync(this.filePath, "r");
|
|
7019
7204
|
try {
|
|
7020
|
-
|
|
7205
|
+
fs8.readSync(fd, buf, 0, readSize, stat4.size - readSize);
|
|
7021
7206
|
} finally {
|
|
7022
|
-
|
|
7207
|
+
fs8.closeSync(fd);
|
|
7023
7208
|
}
|
|
7024
7209
|
const text = buf.toString("utf-8");
|
|
7025
7210
|
const lines = text.split("\n").filter((l) => l.trim().length > 0);
|
|
@@ -7066,11 +7251,11 @@ var init_writer = __esm({
|
|
|
7066
7251
|
});
|
|
7067
7252
|
|
|
7068
7253
|
// src/session/reader.ts
|
|
7069
|
-
import * as
|
|
7070
|
-
import * as
|
|
7254
|
+
import * as fs9 from "node:fs";
|
|
7255
|
+
import * as path9 from "node:path";
|
|
7071
7256
|
import * as readline from "node:readline";
|
|
7072
7257
|
async function readSessionHeader(filePath) {
|
|
7073
|
-
const stream =
|
|
7258
|
+
const stream = fs9.createReadStream(filePath, { encoding: "utf-8" });
|
|
7074
7259
|
const rl = readline.createInterface({ input: stream });
|
|
7075
7260
|
return new Promise((resolve11) => {
|
|
7076
7261
|
let resolved = false;
|
|
@@ -7101,7 +7286,7 @@ async function readSessionHeader(filePath) {
|
|
|
7101
7286
|
});
|
|
7102
7287
|
}
|
|
7103
7288
|
async function readLargeFilePostBoundary(filePath) {
|
|
7104
|
-
const stat4 =
|
|
7289
|
+
const stat4 = fs9.statSync(filePath);
|
|
7105
7290
|
const fileSize = stat4.size;
|
|
7106
7291
|
const boundaryMarker = '"compact_boundary"';
|
|
7107
7292
|
const CHUNK_SIZE = TRANSCRIPT_READ_CHUNK_SIZE;
|
|
@@ -7109,13 +7294,13 @@ async function readLargeFilePostBoundary(filePath) {
|
|
|
7109
7294
|
let outLen = 0;
|
|
7110
7295
|
let boundaryStartOffset = 0;
|
|
7111
7296
|
const chunk = Buffer.allocUnsafe(CHUNK_SIZE);
|
|
7112
|
-
const fd =
|
|
7297
|
+
const fd = fs9.openSync(filePath, "r");
|
|
7113
7298
|
try {
|
|
7114
7299
|
let filePos = 0;
|
|
7115
7300
|
let carryBuf;
|
|
7116
7301
|
let carryLen = 0;
|
|
7117
7302
|
while (filePos < fileSize) {
|
|
7118
|
-
const bytesRead =
|
|
7303
|
+
const bytesRead = fs9.readSync(fd, chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
|
|
7119
7304
|
if (bytesRead === 0) break;
|
|
7120
7305
|
filePos += bytesRead;
|
|
7121
7306
|
let scanBuf;
|
|
@@ -7167,7 +7352,7 @@ async function readLargeFilePostBoundary(filePath) {
|
|
|
7167
7352
|
}
|
|
7168
7353
|
}
|
|
7169
7354
|
} finally {
|
|
7170
|
-
|
|
7355
|
+
fs9.closeSync(fd);
|
|
7171
7356
|
}
|
|
7172
7357
|
const postBoundaryText = outBuf.subarray(0, outLen).toString("utf-8");
|
|
7173
7358
|
return postBoundaryText.split("\n").filter((l) => l.trim().length > 0);
|
|
@@ -7291,7 +7476,7 @@ function recoverOrphanedParallelToolResults(allEntries, chain, byUuid, seen) {
|
|
|
7291
7476
|
return result2;
|
|
7292
7477
|
}
|
|
7293
7478
|
async function readSessionHistory(filePath) {
|
|
7294
|
-
const stat4 =
|
|
7479
|
+
const stat4 = fs9.statSync(filePath);
|
|
7295
7480
|
const fileSize = stat4.size;
|
|
7296
7481
|
if (fileSize > MAX_TRANSCRIPT_READ_BYTES) {
|
|
7297
7482
|
console.warn(`[reader] Session file exceeds 50MB limit (${(fileSize / 1024 / 1024).toFixed(1)}MB), using chunked fd read with boundary skip`);
|
|
@@ -7330,7 +7515,7 @@ async function readSessionHistory(filePath) {
|
|
|
7330
7515
|
return [...sessionStarts, ...filtered, ...restAttachments];
|
|
7331
7516
|
}
|
|
7332
7517
|
async function readAllLines(filePath) {
|
|
7333
|
-
const stream =
|
|
7518
|
+
const stream = fs9.createReadStream(filePath, { encoding: "utf-8" });
|
|
7334
7519
|
const rl = readline.createInterface({ input: stream });
|
|
7335
7520
|
const lines = [];
|
|
7336
7521
|
return new Promise((resolve11, reject) => {
|
|
@@ -7480,12 +7665,12 @@ function extractText2(content) {
|
|
|
7480
7665
|
return content.filter((b) => b.type === "text").map((b) => b.text || "").join("") || null;
|
|
7481
7666
|
}
|
|
7482
7667
|
function listSessions(sessionsDir) {
|
|
7483
|
-
if (!
|
|
7484
|
-
const files =
|
|
7485
|
-
file:
|
|
7668
|
+
if (!fs9.existsSync(sessionsDir)) return [];
|
|
7669
|
+
const files = fs9.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") || f.includes(".jsonl.")).map((f) => ({
|
|
7670
|
+
file: path9.join(sessionsDir, f),
|
|
7486
7671
|
id: f.replace(/\.jsonl.*$/, ""),
|
|
7487
7672
|
// strip .jsonl and everything after (archived suffix)
|
|
7488
|
-
modified: new Date(
|
|
7673
|
+
modified: new Date(fs9.statSync(path9.join(sessionsDir, f)).mtimeMs)
|
|
7489
7674
|
})).sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
7490
7675
|
return files;
|
|
7491
7676
|
}
|
|
@@ -7505,8 +7690,8 @@ var session_manager_exports = {};
|
|
|
7505
7690
|
__export(session_manager_exports, {
|
|
7506
7691
|
SessionManager: () => SessionManager
|
|
7507
7692
|
});
|
|
7508
|
-
import * as
|
|
7509
|
-
import * as
|
|
7693
|
+
import * as path10 from "node:path";
|
|
7694
|
+
import * as fs10 from "node:fs";
|
|
7510
7695
|
import * as crypto3 from "node:crypto";
|
|
7511
7696
|
var RESTORE_MAX_CHARS, CHARS_PER_TOKEN, SessionManager;
|
|
7512
7697
|
var init_session_manager = __esm({
|
|
@@ -7538,24 +7723,24 @@ var init_session_manager = __esm({
|
|
|
7538
7723
|
constructor(config) {
|
|
7539
7724
|
this.config = config;
|
|
7540
7725
|
this.scopeConfig = config.scopeConfig;
|
|
7541
|
-
this.sessionsDir =
|
|
7542
|
-
this.indexPath =
|
|
7543
|
-
this.platformMapPath =
|
|
7544
|
-
|
|
7726
|
+
this.sessionsDir = path10.join(config.stateDir, "agents", "main", "sessions");
|
|
7727
|
+
this.indexPath = path10.join(this.sessionsDir, "session-index.json");
|
|
7728
|
+
this.platformMapPath = path10.join(this.sessionsDir, "platform-map.json");
|
|
7729
|
+
fs10.mkdirSync(this.sessionsDir, { recursive: true });
|
|
7545
7730
|
}
|
|
7546
7731
|
// === 索引操作 ===
|
|
7547
7732
|
loadIndex() {
|
|
7548
7733
|
try {
|
|
7549
|
-
if (
|
|
7550
|
-
const raw =
|
|
7734
|
+
if (fs10.existsSync(this.indexPath)) {
|
|
7735
|
+
const raw = fs10.readFileSync(this.indexPath, "utf-8");
|
|
7551
7736
|
const obj = JSON.parse(raw);
|
|
7552
7737
|
this.index = new Map(Object.entries(obj));
|
|
7553
7738
|
let fixed = 0;
|
|
7554
7739
|
for (const [key, entry] of this.index) {
|
|
7555
|
-
if (
|
|
7556
|
-
const basename8 =
|
|
7557
|
-
const localPath =
|
|
7558
|
-
if (
|
|
7740
|
+
if (fs10.existsSync(entry.file)) continue;
|
|
7741
|
+
const basename8 = path10.basename(entry.file);
|
|
7742
|
+
const localPath = path10.join(this.sessionsDir, basename8);
|
|
7743
|
+
if (fs10.existsSync(localPath)) {
|
|
7559
7744
|
entry.file = localPath;
|
|
7560
7745
|
fixed++;
|
|
7561
7746
|
}
|
|
@@ -7574,7 +7759,7 @@ var init_session_manager = __esm({
|
|
|
7574
7759
|
try {
|
|
7575
7760
|
const obj = {};
|
|
7576
7761
|
for (const [k, v] of this.index) obj[k] = v;
|
|
7577
|
-
|
|
7762
|
+
fs10.writeFileSync(this.indexPath, JSON.stringify(obj, null, 2));
|
|
7578
7763
|
} catch (err) {
|
|
7579
7764
|
console.error(`[session] Failed to save index: ${err.message}`);
|
|
7580
7765
|
}
|
|
@@ -7582,8 +7767,8 @@ var init_session_manager = __esm({
|
|
|
7582
7767
|
// === 平台映射 ===
|
|
7583
7768
|
loadPlatformMap() {
|
|
7584
7769
|
try {
|
|
7585
|
-
if (
|
|
7586
|
-
const raw =
|
|
7770
|
+
if (fs10.existsSync(this.platformMapPath)) {
|
|
7771
|
+
const raw = fs10.readFileSync(this.platformMapPath, "utf-8");
|
|
7587
7772
|
const obj = JSON.parse(raw);
|
|
7588
7773
|
this.platformMap = new Map(Object.entries(obj));
|
|
7589
7774
|
console.log(`[session] Platform map loaded: ${this.platformMap.size} entries`);
|
|
@@ -7595,7 +7780,7 @@ var init_session_manager = __esm({
|
|
|
7595
7780
|
try {
|
|
7596
7781
|
const obj = {};
|
|
7597
7782
|
for (const [k, v] of this.platformMap) obj[k] = v;
|
|
7598
|
-
|
|
7783
|
+
fs10.writeFileSync(this.platformMapPath, JSON.stringify(obj, null, 2));
|
|
7599
7784
|
} catch (err) {
|
|
7600
7785
|
console.error(`[session] Failed to save platform map: ${err.message}`);
|
|
7601
7786
|
}
|
|
@@ -7634,17 +7819,17 @@ var init_session_manager = __esm({
|
|
|
7634
7819
|
*/
|
|
7635
7820
|
getSessionFilePath(sessionId) {
|
|
7636
7821
|
const entry = this.index.get(sessionId);
|
|
7637
|
-
if (entry &&
|
|
7638
|
-
const direct =
|
|
7639
|
-
return
|
|
7822
|
+
if (entry && fs10.existsSync(entry.file)) return entry.file;
|
|
7823
|
+
const direct = path10.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
7824
|
+
return fs10.existsSync(direct) ? direct : null;
|
|
7640
7825
|
}
|
|
7641
7826
|
// === Writer 管理 ===
|
|
7642
7827
|
getWriter(sessionId) {
|
|
7643
7828
|
let writer = this.writers.get(sessionId);
|
|
7644
7829
|
if (!writer) {
|
|
7645
7830
|
const existing = this.index.get(sessionId);
|
|
7646
|
-
if (existing &&
|
|
7647
|
-
const existingFileId =
|
|
7831
|
+
if (existing && fs10.existsSync(existing.file)) {
|
|
7832
|
+
const existingFileId = path10.basename(existing.file, ".jsonl");
|
|
7648
7833
|
writer = new SessionWriter(this.sessionsDir, existingFileId);
|
|
7649
7834
|
writer.open(this.config.workspace, sessionId);
|
|
7650
7835
|
} else {
|
|
@@ -7656,7 +7841,7 @@ var init_session_manager = __esm({
|
|
|
7656
7841
|
this.saveIndex();
|
|
7657
7842
|
this.writers.set(sessionId, writer);
|
|
7658
7843
|
this.onWriterCreated?.(writer, sessionId);
|
|
7659
|
-
console.log(`[session] ${existing ? "Resumed" : "New"}: ${sessionId} \u2192 ${
|
|
7844
|
+
console.log(`[session] ${existing ? "Resumed" : "New"}: ${sessionId} \u2192 ${path10.basename(writer.path)}`);
|
|
7660
7845
|
}
|
|
7661
7846
|
return writer;
|
|
7662
7847
|
}
|
|
@@ -7675,7 +7860,7 @@ var init_session_manager = __esm({
|
|
|
7675
7860
|
if (!writer) return null;
|
|
7676
7861
|
try {
|
|
7677
7862
|
this.lastArchiveCheck = Date.now();
|
|
7678
|
-
const stat4 =
|
|
7863
|
+
const stat4 = fs10.statSync(writer.path);
|
|
7679
7864
|
if (stat4.size < threshold) return null;
|
|
7680
7865
|
const sizeMB = (stat4.size / 1024 / 1024).toFixed(1);
|
|
7681
7866
|
const thresholdMB = (threshold / 1024 / 1024).toFixed(1);
|
|
@@ -7684,10 +7869,10 @@ var init_session_manager = __esm({
|
|
|
7684
7869
|
if (archivedPath) {
|
|
7685
7870
|
this.index.set(sessionId, { file: writer.path, updatedAt: Date.now() });
|
|
7686
7871
|
this.saveIndex();
|
|
7687
|
-
const newSize =
|
|
7872
|
+
const newSize = fs10.statSync(writer.path).size;
|
|
7688
7873
|
const oldSizeMB = (stat4.size / 1024 / 1024).toFixed(1);
|
|
7689
|
-
console.log(`[session] Archive complete: ${
|
|
7690
|
-
const fileId =
|
|
7874
|
+
console.log(`[session] Archive complete: ${path10.basename(archivedPath)} (${oldSizeMB}MB) \u2192 new JSONL created (${newSize} bytes)`);
|
|
7875
|
+
const fileId = path10.basename(writer.path).replace(/\.jsonl$/, "");
|
|
7691
7876
|
this.purgeOldArchives(fileId, 3);
|
|
7692
7877
|
return archivedPath;
|
|
7693
7878
|
}
|
|
@@ -7703,15 +7888,15 @@ var init_session_manager = __esm({
|
|
|
7703
7888
|
purgeOldArchives(sessionId, keepCount = 3) {
|
|
7704
7889
|
try {
|
|
7705
7890
|
const dir = this.sessionsDir;
|
|
7706
|
-
if (!
|
|
7707
|
-
const allFiles =
|
|
7891
|
+
if (!fs10.existsSync(dir)) return;
|
|
7892
|
+
const allFiles = fs10.readdirSync(dir);
|
|
7708
7893
|
const archiveFiles = allFiles.filter((f) => {
|
|
7709
7894
|
if (!f.startsWith(sessionId)) return false;
|
|
7710
7895
|
return f.includes(".archived.") || f.includes(".compaction.");
|
|
7711
7896
|
}).map((f) => ({
|
|
7712
7897
|
name: f,
|
|
7713
|
-
path:
|
|
7714
|
-
mtime:
|
|
7898
|
+
path: path10.join(dir, f),
|
|
7899
|
+
mtime: fs10.statSync(path10.join(dir, f)).mtimeMs
|
|
7715
7900
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
7716
7901
|
console.log(`[session] purgeOldArchives: sessionId=${sessionId.substring(0, 8)}... found=${archiveFiles.length} keep=${keepCount}`);
|
|
7717
7902
|
if (archiveFiles.length <= keepCount) return;
|
|
@@ -7721,7 +7906,7 @@ var init_session_manager = __esm({
|
|
|
7721
7906
|
console.log(`[session] Skipping archived (kept for history): ${f.name}`);
|
|
7722
7907
|
continue;
|
|
7723
7908
|
}
|
|
7724
|
-
|
|
7909
|
+
fs10.unlinkSync(f.path);
|
|
7725
7910
|
console.log(`[session] Purged old archive: ${f.name}`);
|
|
7726
7911
|
}
|
|
7727
7912
|
if (toDelete.length > 0) {
|
|
@@ -7770,29 +7955,29 @@ var init_session_manager = __esm({
|
|
|
7770
7955
|
/** 列出 session 的所有文件(当前 + 归档),按修改时间排序 */
|
|
7771
7956
|
findAllSessionFiles(sessionId) {
|
|
7772
7957
|
const results = [];
|
|
7773
|
-
const mainFile =
|
|
7774
|
-
if (
|
|
7958
|
+
const mainFile = path10.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
7959
|
+
if (fs10.existsSync(mainFile)) {
|
|
7775
7960
|
results.push(mainFile);
|
|
7776
7961
|
}
|
|
7777
|
-
if (
|
|
7778
|
-
const compactionFiles =
|
|
7962
|
+
if (fs10.existsSync(this.sessionsDir)) {
|
|
7963
|
+
const compactionFiles = fs10.readdirSync(this.sessionsDir).filter((f) => f.startsWith(`${sessionId}.jsonl.compaction.`)).map((f) => ({
|
|
7779
7964
|
name: f,
|
|
7780
|
-
path:
|
|
7781
|
-
mtime:
|
|
7965
|
+
path: path10.join(this.sessionsDir, f),
|
|
7966
|
+
mtime: fs10.statSync(path10.join(this.sessionsDir, f)).mtimeMs
|
|
7782
7967
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
7783
7968
|
if (compactionFiles.length > 0) {
|
|
7784
7969
|
results.push(compactionFiles[0].path);
|
|
7785
7970
|
}
|
|
7786
7971
|
}
|
|
7787
7972
|
results.sort((a, b) => {
|
|
7788
|
-
const ta =
|
|
7789
|
-
const tb =
|
|
7973
|
+
const ta = fs10.statSync(a).mtimeMs;
|
|
7974
|
+
const tb = fs10.statSync(b).mtimeMs;
|
|
7790
7975
|
return ta - tb;
|
|
7791
7976
|
});
|
|
7792
7977
|
return results;
|
|
7793
7978
|
}
|
|
7794
7979
|
async findSessionFiles(sessionId) {
|
|
7795
|
-
if (!
|
|
7980
|
+
if (!fs10.existsSync(this.sessionsDir)) {
|
|
7796
7981
|
console.log(`[session:find] SESSIONS_DIR not found: ${this.sessionsDir}`);
|
|
7797
7982
|
return [];
|
|
7798
7983
|
}
|
|
@@ -7804,15 +7989,15 @@ var init_session_manager = __esm({
|
|
|
7804
7989
|
return mappedFiles;
|
|
7805
7990
|
}
|
|
7806
7991
|
const indexedEntry = this.index.get(mappedId);
|
|
7807
|
-
if (indexedEntry &&
|
|
7808
|
-
const fileUuid =
|
|
7992
|
+
if (indexedEntry && fs10.existsSync(indexedEntry.file)) {
|
|
7993
|
+
const fileUuid = path10.basename(indexedEntry.file, ".jsonl");
|
|
7809
7994
|
return this.findAllSessionFiles(fileUuid);
|
|
7810
7995
|
}
|
|
7811
7996
|
}
|
|
7812
7997
|
const allFiles = this.findAllSessionFiles(sessionId);
|
|
7813
7998
|
if (allFiles.length > 0) {
|
|
7814
7999
|
const labels = allFiles.map((f) => {
|
|
7815
|
-
const base =
|
|
8000
|
+
const base = path10.basename(f);
|
|
7816
8001
|
return base.endsWith(".jsonl") ? base : `${base} (archived)`;
|
|
7817
8002
|
});
|
|
7818
8003
|
console.log(`[session:find] Found ${allFiles.length} file(s) for ${sessionId}: ${labels.join(", ")}`);
|
|
@@ -7820,9 +8005,9 @@ var init_session_manager = __esm({
|
|
|
7820
8005
|
}
|
|
7821
8006
|
const indexed = this.index.get(sessionId);
|
|
7822
8007
|
if (indexed) {
|
|
7823
|
-
console.log(`[session:find] Index hit: ${sessionId} \u2192 ${indexed.file} (exists=${
|
|
7824
|
-
if (
|
|
7825
|
-
return this.findAllSessionFiles(
|
|
8008
|
+
console.log(`[session:find] Index hit: ${sessionId} \u2192 ${indexed.file} (exists=${fs10.existsSync(indexed.file)})`);
|
|
8009
|
+
if (fs10.existsSync(indexed.file)) {
|
|
8010
|
+
return this.findAllSessionFiles(path10.basename(indexed.file, ".jsonl"));
|
|
7826
8011
|
}
|
|
7827
8012
|
} else {
|
|
7828
8013
|
console.log(`[session:find] Index miss: ${sessionId} (index has ${this.index.size} entries)`);
|
|
@@ -7851,8 +8036,8 @@ var init_session_manager = __esm({
|
|
|
7851
8036
|
return [];
|
|
7852
8037
|
}
|
|
7853
8038
|
files.sort((a, b) => {
|
|
7854
|
-
const ta =
|
|
7855
|
-
const tb =
|
|
8039
|
+
const ta = fs10.statSync(a).mtimeMs;
|
|
8040
|
+
const tb = fs10.statSync(b).mtimeMs;
|
|
7856
8041
|
return ta - tb;
|
|
7857
8042
|
});
|
|
7858
8043
|
const latestFile = files[files.length - 1];
|
|
@@ -7860,11 +8045,11 @@ var init_session_manager = __esm({
|
|
|
7860
8045
|
if (!currentEntry || currentEntry.file !== latestFile) {
|
|
7861
8046
|
this.index.set(sessionId, { file: latestFile, updatedAt: Date.now() });
|
|
7862
8047
|
this.saveIndex();
|
|
7863
|
-
console.log(`[session:restore] Synced index: ${sessionId} \u2192 ${
|
|
8048
|
+
console.log(`[session:restore] Synced index: ${sessionId} \u2192 ${path10.basename(latestFile)}`);
|
|
7864
8049
|
}
|
|
7865
8050
|
const allMessages = [];
|
|
7866
|
-
for (const
|
|
7867
|
-
const sessionMsgs = await readSessionHistory(
|
|
8051
|
+
for (const file2 of files) {
|
|
8052
|
+
const sessionMsgs = await readSessionHistory(file2);
|
|
7868
8053
|
for (const m of sessionMsgs) {
|
|
7869
8054
|
if (isAttachmentMessage(m)) {
|
|
7870
8055
|
allMessages.push(m);
|
|
@@ -7896,7 +8081,7 @@ var init_session_manager = __esm({
|
|
|
7896
8081
|
if (isAttachmentMessage(m) && m.attachment.type === "relevant_memories") {
|
|
7897
8082
|
for (const mem of m.attachment.memories) {
|
|
7898
8083
|
rawCount++;
|
|
7899
|
-
restoredPaths.add(
|
|
8084
|
+
restoredPaths.add(path10.resolve(mem.path));
|
|
7900
8085
|
}
|
|
7901
8086
|
}
|
|
7902
8087
|
}
|
|
@@ -7925,15 +8110,15 @@ var init_session_manager = __esm({
|
|
|
7925
8110
|
*/
|
|
7926
8111
|
rotateMainSession() {
|
|
7927
8112
|
const entry = this.index.get("main");
|
|
7928
|
-
if (!entry || !
|
|
7929
|
-
const oldFileId =
|
|
7930
|
-
const stat4 =
|
|
8113
|
+
if (!entry || !fs10.existsSync(entry.file)) return;
|
|
8114
|
+
const oldFileId = path10.basename(entry.file, ".jsonl");
|
|
8115
|
+
const stat4 = fs10.statSync(entry.file);
|
|
7931
8116
|
if (stat4.size < 1024) return;
|
|
7932
8117
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-");
|
|
7933
8118
|
const archivedPath = `${entry.file}.archived.${ts}`;
|
|
7934
|
-
|
|
8119
|
+
fs10.renameSync(entry.file, archivedPath);
|
|
7935
8120
|
const sizeMB = (stat4.size / 1024 / 1024).toFixed(1);
|
|
7936
|
-
console.log(`[session] Archived: ${
|
|
8121
|
+
console.log(`[session] Archived: ${path10.basename(entry.file)} \u2192 ${path10.basename(archivedPath)} (${sizeMB}MB)`);
|
|
7937
8122
|
const newWriter = new SessionWriter(this.sessionsDir);
|
|
7938
8123
|
newWriter.open(this.config.workspace, "main");
|
|
7939
8124
|
newWriter.writeModelChange(this.config.providerId, this.config.model);
|
|
@@ -7942,7 +8127,7 @@ var init_session_manager = __esm({
|
|
|
7942
8127
|
this.index.set("main", { file: newPath, updatedAt: Date.now() });
|
|
7943
8128
|
this.saveIndex();
|
|
7944
8129
|
this.purgeOldArchives(oldFileId, 3);
|
|
7945
|
-
console.log(`[session] Rotated main: ${oldFileId}.jsonl \u2192 ${
|
|
8130
|
+
console.log(`[session] Rotated main: ${oldFileId}.jsonl \u2192 ${path10.basename(newPath)}`);
|
|
7946
8131
|
}
|
|
7947
8132
|
// === 迁移 ===
|
|
7948
8133
|
/** 迁移旧索引:session-index.json 里有 "discord:xxx" 格式的 key 时,生成 UUID 替换 */
|
|
@@ -8007,7 +8192,7 @@ var init_session_manager = __esm({
|
|
|
8007
8192
|
});
|
|
8008
8193
|
|
|
8009
8194
|
// src/utils/path.ts
|
|
8010
|
-
import * as
|
|
8195
|
+
import * as path11 from "node:path";
|
|
8011
8196
|
function fixMsysPath(p) {
|
|
8012
8197
|
let fixed = p.includes("\\") ? p.replace(/\\/g, "/") : p;
|
|
8013
8198
|
if (process.platform === "win32") {
|
|
@@ -8017,15 +8202,15 @@ function fixMsysPath(p) {
|
|
|
8017
8202
|
}
|
|
8018
8203
|
function resolvePath(p, workspace) {
|
|
8019
8204
|
const fixed = fixMsysPath(p);
|
|
8020
|
-
const resolved =
|
|
8021
|
-
const normalized =
|
|
8022
|
-
const normalizedWorkspace =
|
|
8205
|
+
const resolved = path11.isAbsolute(fixed) ? path11.normalize(fixed) : path11.resolve(workspace, fixed);
|
|
8206
|
+
const normalized = path11.normalize(resolved);
|
|
8207
|
+
const normalizedWorkspace = path11.normalize(workspace);
|
|
8023
8208
|
if (sandboxOff) return normalized;
|
|
8024
|
-
if (normalized === normalizedWorkspace || normalized.startsWith(normalizedWorkspace +
|
|
8209
|
+
if (normalized === normalizedWorkspace || normalized.startsWith(normalizedWorkspace + path11.sep)) {
|
|
8025
8210
|
return normalized;
|
|
8026
8211
|
}
|
|
8027
8212
|
for (const allowed of extraAllowedPaths) {
|
|
8028
|
-
if (normalized === allowed || normalized.startsWith(allowed +
|
|
8213
|
+
if (normalized === allowed || normalized.startsWith(allowed + path11.sep)) {
|
|
8029
8214
|
return normalized;
|
|
8030
8215
|
}
|
|
8031
8216
|
}
|
|
@@ -8041,15 +8226,15 @@ var init_path = __esm({
|
|
|
8041
8226
|
});
|
|
8042
8227
|
|
|
8043
8228
|
// src/tools/read.ts
|
|
8044
|
-
import * as
|
|
8045
|
-
import * as
|
|
8229
|
+
import * as fs11 from "node:fs";
|
|
8230
|
+
import * as path12 from "node:path";
|
|
8046
8231
|
function isBlockedDevicePath(filePath) {
|
|
8047
8232
|
if (BLOCKED_DEVICE_PATHS.has(filePath)) return true;
|
|
8048
8233
|
if (filePath.startsWith("/proc/") && (filePath.endsWith("/fd/0") || filePath.endsWith("/fd/1") || filePath.endsWith("/fd/2"))) return true;
|
|
8049
8234
|
return false;
|
|
8050
8235
|
}
|
|
8051
8236
|
function checkReadLoop(filePath, offset, limit) {
|
|
8052
|
-
const stat4 =
|
|
8237
|
+
const stat4 = fs11.statSync(filePath);
|
|
8053
8238
|
const mtimeMs = stat4.mtimeMs;
|
|
8054
8239
|
const prev = readHistory.get(filePath);
|
|
8055
8240
|
if (prev && prev.offset === offset && prev.limit === limit && prev.mtimeMs === mtimeMs) {
|
|
@@ -8063,19 +8248,19 @@ function checkReadLoop(filePath, offset, limit) {
|
|
|
8063
8248
|
return null;
|
|
8064
8249
|
}
|
|
8065
8250
|
function readFileContent(filePath) {
|
|
8066
|
-
const fd =
|
|
8251
|
+
const fd = fs11.openSync(filePath, "r");
|
|
8067
8252
|
const bom = Buffer.alloc(2);
|
|
8068
|
-
|
|
8069
|
-
|
|
8253
|
+
fs11.readSync(fd, bom, 0, 2, 0);
|
|
8254
|
+
fs11.closeSync(fd);
|
|
8070
8255
|
let encoding = "utf8";
|
|
8071
8256
|
if (bom[0] === 255 && bom[1] === 254) {
|
|
8072
8257
|
encoding = "utf16le";
|
|
8073
8258
|
}
|
|
8074
|
-
const stat4 =
|
|
8259
|
+
const stat4 = fs11.statSync(filePath);
|
|
8075
8260
|
if (stat4.size > MAX_FILE_SIZE) {
|
|
8076
8261
|
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`);
|
|
8077
8262
|
}
|
|
8078
|
-
const raw =
|
|
8263
|
+
const raw = fs11.readFileSync(filePath, encoding);
|
|
8079
8264
|
const content = raw.toString().replaceAll("\r\n", "\n");
|
|
8080
8265
|
return { content, encoding };
|
|
8081
8266
|
}
|
|
@@ -8217,11 +8402,11 @@ Usage:
|
|
|
8217
8402
|
} catch (e) {
|
|
8218
8403
|
return { content: e.message, isError: true };
|
|
8219
8404
|
}
|
|
8220
|
-
if (!
|
|
8405
|
+
if (!fs11.existsSync(filePath)) {
|
|
8221
8406
|
return { content: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`, isError: true };
|
|
8222
8407
|
}
|
|
8223
|
-
const stat4 =
|
|
8224
|
-
const baseName =
|
|
8408
|
+
const stat4 = fs11.statSync(filePath);
|
|
8409
|
+
const baseName = path12.basename(filePath).toUpperCase();
|
|
8225
8410
|
if (BLOCKED_BASENAMES.has(baseName)) {
|
|
8226
8411
|
return { content: `\u8BBE\u5907\u6587\u4EF6\u4E0D\u652F\u6301\u8BFB\u53D6: ${filePath}`, isError: true };
|
|
8227
8412
|
}
|
|
@@ -8229,11 +8414,11 @@ Usage:
|
|
|
8229
8414
|
return { content: `\u8BBE\u5907\u6587\u4EF6\u4F1A\u963B\u585E\u6216\u4EA7\u751F\u65E0\u9650\u8F93\u51FA: ${filePath}`, isError: true };
|
|
8230
8415
|
}
|
|
8231
8416
|
if (stat4.isDirectory()) {
|
|
8232
|
-
const entries2 =
|
|
8417
|
+
const entries2 = fs11.readdirSync(filePath);
|
|
8233
8418
|
const items = entries2.map((e) => {
|
|
8234
|
-
const full =
|
|
8419
|
+
const full = path12.join(filePath, e);
|
|
8235
8420
|
try {
|
|
8236
|
-
const s =
|
|
8421
|
+
const s = fs11.statSync(full);
|
|
8237
8422
|
return s.isDirectory() ? `${e}/` : e;
|
|
8238
8423
|
} catch {
|
|
8239
8424
|
return e;
|
|
@@ -8242,7 +8427,7 @@ Usage:
|
|
|
8242
8427
|
return { content: `\u76EE\u5F55 (${entries2.length} \u9879):
|
|
8243
8428
|
${items.join("\n")}` };
|
|
8244
8429
|
}
|
|
8245
|
-
const ext =
|
|
8430
|
+
const ext = path12.extname(filePath).toLowerCase();
|
|
8246
8431
|
if (BINARY_EXTENSIONS.has(ext)) {
|
|
8247
8432
|
return { content: `\u4E8C\u8FDB\u5236\u6587\u4EF6\u4E0D\u652F\u6301\u8BFB\u53D6 (${ext}): ${filePath}`, isError: true };
|
|
8248
8433
|
}
|
|
@@ -8289,22 +8474,22 @@ ${result2}` : result2 };
|
|
|
8289
8474
|
});
|
|
8290
8475
|
|
|
8291
8476
|
// src/tools/write.ts
|
|
8292
|
-
import * as
|
|
8293
|
-
import * as
|
|
8477
|
+
import * as fs12 from "node:fs";
|
|
8478
|
+
import * as path13 from "node:path";
|
|
8294
8479
|
function isBlockedPath(filePath) {
|
|
8295
8480
|
return BLOCKED_PATTERNS.some((p) => p.test(filePath));
|
|
8296
8481
|
}
|
|
8297
8482
|
function atomicWrite(filePath, content) {
|
|
8298
8483
|
const tmpPath = filePath + ".tmp." + Date.now() + ".write";
|
|
8299
|
-
|
|
8484
|
+
fs12.writeFileSync(tmpPath, content, "utf-8");
|
|
8300
8485
|
try {
|
|
8301
|
-
|
|
8486
|
+
fs12.renameSync(tmpPath, filePath);
|
|
8302
8487
|
} catch (e) {
|
|
8303
8488
|
try {
|
|
8304
|
-
|
|
8489
|
+
fs12.unlinkSync(tmpPath);
|
|
8305
8490
|
} catch {
|
|
8306
8491
|
}
|
|
8307
|
-
|
|
8492
|
+
fs12.writeFileSync(filePath, content, "utf-8");
|
|
8308
8493
|
}
|
|
8309
8494
|
}
|
|
8310
8495
|
function simpleDiff(oldContent, newContent) {
|
|
@@ -8398,15 +8583,15 @@ Usage:
|
|
|
8398
8583
|
}
|
|
8399
8584
|
const rawContent = args.content;
|
|
8400
8585
|
const content = rawContent.replaceAll("\r\n", "\n");
|
|
8401
|
-
if (
|
|
8586
|
+
if (fs12.existsSync(filePath) && fs12.statSync(filePath).isDirectory()) {
|
|
8402
8587
|
return { content: `\u8DEF\u5F84\u662F\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6: ${filePath}`, isError: true };
|
|
8403
8588
|
}
|
|
8404
8589
|
let oldContent = null;
|
|
8405
8590
|
let isCreate = true;
|
|
8406
|
-
if (
|
|
8591
|
+
if (fs12.existsSync(filePath)) {
|
|
8407
8592
|
isCreate = false;
|
|
8408
8593
|
try {
|
|
8409
|
-
oldContent =
|
|
8594
|
+
oldContent = fs12.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
|
|
8410
8595
|
} catch {
|
|
8411
8596
|
isCreate = true;
|
|
8412
8597
|
}
|
|
@@ -8422,10 +8607,10 @@ Usage:
|
|
|
8422
8607
|
isError: true
|
|
8423
8608
|
};
|
|
8424
8609
|
}
|
|
8425
|
-
const currentStat =
|
|
8610
|
+
const currentStat = fs12.statSync(filePath);
|
|
8426
8611
|
const lastWriteTime = Math.floor(currentStat.mtimeMs);
|
|
8427
8612
|
if (lastWriteTime > readState.timestamp) {
|
|
8428
|
-
const currentContent =
|
|
8613
|
+
const currentContent = fs12.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
|
|
8429
8614
|
if (currentContent !== oldContent) {
|
|
8430
8615
|
return {
|
|
8431
8616
|
content: `\u6587\u4EF6\u5728\u8BFB\u53D6\u540E\u88AB\u4FEE\u6539\u3002\u8BF7\u5148\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\u518D\u5199\u5165: ${filePath}`,
|
|
@@ -8434,9 +8619,9 @@ Usage:
|
|
|
8434
8619
|
}
|
|
8435
8620
|
}
|
|
8436
8621
|
}
|
|
8437
|
-
const dir =
|
|
8622
|
+
const dir = path13.dirname(filePath);
|
|
8438
8623
|
try {
|
|
8439
|
-
|
|
8624
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
8440
8625
|
} catch (e) {
|
|
8441
8626
|
return { content: `\u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55: ${dir} \u2014 ${e.message}`, isError: true };
|
|
8442
8627
|
}
|
|
@@ -8445,11 +8630,11 @@ Usage:
|
|
|
8445
8630
|
} catch (e) {
|
|
8446
8631
|
return { content: `\u5199\u5165\u5931\u8D25: ${e.message}`, isError: true };
|
|
8447
8632
|
}
|
|
8448
|
-
readFileState.set(filePath, { timestamp:
|
|
8633
|
+
readFileState.set(filePath, { timestamp: fs12.statSync(filePath).mtimeMs });
|
|
8449
8634
|
const action = isCreate ? "\u521B\u5EFA" : "\u66F4\u65B0";
|
|
8450
8635
|
const lines = content.split("\n").length;
|
|
8451
8636
|
const chars = content.length;
|
|
8452
|
-
const stat4 =
|
|
8637
|
+
const stat4 = fs12.statSync(filePath);
|
|
8453
8638
|
let diff = "";
|
|
8454
8639
|
if (!isCreate && oldContent !== null) {
|
|
8455
8640
|
diff = `
|
|
@@ -8468,8 +8653,8 @@ ${simpleDiff(oldContent, content)}`;
|
|
|
8468
8653
|
});
|
|
8469
8654
|
|
|
8470
8655
|
// src/tools/edit.ts
|
|
8471
|
-
import * as
|
|
8472
|
-
import * as
|
|
8656
|
+
import * as fs13 from "node:fs";
|
|
8657
|
+
import * as path14 from "node:path";
|
|
8473
8658
|
function normalizeQuotes(str) {
|
|
8474
8659
|
return str.replaceAll(LEFT_SINGLE_CURLY, "'").replaceAll(RIGHT_SINGLE_CURLY, "'").replaceAll(LEFT_DOUBLE_CURLY, '"').replaceAll(RIGHT_DOUBLE_CURLY, '"');
|
|
8475
8660
|
}
|
|
@@ -8622,7 +8807,7 @@ Usage:
|
|
|
8622
8807
|
}
|
|
8623
8808
|
let fileContent = null;
|
|
8624
8809
|
try {
|
|
8625
|
-
const stat4 =
|
|
8810
|
+
const stat4 = fs13.statSync(filePath);
|
|
8626
8811
|
if (stat4.isDirectory()) {
|
|
8627
8812
|
return { content: `\u8DEF\u5F84\u662F\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6: ${filePath}`, isError: true };
|
|
8628
8813
|
}
|
|
@@ -8632,21 +8817,21 @@ Usage:
|
|
|
8632
8817
|
} catch (e) {
|
|
8633
8818
|
if (e.code === "ENOENT") {
|
|
8634
8819
|
if (oldString === "") {
|
|
8635
|
-
const dir =
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
readFileState.set(filePath, { timestamp:
|
|
8820
|
+
const dir = path14.dirname(filePath);
|
|
8821
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
8822
|
+
fs13.writeFileSync(filePath, newString, "utf-8");
|
|
8823
|
+
readFileState.set(filePath, { timestamp: fs13.statSync(filePath).mtimeMs });
|
|
8639
8824
|
return { content: `\u521B\u5EFA\u6587\u4EF6: ${filePath} (${newString.split("\n").length} \u884C)` };
|
|
8640
8825
|
}
|
|
8641
8826
|
return { content: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`, isError: true };
|
|
8642
8827
|
}
|
|
8643
8828
|
throw e;
|
|
8644
8829
|
}
|
|
8645
|
-
const rawContent =
|
|
8830
|
+
const rawContent = fs13.readFileSync(filePath, "utf-8");
|
|
8646
8831
|
fileContent = rawContent.replaceAll("\r\n", "\n");
|
|
8647
8832
|
if (oldString === "" && fileContent.trim() === "") {
|
|
8648
|
-
|
|
8649
|
-
readFileState.set(filePath, { timestamp:
|
|
8833
|
+
fs13.writeFileSync(filePath, newString, "utf-8");
|
|
8834
|
+
readFileState.set(filePath, { timestamp: fs13.statSync(filePath).mtimeMs });
|
|
8650
8835
|
return { content: `\u5199\u5165\u7A7A\u6587\u4EF6: ${filePath} (${newString.split("\n").length} \u884C)` };
|
|
8651
8836
|
}
|
|
8652
8837
|
const readState = readFileState.get(filePath);
|
|
@@ -8656,11 +8841,11 @@ Usage:
|
|
|
8656
8841
|
isError: true
|
|
8657
8842
|
};
|
|
8658
8843
|
}
|
|
8659
|
-
const currentStat =
|
|
8844
|
+
const currentStat = fs13.statSync(filePath);
|
|
8660
8845
|
const lastWriteTime = Math.floor(currentStat.mtimeMs);
|
|
8661
8846
|
if (lastWriteTime > readState.timestamp) {
|
|
8662
8847
|
if (fileContent !== rawContent.replaceAll("\r\n", "\n")) {
|
|
8663
|
-
if (fileContent !==
|
|
8848
|
+
if (fileContent !== fs13.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n")) {
|
|
8664
8849
|
return {
|
|
8665
8850
|
content: `\u6587\u4EF6\u5728\u8BFB\u53D6\u540E\u88AB\u4FEE\u6539\u3002\u8BF7\u5148\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\u518D\u7F16\u8F91: ${filePath}`,
|
|
8666
8851
|
isError: true
|
|
@@ -8692,8 +8877,8 @@ ${preview}
|
|
|
8692
8877
|
const actualNewString = preserveQuoteStyle(oldString, actualOldString, newString);
|
|
8693
8878
|
const diffView = generateEditDiff(fileContent, actualOldString, actualNewString);
|
|
8694
8879
|
const newContent = applyEditToFile(fileContent, actualOldString, actualNewString, replaceAll);
|
|
8695
|
-
|
|
8696
|
-
readFileState.set(filePath, { timestamp:
|
|
8880
|
+
fs13.writeFileSync(filePath, newContent, "utf-8");
|
|
8881
|
+
readFileState.set(filePath, { timestamp: fs13.statSync(filePath).mtimeMs });
|
|
8697
8882
|
const strategy = actualOldString === oldString ? "\u7CBE\u786E\u5339\u914D" : "\u5F15\u53F7\u89C4\u8303\u5316\u5339\u914D";
|
|
8698
8883
|
const count = replaceAll ? matchCount : 1;
|
|
8699
8884
|
const diff = `${oldString.length}\u2192${newString.length}\u5B57\u7B26`;
|
|
@@ -8710,8 +8895,8 @@ ${diffView}`
|
|
|
8710
8895
|
});
|
|
8711
8896
|
|
|
8712
8897
|
// src/tools/glob.ts
|
|
8713
|
-
import * as
|
|
8714
|
-
import * as
|
|
8898
|
+
import * as fs14 from "node:fs";
|
|
8899
|
+
import * as path15 from "node:path";
|
|
8715
8900
|
function globMatch(pattern, filename) {
|
|
8716
8901
|
const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
8717
8902
|
try {
|
|
@@ -8731,18 +8916,18 @@ function findFiles(dir, pattern, limit, baseDir) {
|
|
|
8731
8916
|
}
|
|
8732
8917
|
let entries2;
|
|
8733
8918
|
try {
|
|
8734
|
-
entries2 =
|
|
8919
|
+
entries2 = fs14.readdirSync(currentDir, { withFileTypes: true });
|
|
8735
8920
|
} catch {
|
|
8736
8921
|
return;
|
|
8737
8922
|
}
|
|
8738
8923
|
for (const entry of entries2) {
|
|
8739
8924
|
if (truncated) return;
|
|
8740
|
-
const fullPath =
|
|
8925
|
+
const fullPath = path15.join(currentDir, entry.name);
|
|
8741
8926
|
if (entry.isDirectory()) {
|
|
8742
8927
|
if (VCS_DIRS.has(entry.name)) continue;
|
|
8743
8928
|
walk(fullPath);
|
|
8744
8929
|
} else if (entry.isFile()) {
|
|
8745
|
-
const relativePath =
|
|
8930
|
+
const relativePath = path15.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
8746
8931
|
const patternsToTry = [pattern];
|
|
8747
8932
|
if (pattern.startsWith("**/")) {
|
|
8748
8933
|
patternsToTry.push(pattern.slice(3));
|
|
@@ -8752,7 +8937,7 @@ function findFiles(dir, pattern, limit, baseDir) {
|
|
|
8752
8937
|
);
|
|
8753
8938
|
if (matched) {
|
|
8754
8939
|
try {
|
|
8755
|
-
const stat4 =
|
|
8940
|
+
const stat4 = fs14.statSync(fullPath);
|
|
8756
8941
|
results.push({ path: fullPath, mtimeMs: stat4.mtimeMs });
|
|
8757
8942
|
} catch {
|
|
8758
8943
|
}
|
|
@@ -8769,7 +8954,7 @@ function findFiles(dir, pattern, limit, baseDir) {
|
|
|
8769
8954
|
};
|
|
8770
8955
|
}
|
|
8771
8956
|
function toRelativePath(absolutePath, cwd) {
|
|
8772
|
-
if (absolutePath.startsWith(cwd +
|
|
8957
|
+
if (absolutePath.startsWith(cwd + path15.sep)) {
|
|
8773
8958
|
return absolutePath.slice(cwd.length + 1);
|
|
8774
8959
|
}
|
|
8775
8960
|
return absolutePath;
|
|
@@ -8802,10 +8987,10 @@ var init_glob = __esm({
|
|
|
8802
8987
|
const searchPath = args.path ? resolvePath(args.path, ctx.workspace) : ctx.workspace;
|
|
8803
8988
|
const pattern = args.pattern;
|
|
8804
8989
|
const limit = args.limit || DEFAULT_LIMIT;
|
|
8805
|
-
if (!
|
|
8990
|
+
if (!fs14.existsSync(searchPath)) {
|
|
8806
8991
|
return { content: `\u76EE\u5F55\u4E0D\u5B58\u5728: ${searchPath}`, isError: true };
|
|
8807
8992
|
}
|
|
8808
|
-
if (!
|
|
8993
|
+
if (!fs14.statSync(searchPath).isDirectory()) {
|
|
8809
8994
|
return { content: `\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${searchPath}`, isError: true };
|
|
8810
8995
|
}
|
|
8811
8996
|
const start = Date.now();
|
|
@@ -8829,7 +9014,7 @@ ${filenames.join("\n")}${truncatedNote}`
|
|
|
8829
9014
|
|
|
8830
9015
|
// src/tools/grep.ts
|
|
8831
9016
|
import { execFile } from "node:child_process";
|
|
8832
|
-
import * as
|
|
9017
|
+
import * as path16 from "node:path";
|
|
8833
9018
|
function ripGrep(args, searchPath, signal) {
|
|
8834
9019
|
return new Promise((resolve11) => {
|
|
8835
9020
|
const fullArgs = [...args, searchPath];
|
|
@@ -8861,7 +9046,7 @@ function applyHeadLimit(items, limit, offset = 0) {
|
|
|
8861
9046
|
};
|
|
8862
9047
|
}
|
|
8863
9048
|
function toRelativePath2(absolutePath, cwd) {
|
|
8864
|
-
if (absolutePath.startsWith(cwd +
|
|
9049
|
+
if (absolutePath.startsWith(cwd + path16.sep)) {
|
|
8865
9050
|
return absolutePath.slice(cwd.length + 1);
|
|
8866
9051
|
}
|
|
8867
9052
|
if (absolutePath.startsWith(cwd)) {
|
|
@@ -9031,12 +9216,14 @@ ${filenames.join("\n")}${truncatedNote}`
|
|
|
9031
9216
|
// src/tools/task-manager.ts
|
|
9032
9217
|
var task_manager_exports = {};
|
|
9033
9218
|
__export(task_manager_exports, {
|
|
9219
|
+
ackPendingNotification: () => ackPendingNotification,
|
|
9034
9220
|
buildCalendarNotification: () => buildCalendarNotification,
|
|
9035
9221
|
buildNudgeNotification: () => buildNudgeNotification,
|
|
9036
9222
|
clearNotificationCallback: () => clearNotificationCallback,
|
|
9037
9223
|
drainPendingNotifications: () => drainPendingNotifications,
|
|
9038
9224
|
enqueueNotification: () => enqueueNotification,
|
|
9039
9225
|
generateTaskId: () => generateTaskId,
|
|
9226
|
+
getPendingNotificationRecords: () => getPendingNotificationRecords,
|
|
9040
9227
|
getPendingNotifications: () => getPendingNotifications,
|
|
9041
9228
|
getTask: () => getTask,
|
|
9042
9229
|
getTaskOutput: () => getTaskOutput,
|
|
@@ -9045,14 +9232,16 @@ __export(task_manager_exports, {
|
|
|
9045
9232
|
getTaskOutputPath: () => getTaskOutputPath,
|
|
9046
9233
|
getTaskOutputSize: () => getTaskOutputSize,
|
|
9047
9234
|
killTask: () => killTask,
|
|
9235
|
+
listLiveTasks: () => listLiveTasks,
|
|
9048
9236
|
listTasks: () => listTasks,
|
|
9237
|
+
loadPersistedTasks: () => loadPersistedTasks,
|
|
9049
9238
|
setNotificationCallback: () => setNotificationCallback,
|
|
9050
9239
|
spawnBackgroundTask: () => spawnBackgroundTask
|
|
9051
9240
|
});
|
|
9052
9241
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
9053
9242
|
import { spawn as spawn2 } from "node:child_process";
|
|
9054
|
-
import * as
|
|
9055
|
-
import * as
|
|
9243
|
+
import * as fs15 from "node:fs";
|
|
9244
|
+
import * as path17 from "node:path";
|
|
9056
9245
|
function generateTaskId(type2 = "local_bash") {
|
|
9057
9246
|
const prefix = TASK_ID_PREFIXES[type2] ?? "x";
|
|
9058
9247
|
const bytes = randomBytes3(8);
|
|
@@ -9065,60 +9254,182 @@ function generateTaskId(type2 = "local_bash") {
|
|
|
9065
9254
|
function getTaskOutputDir() {
|
|
9066
9255
|
if (_taskOutputDir === void 0) {
|
|
9067
9256
|
const stateDir = process.env.ENGINE_STATE_DIR || process.cwd();
|
|
9068
|
-
_taskOutputDir =
|
|
9257
|
+
_taskOutputDir = path17.join(stateDir, "tasks");
|
|
9069
9258
|
}
|
|
9070
9259
|
return _taskOutputDir;
|
|
9071
9260
|
}
|
|
9072
9261
|
function getTaskOutputPath(taskId) {
|
|
9073
|
-
return
|
|
9262
|
+
return path17.join(getTaskOutputDir(), `${taskId}.output`);
|
|
9074
9263
|
}
|
|
9075
9264
|
function ensureOutputDir() {
|
|
9076
9265
|
const dir = getTaskOutputDir();
|
|
9077
|
-
if (!
|
|
9078
|
-
|
|
9266
|
+
if (!fs15.existsSync(dir)) {
|
|
9267
|
+
fs15.mkdirSync(dir, { recursive: true });
|
|
9079
9268
|
}
|
|
9080
9269
|
}
|
|
9081
9270
|
function initTaskOutput(taskId) {
|
|
9082
9271
|
ensureOutputDir();
|
|
9083
9272
|
const outputPath = getTaskOutputPath(taskId);
|
|
9084
|
-
|
|
9273
|
+
fs15.writeFileSync(outputPath, "", "utf-8");
|
|
9085
9274
|
return outputPath;
|
|
9086
9275
|
}
|
|
9276
|
+
function persistTask(state2) {
|
|
9277
|
+
try {
|
|
9278
|
+
ensureOutputDir();
|
|
9279
|
+
const p = taskIndexPath();
|
|
9280
|
+
const existing = fs15.existsSync(p) ? JSON.parse(fs15.readFileSync(p, "utf8")) : [];
|
|
9281
|
+
const next = existing.filter((t) => t.id !== state2.id);
|
|
9282
|
+
next.push({ ...state2 });
|
|
9283
|
+
const tmp = `${p}.${process.pid}.tmp`;
|
|
9284
|
+
fs15.writeFileSync(tmp, JSON.stringify(next, null, 2));
|
|
9285
|
+
fs15.renameSync(tmp, p);
|
|
9286
|
+
} catch (err) {
|
|
9287
|
+
console.warn(`[task-manager] persist failed: ${err.message}`);
|
|
9288
|
+
}
|
|
9289
|
+
}
|
|
9290
|
+
function loadPersistedTasks() {
|
|
9291
|
+
try {
|
|
9292
|
+
const v = JSON.parse(fs15.readFileSync(taskIndexPath(), "utf8"));
|
|
9293
|
+
return Array.isArray(v) ? v : [];
|
|
9294
|
+
} catch {
|
|
9295
|
+
return [];
|
|
9296
|
+
}
|
|
9297
|
+
}
|
|
9298
|
+
function loadNotificationQueue() {
|
|
9299
|
+
if (notificationsLoaded) return;
|
|
9300
|
+
notificationsLoaded = true;
|
|
9301
|
+
try {
|
|
9302
|
+
const value = JSON.parse(fs15.readFileSync(notificationQueuePath(), "utf8"));
|
|
9303
|
+
if (Array.isArray(value)) pendingNotifications.push(...value.filter((x) => x && typeof x.notification === "string"));
|
|
9304
|
+
} catch {
|
|
9305
|
+
}
|
|
9306
|
+
}
|
|
9307
|
+
function persistNotificationQueue() {
|
|
9308
|
+
try {
|
|
9309
|
+
ensureOutputDir();
|
|
9310
|
+
const p = notificationQueuePath();
|
|
9311
|
+
const tmp = `${p}.${process.pid}.tmp`;
|
|
9312
|
+
fs15.writeFileSync(tmp, JSON.stringify(pendingNotifications, null, 2), "utf8");
|
|
9313
|
+
fs15.renameSync(tmp, p);
|
|
9314
|
+
} catch (err) {
|
|
9315
|
+
console.warn(`[task-manager] notification persist failed: ${err.message}`);
|
|
9316
|
+
}
|
|
9317
|
+
}
|
|
9318
|
+
function notificationRetryDelayMs(attempt) {
|
|
9319
|
+
return Math.min(RETRY_MAX_MS, RETRY_BASE_MS * 2 ** Math.min(attempt, 6));
|
|
9320
|
+
}
|
|
9321
|
+
function notificationDue(item, now = Date.now()) {
|
|
9322
|
+
if (!item.nextAttemptAt) return true;
|
|
9323
|
+
const dueAt = Date.parse(item.nextAttemptAt);
|
|
9324
|
+
return Number.isFinite(dueAt) && dueAt <= now;
|
|
9325
|
+
}
|
|
9326
|
+
function scheduleNotificationRetry() {
|
|
9327
|
+
if (notificationRetryTimer || !notificationCallback || pendingNotifications.length === 0) return;
|
|
9328
|
+
let earliest;
|
|
9329
|
+
for (const item of pendingNotifications) {
|
|
9330
|
+
if (!item.nextAttemptAt) continue;
|
|
9331
|
+
const dueAt = Date.parse(item.nextAttemptAt);
|
|
9332
|
+
if (Number.isFinite(dueAt) && (earliest === void 0 || dueAt < earliest)) earliest = dueAt;
|
|
9333
|
+
}
|
|
9334
|
+
if (earliest === void 0) return;
|
|
9335
|
+
notificationRetryTimer = setTimeout(() => {
|
|
9336
|
+
notificationRetryTimer = void 0;
|
|
9337
|
+
attemptDueNotifications();
|
|
9338
|
+
}, Math.max(0, earliest - Date.now()));
|
|
9339
|
+
notificationRetryTimer.unref?.();
|
|
9340
|
+
}
|
|
9341
|
+
function attemptDueNotifications() {
|
|
9342
|
+
if (!notificationCallback) return;
|
|
9343
|
+
const remaining = [];
|
|
9344
|
+
for (const item of pendingNotifications) {
|
|
9345
|
+
if (!notificationDue(item)) {
|
|
9346
|
+
remaining.push(item);
|
|
9347
|
+
continue;
|
|
9348
|
+
}
|
|
9349
|
+
try {
|
|
9350
|
+
notificationCallback(item.notification, item.route);
|
|
9351
|
+
} catch (err) {
|
|
9352
|
+
const attempt = (item.attempt ?? 0) + 1;
|
|
9353
|
+
remaining.push({ ...item, attempt, nextAttemptAt: new Date(Date.now() + notificationRetryDelayMs(attempt)).toISOString(), lastError: String(err?.message || err) });
|
|
9354
|
+
}
|
|
9355
|
+
}
|
|
9356
|
+
pendingNotifications.length = 0;
|
|
9357
|
+
pendingNotifications.push(...remaining);
|
|
9358
|
+
persistNotificationQueue();
|
|
9359
|
+
scheduleNotificationRetry();
|
|
9360
|
+
}
|
|
9087
9361
|
function setNotificationCallback(cb) {
|
|
9088
9362
|
notificationCallback = cb;
|
|
9363
|
+
loadNotificationQueue();
|
|
9364
|
+
if (pendingNotifications.length === 0) return;
|
|
9365
|
+
attemptDueNotifications();
|
|
9089
9366
|
}
|
|
9090
9367
|
function clearNotificationCallback() {
|
|
9091
9368
|
notificationCallback = null;
|
|
9369
|
+
if (notificationRetryTimer) {
|
|
9370
|
+
clearTimeout(notificationRetryTimer);
|
|
9371
|
+
notificationRetryTimer = void 0;
|
|
9372
|
+
}
|
|
9092
9373
|
}
|
|
9093
|
-
function enqueueNotification(notification, route) {
|
|
9374
|
+
function enqueueNotification(notification, route, idempotencyKey) {
|
|
9375
|
+
loadNotificationQueue();
|
|
9376
|
+
if (idempotencyKey && pendingNotifications.some((item) => item.idempotencyKey === idempotencyKey)) return;
|
|
9094
9377
|
if (notificationCallback) {
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9378
|
+
try {
|
|
9379
|
+
notificationCallback(notification, route);
|
|
9380
|
+
console.log(`[task-manager] Notification dispatched via callback (event-driven, session=${route?.sessionId || "none"}, channel=${route?.channel || "none"})`);
|
|
9381
|
+
return;
|
|
9382
|
+
} catch (err) {
|
|
9383
|
+
console.warn(`[task-manager] Notification callback failed, persisting for retry: ${err.message}`);
|
|
9384
|
+
pendingNotifications.push({ id: `n-${Date.now()}-${randomBytes3(4).toString("hex")}`, notification, route, createdAt: (/* @__PURE__ */ new Date()).toISOString(), attempt: 1, nextAttemptAt: new Date(Date.now() + notificationRetryDelayMs(1)).toISOString(), lastError: String(err?.message || err), idempotencyKey });
|
|
9385
|
+
persistNotificationQueue();
|
|
9386
|
+
scheduleNotificationRetry();
|
|
9387
|
+
return;
|
|
9388
|
+
}
|
|
9098
9389
|
}
|
|
9099
|
-
pendingNotifications.push(notification);
|
|
9390
|
+
pendingNotifications.push({ id: `n-${Date.now()}-${randomBytes3(4).toString("hex")}`, notification, route, createdAt: (/* @__PURE__ */ new Date()).toISOString(), idempotencyKey });
|
|
9391
|
+
persistNotificationQueue();
|
|
9100
9392
|
console.log(`[task-manager] Notification queued (${pendingNotifications.length} pending, no callback)`);
|
|
9101
9393
|
}
|
|
9102
9394
|
function getPendingNotifications() {
|
|
9103
|
-
|
|
9395
|
+
loadNotificationQueue();
|
|
9396
|
+
return pendingNotifications.map((item) => item.notification);
|
|
9397
|
+
}
|
|
9398
|
+
function getPendingNotificationRecords() {
|
|
9399
|
+
loadNotificationQueue();
|
|
9400
|
+
return pendingNotifications.map((item) => ({ ...item, route: item.route ? { ...item.route } : void 0 }));
|
|
9401
|
+
}
|
|
9402
|
+
function ackPendingNotification(id) {
|
|
9403
|
+
loadNotificationQueue();
|
|
9404
|
+
const index = pendingNotifications.findIndex((item) => item.id === id);
|
|
9405
|
+
if (index < 0) return false;
|
|
9406
|
+
pendingNotifications.splice(index, 1);
|
|
9407
|
+
persistNotificationQueue();
|
|
9408
|
+
scheduleNotificationRetry();
|
|
9409
|
+
return true;
|
|
9104
9410
|
}
|
|
9105
9411
|
function drainPendingNotifications() {
|
|
9106
|
-
|
|
9412
|
+
loadNotificationQueue();
|
|
9413
|
+
const due = pendingNotifications.filter((item) => notificationDue(item));
|
|
9414
|
+
if (due.length === 0) return [];
|
|
9415
|
+
const kept = pendingNotifications.filter((item) => !notificationDue(item));
|
|
9107
9416
|
pendingNotifications.length = 0;
|
|
9108
|
-
|
|
9417
|
+
pendingNotifications.push(...kept);
|
|
9418
|
+
persistNotificationQueue();
|
|
9419
|
+
return due.map((item) => item.notification);
|
|
9109
9420
|
}
|
|
9110
9421
|
function spawnBackgroundTask(opts) {
|
|
9111
9422
|
const taskId = generateTaskId("local_bash");
|
|
9112
9423
|
const outputPath = initTaskOutput(taskId);
|
|
9113
9424
|
const { shell, args: shellArgs } = findShell();
|
|
9114
|
-
const outputFd =
|
|
9425
|
+
const outputFd = fs15.openSync(outputPath, "w");
|
|
9115
9426
|
const child = spawn2(shell, [...shellArgs, opts.command], {
|
|
9116
9427
|
cwd: opts.cwd,
|
|
9117
9428
|
env: opts.env || process.env,
|
|
9118
9429
|
stdio: ["ignore", outputFd, outputFd]
|
|
9119
9430
|
});
|
|
9120
9431
|
try {
|
|
9121
|
-
|
|
9432
|
+
fs15.closeSync(outputFd);
|
|
9122
9433
|
} catch {
|
|
9123
9434
|
}
|
|
9124
9435
|
processes.set(taskId, child);
|
|
@@ -9136,6 +9447,7 @@ function spawnBackgroundTask(opts) {
|
|
|
9136
9447
|
channelTarget: opts.channelTarget
|
|
9137
9448
|
};
|
|
9138
9449
|
tasks.set(taskId, taskState);
|
|
9450
|
+
persistTask(taskState);
|
|
9139
9451
|
let timer;
|
|
9140
9452
|
if (opts.timeout && opts.timeout > 0) {
|
|
9141
9453
|
timer = setTimeout(() => {
|
|
@@ -9149,12 +9461,12 @@ function spawnBackgroundTask(opts) {
|
|
|
9149
9461
|
let killedForSize = false;
|
|
9150
9462
|
sizeWatchdog = setInterval(() => {
|
|
9151
9463
|
if (tasks.get(taskId)?.status !== "running") return;
|
|
9152
|
-
|
|
9464
|
+
fs15.stat(outputPath, (err, st) => {
|
|
9153
9465
|
if (err || st.size <= MAX_TASK_OUTPUT_BYTES) return;
|
|
9154
9466
|
killedForSize = true;
|
|
9155
9467
|
if (sizeWatchdog) clearInterval(sizeWatchdog);
|
|
9156
9468
|
try {
|
|
9157
|
-
|
|
9469
|
+
fs15.appendFileSync(outputPath, "\n[output truncated: exceeded 5GB disk cap]\n");
|
|
9158
9470
|
} catch {
|
|
9159
9471
|
}
|
|
9160
9472
|
killChild(child);
|
|
@@ -9172,8 +9484,15 @@ function spawnBackgroundTask(opts) {
|
|
|
9172
9484
|
state2.status = status;
|
|
9173
9485
|
state2.exitCode = exitCode;
|
|
9174
9486
|
state2.endTime = Date.now();
|
|
9487
|
+
persistTask(state2);
|
|
9488
|
+
try {
|
|
9489
|
+
opts.onComplete?.(state2);
|
|
9490
|
+
} catch (err) {
|
|
9491
|
+
console.error(`[task-manager] completion callback failed: ${err.message}`);
|
|
9492
|
+
}
|
|
9175
9493
|
if (!state2.notified) {
|
|
9176
9494
|
state2.notified = true;
|
|
9495
|
+
persistTask(state2);
|
|
9177
9496
|
const summary = buildSummary(state2);
|
|
9178
9497
|
const notification = buildTaskNotification(taskId, outputPath, status, summary);
|
|
9179
9498
|
enqueueNotification(notification, { sessionId: state2.sessionId, channel: state2.channel, channelTarget: state2.channelTarget });
|
|
@@ -9228,6 +9547,12 @@ function getTask(taskId) {
|
|
|
9228
9547
|
return tasks.get(taskId);
|
|
9229
9548
|
}
|
|
9230
9549
|
function listTasks() {
|
|
9550
|
+
const merged = /* @__PURE__ */ new Map();
|
|
9551
|
+
for (const t of loadPersistedTasks()) merged.set(t.id, t);
|
|
9552
|
+
for (const t of tasks.values()) merged.set(t.id, t);
|
|
9553
|
+
return [...merged.values()];
|
|
9554
|
+
}
|
|
9555
|
+
function listLiveTasks() {
|
|
9231
9556
|
return [...tasks.values()];
|
|
9232
9557
|
}
|
|
9233
9558
|
function getTaskOutput(taskId, maxBytes = 8 * 1024 * 1024) {
|
|
@@ -9235,16 +9560,16 @@ function getTaskOutput(taskId, maxBytes = 8 * 1024 * 1024) {
|
|
|
9235
9560
|
if (!state2) return "";
|
|
9236
9561
|
try {
|
|
9237
9562
|
const outputPath = state2.outputFile;
|
|
9238
|
-
if (!
|
|
9239
|
-
const stat4 =
|
|
9563
|
+
if (!fs15.existsSync(outputPath)) return "";
|
|
9564
|
+
const stat4 = fs15.statSync(outputPath);
|
|
9240
9565
|
if (stat4.size <= maxBytes) {
|
|
9241
|
-
return
|
|
9566
|
+
return fs15.readFileSync(outputPath, "utf-8");
|
|
9242
9567
|
}
|
|
9243
|
-
const fd =
|
|
9568
|
+
const fd = fs15.openSync(outputPath, "r");
|
|
9244
9569
|
const start = stat4.size - maxBytes;
|
|
9245
9570
|
const buf = Buffer.alloc(maxBytes);
|
|
9246
|
-
|
|
9247
|
-
|
|
9571
|
+
fs15.readSync(fd, buf, 0, maxBytes, start);
|
|
9572
|
+
fs15.closeSync(fd);
|
|
9248
9573
|
const content = buf.toString("utf-8");
|
|
9249
9574
|
const omitted = Math.round((stat4.size - maxBytes) / 1024);
|
|
9250
9575
|
return `[${omitted}KB of earlier output omitted]
|
|
@@ -9258,14 +9583,14 @@ function getTaskOutputDelta(taskId, fromOffset, maxBytes = 8 * 1024 * 1024) {
|
|
|
9258
9583
|
if (!state2) return { content: "", newOffset: fromOffset };
|
|
9259
9584
|
try {
|
|
9260
9585
|
const outputPath = state2.outputFile;
|
|
9261
|
-
if (!
|
|
9262
|
-
const stat4 =
|
|
9586
|
+
if (!fs15.existsSync(outputPath)) return { content: "", newOffset: fromOffset };
|
|
9587
|
+
const stat4 = fs15.statSync(outputPath);
|
|
9263
9588
|
if (fromOffset >= stat4.size) return { content: "", newOffset: stat4.size };
|
|
9264
9589
|
const readLen = Math.min(maxBytes, stat4.size - fromOffset);
|
|
9265
9590
|
const buf = Buffer.alloc(readLen);
|
|
9266
|
-
const fd =
|
|
9267
|
-
|
|
9268
|
-
|
|
9591
|
+
const fd = fs15.openSync(outputPath, "r");
|
|
9592
|
+
fs15.readSync(fd, buf, 0, readLen, fromOffset);
|
|
9593
|
+
fs15.closeSync(fd);
|
|
9269
9594
|
return { content: buf.toString("utf-8"), newOffset: fromOffset + readLen };
|
|
9270
9595
|
} catch {
|
|
9271
9596
|
return { content: "", newOffset: fromOffset };
|
|
@@ -9275,8 +9600,8 @@ function getTaskOutputSize(taskId) {
|
|
|
9275
9600
|
const state2 = tasks.get(taskId);
|
|
9276
9601
|
if (!state2) return 0;
|
|
9277
9602
|
try {
|
|
9278
|
-
if (!
|
|
9279
|
-
return
|
|
9603
|
+
if (!fs15.existsSync(state2.outputFile)) return 0;
|
|
9604
|
+
return fs15.statSync(state2.outputFile).size;
|
|
9280
9605
|
} catch {
|
|
9281
9606
|
return 0;
|
|
9282
9607
|
}
|
|
@@ -9300,7 +9625,7 @@ function killTask(taskId) {
|
|
|
9300
9625
|
}
|
|
9301
9626
|
return true;
|
|
9302
9627
|
}
|
|
9303
|
-
var TASK_ID_PREFIXES, TASK_ID_ALPHABET, MAX_TASK_OUTPUT_BYTES, _taskOutputDir, tasks, processes, pendingNotifications, notificationCallback, TASK_NOTIFICATION_TAG, TASK_ID_TAG, TASK_TYPE_TAG, TOOL_USE_ID_TAG, OUTPUT_FILE_TAG, STATUS_TAG, SUMMARY_TAG, CALENDAR_NOTIFICATION_TAG, CAL_TYPE_TAG, CAL_EVENT_TAG, CAL_EVENTS_TAG, NUDGE_NOTIFICATION_TAG, NUDGE_TYPE_TAG, NUDGE_DESC_TAG;
|
|
9628
|
+
var TASK_ID_PREFIXES, TASK_ID_ALPHABET, MAX_TASK_OUTPUT_BYTES, _taskOutputDir, tasks, processes, taskIndexPath, pendingNotifications, notificationsLoaded, notificationQueuePath, notificationCallback, RETRY_BASE_MS, RETRY_MAX_MS, notificationRetryTimer, TASK_NOTIFICATION_TAG, TASK_ID_TAG, TASK_TYPE_TAG, TOOL_USE_ID_TAG, OUTPUT_FILE_TAG, STATUS_TAG, SUMMARY_TAG, CALENDAR_NOTIFICATION_TAG, CAL_TYPE_TAG, CAL_EVENT_TAG, CAL_EVENTS_TAG, NUDGE_NOTIFICATION_TAG, NUDGE_TYPE_TAG, NUDGE_DESC_TAG;
|
|
9304
9629
|
var init_task_manager = __esm({
|
|
9305
9630
|
"src/tools/task-manager.ts"() {
|
|
9306
9631
|
"use strict";
|
|
@@ -9314,8 +9639,13 @@ var init_task_manager = __esm({
|
|
|
9314
9639
|
MAX_TASK_OUTPUT_BYTES = 5 * 1024 * 1024 * 1024;
|
|
9315
9640
|
tasks = /* @__PURE__ */ new Map();
|
|
9316
9641
|
processes = /* @__PURE__ */ new Map();
|
|
9642
|
+
taskIndexPath = () => path17.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "index.json");
|
|
9317
9643
|
pendingNotifications = [];
|
|
9644
|
+
notificationsLoaded = false;
|
|
9645
|
+
notificationQueuePath = () => path17.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "notifications.json");
|
|
9318
9646
|
notificationCallback = null;
|
|
9647
|
+
RETRY_BASE_MS = 1e3;
|
|
9648
|
+
RETRY_MAX_MS = 6e4;
|
|
9319
9649
|
TASK_NOTIFICATION_TAG = "task-notification";
|
|
9320
9650
|
TASK_ID_TAG = "task-id";
|
|
9321
9651
|
TASK_TYPE_TAG = "task-type";
|
|
@@ -9554,8 +9884,8 @@ __export(BashTool_exports, {
|
|
|
9554
9884
|
killChild: () => killChild
|
|
9555
9885
|
});
|
|
9556
9886
|
import { spawn as spawn3, execSync } from "node:child_process";
|
|
9557
|
-
import * as
|
|
9558
|
-
import * as
|
|
9887
|
+
import * as fs16 from "node:fs";
|
|
9888
|
+
import * as path18 from "node:path";
|
|
9559
9889
|
function isWslBash(p) {
|
|
9560
9890
|
const normalized = p.replace(/\//g, "\\").toLowerCase();
|
|
9561
9891
|
return WSL_PATH_MARKERS.some((m) => normalized.includes(m.toLowerCase()));
|
|
@@ -9574,7 +9904,7 @@ function findShell() {
|
|
|
9574
9904
|
});
|
|
9575
9905
|
const candidates = result2.trim().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
9576
9906
|
const nonWsl = candidates.find((p) => !isWslBash(p));
|
|
9577
|
-
if (nonWsl &&
|
|
9907
|
+
if (nonWsl && fs16.existsSync(nonWsl)) {
|
|
9578
9908
|
cachedShell = { shell: nonWsl, args: ["-c"] };
|
|
9579
9909
|
return cachedShell;
|
|
9580
9910
|
}
|
|
@@ -9584,10 +9914,10 @@ function findShell() {
|
|
|
9584
9914
|
"C:\\Program Files\\Git\\bin\\bash.exe",
|
|
9585
9915
|
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
9586
9916
|
"C:\\Program Files\\Git\\usr\\bin\\bash.exe",
|
|
9587
|
-
|
|
9917
|
+
path18.join(process.env.LOCALAPPDATA || "", "Programs", "Git", "bin", "bash.exe")
|
|
9588
9918
|
];
|
|
9589
9919
|
for (const p of knownPaths) {
|
|
9590
|
-
if (p &&
|
|
9920
|
+
if (p && fs16.existsSync(p)) {
|
|
9591
9921
|
cachedShell = { shell: p, args: ["-c"] };
|
|
9592
9922
|
return cachedShell;
|
|
9593
9923
|
}
|
|
@@ -9690,8 +10020,8 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
|
|
|
9690
10020
|
}
|
|
9691
10021
|
const MAX_OUTPUT = 100 * 1024;
|
|
9692
10022
|
const osMod = await import("node:os");
|
|
9693
|
-
const outputFile =
|
|
9694
|
-
const outputHandle = await
|
|
10023
|
+
const outputFile = path18.join(osMod.tmpdir(), `exec-${Date.now()}-${Math.random().toString(36).slice(2)}.out`);
|
|
10024
|
+
const outputHandle = await fs16.promises.open(outputFile, "w");
|
|
9695
10025
|
return new Promise((resolve11) => {
|
|
9696
10026
|
const { shell, args: shellArgs } = findShell();
|
|
9697
10027
|
const child = spawn3(shell, [...shellArgs, command], {
|
|
@@ -9710,21 +10040,21 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
|
|
|
9710
10040
|
let fileOutput = "";
|
|
9711
10041
|
let truncated = false;
|
|
9712
10042
|
try {
|
|
9713
|
-
const st = await
|
|
10043
|
+
const st = await fs16.promises.stat(outputFile);
|
|
9714
10044
|
if (st.size > MAX_OUTPUT) {
|
|
9715
|
-
const rfd = await
|
|
10045
|
+
const rfd = await fs16.promises.open(outputFile, "r");
|
|
9716
10046
|
const buf = Buffer.alloc(MAX_OUTPUT);
|
|
9717
10047
|
await rfd.read(buf, 0, MAX_OUTPUT, 0);
|
|
9718
10048
|
await rfd.close();
|
|
9719
10049
|
fileOutput = buf.toString("utf-8");
|
|
9720
10050
|
truncated = true;
|
|
9721
10051
|
} else {
|
|
9722
|
-
fileOutput = await
|
|
10052
|
+
fileOutput = await fs16.promises.readFile(outputFile, "utf-8");
|
|
9723
10053
|
}
|
|
9724
10054
|
} catch {
|
|
9725
10055
|
}
|
|
9726
10056
|
try {
|
|
9727
|
-
await
|
|
10057
|
+
await fs16.promises.unlink(outputFile);
|
|
9728
10058
|
} catch {
|
|
9729
10059
|
}
|
|
9730
10060
|
const processedStdout = fileOutput.replace(/^(\s*\n)+/, "").trimEnd();
|
|
@@ -10529,23 +10859,23 @@ var init_agentSwarmsEnabled = __esm({
|
|
|
10529
10859
|
});
|
|
10530
10860
|
|
|
10531
10861
|
// src/swarm/teamHelpers.ts
|
|
10532
|
-
import { mkdirSync as
|
|
10862
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
10533
10863
|
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
10534
|
-
import { join as
|
|
10864
|
+
import { join as join16 } from "node:path";
|
|
10535
10865
|
function getTeamsDir() {
|
|
10536
|
-
return
|
|
10866
|
+
return join16(_stateDir, "teams");
|
|
10537
10867
|
}
|
|
10538
10868
|
function getTasksDir() {
|
|
10539
|
-
return
|
|
10869
|
+
return join16(_stateDir, "tasks");
|
|
10540
10870
|
}
|
|
10541
10871
|
function sanitizeName(name) {
|
|
10542
10872
|
return name.replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
|
|
10543
10873
|
}
|
|
10544
10874
|
function getTeamDir(teamName) {
|
|
10545
|
-
return
|
|
10875
|
+
return join16(getTeamsDir(), sanitizeName(teamName));
|
|
10546
10876
|
}
|
|
10547
10877
|
function getTeamFilePath(teamName) {
|
|
10548
|
-
return
|
|
10878
|
+
return join16(getTeamDir(teamName), "config.json");
|
|
10549
10879
|
}
|
|
10550
10880
|
function readTeamFile(teamName) {
|
|
10551
10881
|
try {
|
|
@@ -10612,7 +10942,7 @@ async function cleanupTeamDirectories(teamName) {
|
|
|
10612
10942
|
} catch (error) {
|
|
10613
10943
|
console.warn(`[teamHelpers] Failed to clean up team directory ${teamDir}: ${error.message}`);
|
|
10614
10944
|
}
|
|
10615
|
-
const tasksDir =
|
|
10945
|
+
const tasksDir = join16(getTasksDir(), sanitizedName);
|
|
10616
10946
|
try {
|
|
10617
10947
|
await rm(tasksDir, { recursive: true, force: true });
|
|
10618
10948
|
console.log(`[teamHelpers] Cleaned up tasks directory: ${tasksDir}`);
|
|
@@ -10621,8 +10951,8 @@ async function cleanupTeamDirectories(teamName) {
|
|
|
10621
10951
|
}
|
|
10622
10952
|
}
|
|
10623
10953
|
function ensureTasksDir(taskListId) {
|
|
10624
|
-
const dir =
|
|
10625
|
-
|
|
10954
|
+
const dir = join16(getTasksDir(), taskListId);
|
|
10955
|
+
mkdirSync8(dir, { recursive: true });
|
|
10626
10956
|
}
|
|
10627
10957
|
function setLeaderTeamName(name) {
|
|
10628
10958
|
_leaderTeamName = name;
|
|
@@ -10802,9 +11132,9 @@ The user interacts primarily with the team lead. Your work is coordinated throug
|
|
|
10802
11132
|
|
|
10803
11133
|
// src/swarm/teammateMailbox.ts
|
|
10804
11134
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
10805
|
-
import { join as
|
|
11135
|
+
import { join as join17 } from "node:path";
|
|
10806
11136
|
function getTeamsDir2() {
|
|
10807
|
-
return
|
|
11137
|
+
return join17(process.env.ENGINE_STATE_DIR || ".", "teams");
|
|
10808
11138
|
}
|
|
10809
11139
|
function sanitizePathComponent(s) {
|
|
10810
11140
|
return s.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
@@ -10813,12 +11143,12 @@ function getInboxPath(agentName, teamName) {
|
|
|
10813
11143
|
const team = teamName || "default";
|
|
10814
11144
|
const safeTeam = sanitizePathComponent(team);
|
|
10815
11145
|
const safeAgentName = sanitizePathComponent(agentName);
|
|
10816
|
-
return
|
|
11146
|
+
return join17(getTeamsDir2(), safeTeam, "inboxes", `${safeAgentName}.json`);
|
|
10817
11147
|
}
|
|
10818
11148
|
async function ensureInboxDir(teamName) {
|
|
10819
11149
|
const team = teamName || "default";
|
|
10820
11150
|
const safeTeam = sanitizePathComponent(team);
|
|
10821
|
-
const inboxDir =
|
|
11151
|
+
const inboxDir = join17(getTeamsDir2(), safeTeam, "inboxes");
|
|
10822
11152
|
await mkdir2(inboxDir, { recursive: true });
|
|
10823
11153
|
}
|
|
10824
11154
|
async function sleep4(ms) {
|
|
@@ -10855,7 +11185,7 @@ async function acquireLock(inboxPath) {
|
|
|
10855
11185
|
for (let i = 0; i < LOCK_RETRIES; i++) {
|
|
10856
11186
|
if (await isLockStale(lockPath2)) {
|
|
10857
11187
|
try {
|
|
10858
|
-
await import("node:fs/promises").then((
|
|
11188
|
+
await import("node:fs/promises").then((fs29) => fs29.rm(lockPath2, { force: true }));
|
|
10859
11189
|
} catch {
|
|
10860
11190
|
}
|
|
10861
11191
|
}
|
|
@@ -10863,7 +11193,7 @@ async function acquireLock(inboxPath) {
|
|
|
10863
11193
|
await writeFile2(lockPath2, `${process.pid}-${Date.now()}`, { encoding: "utf-8", flag: "wx" });
|
|
10864
11194
|
return async () => {
|
|
10865
11195
|
try {
|
|
10866
|
-
await import("node:fs/promises").then((
|
|
11196
|
+
await import("node:fs/promises").then((fs29) => fs29.rm(lockPath2, { force: true }));
|
|
10867
11197
|
} catch {
|
|
10868
11198
|
}
|
|
10869
11199
|
};
|
|
@@ -12033,12 +12363,12 @@ Examples:
|
|
|
12033
12363
|
});
|
|
12034
12364
|
|
|
12035
12365
|
// src/tools/msg-husband.ts
|
|
12036
|
-
import
|
|
12037
|
-
import
|
|
12366
|
+
import fs17 from "node:fs";
|
|
12367
|
+
import path19 from "node:path";
|
|
12038
12368
|
function getHusbandFeishuId(workspace) {
|
|
12039
|
-
const contactsPath =
|
|
12369
|
+
const contactsPath = path19.join(workspace, "prompts", "contacts.md");
|
|
12040
12370
|
try {
|
|
12041
|
-
const text =
|
|
12371
|
+
const text = fs17.readFileSync(contactsPath, "utf-8");
|
|
12042
12372
|
const m = text.match(/\|\s*翀哥\s*\|\s*(ou_[a-f0-9]+)\s*\|/);
|
|
12043
12373
|
return m ? m[1] : null;
|
|
12044
12374
|
} catch {
|
|
@@ -12191,8 +12521,8 @@ Examples:
|
|
|
12191
12521
|
if (!to && !resolvedChannelId) {
|
|
12192
12522
|
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 };
|
|
12193
12523
|
}
|
|
12194
|
-
const
|
|
12195
|
-
if (!
|
|
12524
|
+
const fs29 = await import("node:fs");
|
|
12525
|
+
if (!fs29.existsSync(filePath)) {
|
|
12196
12526
|
return { content: `\u53D1\u9001\u5931\u8D25: \u6587\u4EF6\u4E0D\u5B58\u5728 ${filePath}`, isError: true };
|
|
12197
12527
|
}
|
|
12198
12528
|
const toIds = to ? to.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
@@ -12220,7 +12550,7 @@ Examples:
|
|
|
12220
12550
|
md: "text/markdown"
|
|
12221
12551
|
};
|
|
12222
12552
|
const mimeType = mimeTypeMap[ext] || "application/octet-stream";
|
|
12223
|
-
const stat4 =
|
|
12553
|
+
const stat4 = fs29.statSync(filePath);
|
|
12224
12554
|
const sizeMB = stat4.size / 1024 / 1024;
|
|
12225
12555
|
if (sizeMB > 25) {
|
|
12226
12556
|
return { content: `\u53D1\u9001\u5931\u8D25: \u6587\u4EF6 ${sizeMB.toFixed(1)}MB \u8D85\u8FC7 Discord 25MB \u9650\u5236`, isError: true };
|
|
@@ -12249,12 +12579,12 @@ Examples:
|
|
|
12249
12579
|
});
|
|
12250
12580
|
|
|
12251
12581
|
// src/tools/my-eyes.ts
|
|
12252
|
-
import * as
|
|
12253
|
-
import * as
|
|
12582
|
+
import * as fs18 from "node:fs";
|
|
12583
|
+
import * as path20 from "node:path";
|
|
12254
12584
|
function resolveLatestImage(specifiedPath, mediaDir) {
|
|
12255
|
-
if (specifiedPath &&
|
|
12256
|
-
if (!
|
|
12257
|
-
const files =
|
|
12585
|
+
if (specifiedPath && fs18.existsSync(specifiedPath)) return specifiedPath;
|
|
12586
|
+
if (!fs18.existsSync(mediaDir)) return null;
|
|
12587
|
+
const files = fs18.readdirSync(mediaDir).filter((f) => /\.(jpg|jpeg|png|webp|gif|bmp)$/i.test(f)).map((f) => ({ name: f, p: path20.join(mediaDir, f), mtime: fs18.statSync(path20.join(mediaDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
12258
12588
|
return files[0]?.p || null;
|
|
12259
12589
|
}
|
|
12260
12590
|
var MIME_MAP;
|
|
@@ -12299,15 +12629,15 @@ var init_my_eyes = __esm({
|
|
|
12299
12629
|
if (!provider?.streamChat) {
|
|
12300
12630
|
return { content: "Error: provider \u4E0D\u53EF\u7528\u3002", isError: true };
|
|
12301
12631
|
}
|
|
12302
|
-
const mediaDir =
|
|
12632
|
+
const mediaDir = path20.join(ctx.stateDir, "media", "inbound");
|
|
12303
12633
|
const imagePath = resolveLatestImage(args.image_path, mediaDir);
|
|
12304
12634
|
if (!imagePath) {
|
|
12305
12635
|
return { content: "Error: no image found. Provide image_path or ensure media/inbound has images.", isError: true };
|
|
12306
12636
|
}
|
|
12307
12637
|
const rawPrompt = args.prompt?.trim() || "\u63CF\u8FF0\u8FD9\u5F20\u56FE\u7247\u7684\u5185\u5BB9";
|
|
12308
|
-
const ext =
|
|
12638
|
+
const ext = path20.extname(imagePath).toLowerCase();
|
|
12309
12639
|
const mime = MIME_MAP[ext] || "jpeg";
|
|
12310
|
-
const imgB64 =
|
|
12640
|
+
const imgB64 = fs18.readFileSync(imagePath).toString("base64");
|
|
12311
12641
|
const userMsg = {
|
|
12312
12642
|
role: "user",
|
|
12313
12643
|
content: [
|
|
@@ -12342,7 +12672,7 @@ var init_my_eyes = __esm({
|
|
|
12342
12672
|
});
|
|
12343
12673
|
|
|
12344
12674
|
// src/tools/opus-encoder.ts
|
|
12345
|
-
import * as
|
|
12675
|
+
import * as fs19 from "node:fs";
|
|
12346
12676
|
function oggCrc32(buf) {
|
|
12347
12677
|
let crc = 0;
|
|
12348
12678
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -12402,7 +12732,7 @@ async function wavToOggOpusNative(wavPath) {
|
|
|
12402
12732
|
const mod = await import("@discordjs/opus");
|
|
12403
12733
|
const OpusEncoder = mod.OpusEncoder ?? mod.default?.OpusEncoder;
|
|
12404
12734
|
if (!OpusEncoder) throw new Error("@discordjs/opus export shape unexpected");
|
|
12405
|
-
const wav = parseWav(
|
|
12735
|
+
const wav = parseWav(fs19.readFileSync(wavPath));
|
|
12406
12736
|
if (wav.channels !== 1) throw new Error(`unsupported ${wav.channels}ch (need mono)`);
|
|
12407
12737
|
if (!NATIVE_RATES.includes(wav.sampleRate)) throw new Error(`unsupported rate ${wav.sampleRate}`);
|
|
12408
12738
|
if (wav.pcm.length === 0) throw new Error("empty pcm data");
|
|
@@ -12438,7 +12768,7 @@ async function wavToOggOpusNative(wavPath) {
|
|
|
12438
12768
|
}
|
|
12439
12769
|
ogg.page(cur, pageGranule, false, true);
|
|
12440
12770
|
const oggPath = wavPath.replace(/\.wav$/, ".ogg");
|
|
12441
|
-
|
|
12771
|
+
fs19.writeFileSync(oggPath, ogg.finish());
|
|
12442
12772
|
return oggPath;
|
|
12443
12773
|
}
|
|
12444
12774
|
var FRAME_MS, PRESKIP_48K, OPUS_RATE, NATIVE_RATES, BITRATE, CRC_TABLE, OggWriter;
|
|
@@ -12518,8 +12848,8 @@ var init_voice_chat_tts_daemon = __esm({
|
|
|
12518
12848
|
import { execFile as execFile2 } from "node:child_process";
|
|
12519
12849
|
import { createInterface as createInterface2 } from "node:readline";
|
|
12520
12850
|
import { promisify } from "node:util";
|
|
12521
|
-
import * as
|
|
12522
|
-
import * as
|
|
12851
|
+
import * as fs20 from "node:fs";
|
|
12852
|
+
import * as path21 from "node:path";
|
|
12523
12853
|
import * as os3 from "node:os";
|
|
12524
12854
|
function resolvePython(configuredPath) {
|
|
12525
12855
|
if (configuredPath) {
|
|
@@ -12555,8 +12885,8 @@ async function ttsCosyvoice(text, apiKey, model, voice, workspaceId, instruction
|
|
|
12555
12885
|
}
|
|
12556
12886
|
async function ttsCosyvoiceStream(text, cfg, onChunk) {
|
|
12557
12887
|
const { apiKey, model, voice, workspaceId, instruction } = cfg;
|
|
12558
|
-
|
|
12559
|
-
const output =
|
|
12888
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
12889
|
+
const output = path21.join(VOICE_DIR, `tts_${Date.now()}.wav`);
|
|
12560
12890
|
const script = `
|
|
12561
12891
|
import sys, json, base64, threading
|
|
12562
12892
|
import dashscope
|
|
@@ -12641,7 +12971,7 @@ print('EOS')
|
|
|
12641
12971
|
header.writeUInt16LE(16, 34);
|
|
12642
12972
|
header.write("data", 36);
|
|
12643
12973
|
header.writeUInt32LE(pcm.length, 40);
|
|
12644
|
-
|
|
12974
|
+
fs20.writeFileSync(output, Buffer.concat([header, pcm]));
|
|
12645
12975
|
return output;
|
|
12646
12976
|
}
|
|
12647
12977
|
async function ttsQwen3Local(text, cfg, onChunk) {
|
|
@@ -12693,14 +13023,14 @@ async function ttsQwen3Opus(text, cfg) {
|
|
|
12693
13023
|
const ogg = Buffer.from(await res.arrayBuffer());
|
|
12694
13024
|
if (ogg.length < 20) throw new Error("qwen3-3060 opus: empty output");
|
|
12695
13025
|
const durationMs = parseInt(res.headers.get("x-duration-ms") || "0", 10);
|
|
12696
|
-
|
|
12697
|
-
const oggPath =
|
|
12698
|
-
|
|
13026
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13027
|
+
const oggPath = path21.join(VOICE_DIR, `tts_${Date.now()}.ogg`);
|
|
13028
|
+
fs20.writeFileSync(oggPath, ogg);
|
|
12699
13029
|
return { oggPath, durationMs };
|
|
12700
13030
|
}
|
|
12701
13031
|
async function ttsGptsovits(text) {
|
|
12702
|
-
|
|
12703
|
-
const output =
|
|
13032
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13033
|
+
const output = path21.join(VOICE_DIR, `tts_${Date.now()}.wav`);
|
|
12704
13034
|
const params = new URLSearchParams({
|
|
12705
13035
|
text,
|
|
12706
13036
|
text_language: "zh",
|
|
@@ -12711,12 +13041,12 @@ async function ttsGptsovits(text) {
|
|
|
12711
13041
|
const res = await fetch(`${GPTSOVITS_API}/?${params}`);
|
|
12712
13042
|
if (!res.ok) throw new Error(`GPT-SoVITS API ${res.status}`);
|
|
12713
13043
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
12714
|
-
|
|
13044
|
+
fs20.writeFileSync(output, buf);
|
|
12715
13045
|
return output;
|
|
12716
13046
|
}
|
|
12717
13047
|
async function ttsEdge(text) {
|
|
12718
|
-
|
|
12719
|
-
const output =
|
|
13048
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13049
|
+
const output = path21.join(VOICE_DIR, `tts_${Date.now()}.mp3`);
|
|
12720
13050
|
const script = `
|
|
12721
13051
|
import asyncio, edge_tts, sys
|
|
12722
13052
|
async def main():
|
|
@@ -12743,11 +13073,11 @@ async function toWav24kWithDuration(audioPath) {
|
|
|
12743
13073
|
"pcm_s16le",
|
|
12744
13074
|
wavPath
|
|
12745
13075
|
], { timeout: 3e4 });
|
|
12746
|
-
if (!
|
|
13076
|
+
if (!fs20.existsSync(wavPath) || fs20.statSync(wavPath).size < 44) {
|
|
12747
13077
|
throw new Error("toWav24k produced empty output");
|
|
12748
13078
|
}
|
|
12749
13079
|
try {
|
|
12750
|
-
|
|
13080
|
+
fs20.unlinkSync(audioPath);
|
|
12751
13081
|
} catch {
|
|
12752
13082
|
}
|
|
12753
13083
|
}
|
|
@@ -12778,7 +13108,7 @@ async function compressWav(wavPath) {
|
|
|
12778
13108
|
"+faststart",
|
|
12779
13109
|
m4aPath
|
|
12780
13110
|
], { timeout: 3e4 });
|
|
12781
|
-
|
|
13111
|
+
fs20.unlinkSync(wavPath);
|
|
12782
13112
|
return m4aPath;
|
|
12783
13113
|
} catch {
|
|
12784
13114
|
return wavPath;
|
|
@@ -12805,10 +13135,10 @@ async function wavToOggOpus(wavPath) {
|
|
|
12805
13135
|
oggPath
|
|
12806
13136
|
], { timeout: 3e4 });
|
|
12807
13137
|
}
|
|
12808
|
-
if (!
|
|
13138
|
+
if (!fs20.existsSync(oggPath) || fs20.statSync(oggPath).size < 20) {
|
|
12809
13139
|
throw new Error("ogg/opus encode produced empty output");
|
|
12810
13140
|
}
|
|
12811
|
-
|
|
13141
|
+
fs20.unlinkSync(wavPath);
|
|
12812
13142
|
return oggPath;
|
|
12813
13143
|
}
|
|
12814
13144
|
async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
@@ -12825,8 +13155,8 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12825
13155
|
const pcmChunks = [];
|
|
12826
13156
|
await ttsQwen3Local(text, { url: vc.url, voice: vc.voice, lang: vc.lang }, (pcm2) => pcmChunks.push(pcm2));
|
|
12827
13157
|
const pcm = Buffer.concat(pcmChunks);
|
|
12828
|
-
|
|
12829
|
-
const wavPath =
|
|
13158
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13159
|
+
const wavPath = path21.join(VOICE_DIR, `tts_mc_${Date.now()}.wav`);
|
|
12830
13160
|
const header = Buffer.alloc(44);
|
|
12831
13161
|
header.write("RIFF", 0);
|
|
12832
13162
|
header.writeUInt32LE(36 + pcm.length, 4);
|
|
@@ -12841,7 +13171,7 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12841
13171
|
header.writeUInt16LE(16, 34);
|
|
12842
13172
|
header.write("data", 36);
|
|
12843
13173
|
header.writeUInt32LE(pcm.length, 40);
|
|
12844
|
-
|
|
13174
|
+
fs20.writeFileSync(wavPath, Buffer.concat([header, pcm]));
|
|
12845
13175
|
audioPath = wavPath;
|
|
12846
13176
|
}
|
|
12847
13177
|
} else if (actualEngine === "cosyvoice" && vc?.apiKey) {
|
|
@@ -12855,7 +13185,7 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12855
13185
|
} catch (e) {
|
|
12856
13186
|
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 };
|
|
12857
13187
|
}
|
|
12858
|
-
if (!audioPath || !
|
|
13188
|
+
if (!audioPath || !fs20.existsSync(audioPath)) {
|
|
12859
13189
|
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 };
|
|
12860
13190
|
}
|
|
12861
13191
|
if (audioPath.endsWith(".wav")) {
|
|
@@ -12865,21 +13195,21 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12865
13195
|
console.warn(`[my-voice:multaca] opus encode failed (${e.message}), attaching wav`);
|
|
12866
13196
|
}
|
|
12867
13197
|
}
|
|
12868
|
-
const ext =
|
|
12869
|
-
const sizeKB =
|
|
13198
|
+
const ext = path21.extname(audioPath).toLowerCase();
|
|
13199
|
+
const sizeKB = fs20.statSync(audioPath).size / 1024;
|
|
12870
13200
|
const voiceFile = `voice_${Date.now()}${ext}`;
|
|
12871
|
-
const cwdCopy =
|
|
13201
|
+
const cwdCopy = path21.join(process.cwd(), voiceFile);
|
|
12872
13202
|
try {
|
|
12873
|
-
|
|
13203
|
+
fs20.copyFileSync(audioPath, cwdCopy);
|
|
12874
13204
|
} catch (e) {
|
|
12875
13205
|
try {
|
|
12876
|
-
|
|
13206
|
+
fs20.unlinkSync(audioPath);
|
|
12877
13207
|
} catch {
|
|
12878
13208
|
}
|
|
12879
13209
|
return { content: `\u8BED\u97F3\u6302\u8F7D\u5931\u8D25\uFF08\u62F7\u8D1D\u5230\u5DE5\u4F5C\u76EE\u5F55\uFF09\uFF1A${e.message}`, isError: true };
|
|
12880
13210
|
}
|
|
12881
13211
|
try {
|
|
12882
|
-
|
|
13212
|
+
fs20.unlinkSync(audioPath);
|
|
12883
13213
|
} catch {
|
|
12884
13214
|
}
|
|
12885
13215
|
const content = opts.caption || `\u{1F399}\uFE0F \u8BED\u97F3\u6D88\u606F\uFF08${text.length} \u5B57\uFF09`;
|
|
@@ -12908,13 +13238,13 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12908
13238
|
}
|
|
12909
13239
|
if (!ok) throw new Error(`unexpected CLI output: ${String(stdout).slice(0, 200)}`);
|
|
12910
13240
|
try {
|
|
12911
|
-
|
|
13241
|
+
fs20.unlinkSync(cwdCopy);
|
|
12912
13242
|
} catch {
|
|
12913
13243
|
}
|
|
12914
13244
|
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)` };
|
|
12915
13245
|
} catch (e) {
|
|
12916
13246
|
try {
|
|
12917
|
-
|
|
13247
|
+
fs20.unlinkSync(cwdCopy);
|
|
12918
13248
|
} catch {
|
|
12919
13249
|
}
|
|
12920
13250
|
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 };
|
|
@@ -12929,7 +13259,7 @@ var init_my_voice = __esm({
|
|
|
12929
13259
|
init_opus_encoder();
|
|
12930
13260
|
init_voice_chat_tts_daemon();
|
|
12931
13261
|
execFileAsync = promisify(execFile2);
|
|
12932
|
-
VOICE_DIR =
|
|
13262
|
+
VOICE_DIR = path21.join(os3.tmpdir(), "engine-voice");
|
|
12933
13263
|
_pyCache = null;
|
|
12934
13264
|
GPTSOVITS_API = "http://127.0.0.1:9880";
|
|
12935
13265
|
GPTSOVITS_REF_WAV = "/home/chong/voice/ref/shanshan_ref_v2.wav";
|
|
@@ -13028,8 +13358,8 @@ var init_my_voice = __esm({
|
|
|
13028
13358
|
const pcmChunks = [];
|
|
13029
13359
|
await ttsQwen3Local(text, { url: vc.url, voice: vc.voice, lang: vc.lang }, (pcm2) => pcmChunks.push(pcm2));
|
|
13030
13360
|
const pcm = Buffer.concat(pcmChunks);
|
|
13031
|
-
|
|
13032
|
-
const wavPath =
|
|
13361
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13362
|
+
const wavPath = path21.join(VOICE_DIR, `tts_${Date.now()}.wav`);
|
|
13033
13363
|
const header = Buffer.alloc(44);
|
|
13034
13364
|
header.write("RIFF", 0);
|
|
13035
13365
|
header.writeUInt32LE(36 + pcm.length, 4);
|
|
@@ -13044,7 +13374,7 @@ var init_my_voice = __esm({
|
|
|
13044
13374
|
header.writeUInt16LE(16, 34);
|
|
13045
13375
|
header.write("data", 36);
|
|
13046
13376
|
header.writeUInt32LE(pcm.length, 40);
|
|
13047
|
-
|
|
13377
|
+
fs20.writeFileSync(wavPath, Buffer.concat([header, pcm]));
|
|
13048
13378
|
audioPath = wavPath;
|
|
13049
13379
|
}
|
|
13050
13380
|
} catch (e) {
|
|
@@ -13075,10 +13405,10 @@ var init_my_voice = __esm({
|
|
|
13075
13405
|
audioPath = await compressWav(audioPath);
|
|
13076
13406
|
}
|
|
13077
13407
|
}
|
|
13078
|
-
const ext =
|
|
13408
|
+
const ext = path21.extname(audioPath).toLowerCase();
|
|
13079
13409
|
const mimeMap = { ".mp3": "audio/mpeg", ".wav": "audio/wav", ".m4a": "audio/mp4", ".ogg": "audio/ogg", ".silk": "audio/silk" };
|
|
13080
13410
|
const mimeType = mimeMap[ext] || "audio/mpeg";
|
|
13081
|
-
const sizeKB =
|
|
13411
|
+
const sizeKB = fs20.statSync(audioPath).size / 1024;
|
|
13082
13412
|
try {
|
|
13083
13413
|
await mgr.sendFile(resolvedChannel, target, caption, {
|
|
13084
13414
|
path: audioPath,
|
|
@@ -13087,7 +13417,7 @@ var init_my_voice = __esm({
|
|
|
13087
13417
|
...voiceDurationSec !== void 0 ? { voiceDurationSec } : {}
|
|
13088
13418
|
});
|
|
13089
13419
|
try {
|
|
13090
|
-
|
|
13420
|
+
fs20.unlinkSync(audioPath);
|
|
13091
13421
|
} catch {
|
|
13092
13422
|
}
|
|
13093
13423
|
return { content: `Voice sent! (${actualEngine}, ${sizeKB.toFixed(0)}KB, ${resolvedChannel})` };
|
|
@@ -13104,8 +13434,8 @@ var init_my_voice = __esm({
|
|
|
13104
13434
|
});
|
|
13105
13435
|
|
|
13106
13436
|
// src/tools/my-selfie.ts
|
|
13107
|
-
import * as
|
|
13108
|
-
import * as
|
|
13437
|
+
import * as fs21 from "node:fs";
|
|
13438
|
+
import * as path22 from "node:path";
|
|
13109
13439
|
function getProxyDispatcher2() {
|
|
13110
13440
|
const cfg = liveConfig.all();
|
|
13111
13441
|
const proxy = cfg.providers?.xai?.proxy;
|
|
@@ -13421,12 +13751,12 @@ var init_my_selfie = __esm({
|
|
|
13421
13751
|
const REFERENCES = getReferences(ctx);
|
|
13422
13752
|
const refName = args.reference || "default";
|
|
13423
13753
|
const refEntry = REFERENCES.find((r) => r.name === refName) || REFERENCES[0];
|
|
13424
|
-
const refPath =
|
|
13425
|
-
if (provider !== "autodl" && !
|
|
13754
|
+
const refPath = path22.join(ctx.workspace, refEntry.p);
|
|
13755
|
+
if (provider !== "autodl" && !fs21.existsSync(refPath)) {
|
|
13426
13756
|
return { content: `Error: reference image not found at ${refPath}`, isError: true };
|
|
13427
13757
|
}
|
|
13428
13758
|
const resolution = args.resolution || DEFAULT_RESOLUTION;
|
|
13429
|
-
const refB64 =
|
|
13759
|
+
const refB64 = fs21.existsSync(refPath) ? fs21.readFileSync(refPath).toString("base64") : "";
|
|
13430
13760
|
let imageBuffer;
|
|
13431
13761
|
try {
|
|
13432
13762
|
if (provider === "autodl") {
|
|
@@ -13441,11 +13771,11 @@ var init_my_selfie = __esm({
|
|
|
13441
13771
|
} catch (err) {
|
|
13442
13772
|
return { content: `Selfie generation failed: ${err.message}`, isError: true };
|
|
13443
13773
|
}
|
|
13444
|
-
const imagesDir =
|
|
13445
|
-
if (!
|
|
13774
|
+
const imagesDir = path22.join(ctx.workspace, "images");
|
|
13775
|
+
if (!fs21.existsSync(imagesDir)) fs21.mkdirSync(imagesDir, { recursive: true });
|
|
13446
13776
|
const filename = `selfie_${Date.now()}.jpg`;
|
|
13447
|
-
const outputPath =
|
|
13448
|
-
|
|
13777
|
+
const outputPath = path22.join(imagesDir, filename);
|
|
13778
|
+
fs21.writeFileSync(outputPath, imageBuffer);
|
|
13449
13779
|
const mgr = ctx.channelManager;
|
|
13450
13780
|
if (mgr) {
|
|
13451
13781
|
const resolvedChannel = ctx.channel || "feishu";
|
|
@@ -13456,11 +13786,11 @@ var init_my_selfie = __esm({
|
|
|
13456
13786
|
mimeType: "image/jpeg"
|
|
13457
13787
|
});
|
|
13458
13788
|
} catch (err) {
|
|
13459
|
-
return { content: `Selfie generated but send failed: ${err.message}. Image: ${
|
|
13789
|
+
return { content: `Selfie generated but send failed: ${err.message}. Image: ${path22.resolve(outputPath)}`, isError: false };
|
|
13460
13790
|
}
|
|
13461
13791
|
return { content: `Selfie sent! Mode: ${mode}, Provider: ${provider}, Ref: ${refEntry.name}` };
|
|
13462
13792
|
}
|
|
13463
|
-
return { content: `Selfie generated! Mode: ${mode}, Ref: ${refEntry.name}. Image: ${
|
|
13793
|
+
return { content: `Selfie generated! Mode: ${mode}, Ref: ${refEntry.name}. Image: ${path22.resolve(outputPath)}` };
|
|
13464
13794
|
},
|
|
13465
13795
|
isConcurrencySafe: () => false,
|
|
13466
13796
|
interruptBehavior: () => "block",
|
|
@@ -13555,88 +13885,6 @@ var init_body_move = __esm({
|
|
|
13555
13885
|
}
|
|
13556
13886
|
});
|
|
13557
13887
|
|
|
13558
|
-
// src/calendar/db.ts
|
|
13559
|
-
import * as path21 from "node:path";
|
|
13560
|
-
import * as fs20 from "node:fs";
|
|
13561
|
-
import { createRequire as createRequire2 } from "node:module";
|
|
13562
|
-
function getSqlite() {
|
|
13563
|
-
if (!_sqlite) _sqlite = createRequire2(import.meta.url)("node:sqlite");
|
|
13564
|
-
return _sqlite;
|
|
13565
|
-
}
|
|
13566
|
-
function openDb(workspace) {
|
|
13567
|
-
const dir = path21.join(workspace, ".calendar");
|
|
13568
|
-
fs20.mkdirSync(dir, { recursive: true });
|
|
13569
|
-
const dbPath = path21.join(dir, "calendar.db");
|
|
13570
|
-
const db = new DatabaseSync(dbPath);
|
|
13571
|
-
db.exec("PRAGMA journal_mode=WAL");
|
|
13572
|
-
db.exec(`CREATE TABLE IF NOT EXISTS events (
|
|
13573
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
13574
|
-
type TEXT NOT NULL,
|
|
13575
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
13576
|
-
event TEXT NOT NULL,
|
|
13577
|
-
day TEXT,
|
|
13578
|
-
time TEXT,
|
|
13579
|
-
date_str TEXT,
|
|
13580
|
-
created_at TEXT NOT NULL,
|
|
13581
|
-
done_at TEXT,
|
|
13582
|
-
archived_at TEXT
|
|
13583
|
-
)`);
|
|
13584
|
-
migrate(db);
|
|
13585
|
-
return db;
|
|
13586
|
-
}
|
|
13587
|
-
function migrate(db) {
|
|
13588
|
-
const cols = new Set(
|
|
13589
|
-
db.prepare("PRAGMA table_info(events)").all().map((r) => r.name)
|
|
13590
|
-
);
|
|
13591
|
-
if (!cols.has("remind_before_min")) {
|
|
13592
|
-
db.exec("ALTER TABLE events ADD COLUMN remind_before_min INTEGER DEFAULT 60");
|
|
13593
|
-
}
|
|
13594
|
-
if (!cols.has("remind_at")) {
|
|
13595
|
-
db.exec("ALTER TABLE events ADD COLUMN remind_at TEXT");
|
|
13596
|
-
}
|
|
13597
|
-
if (!cols.has("reminded")) {
|
|
13598
|
-
db.exec("ALTER TABLE events ADD COLUMN reminded INTEGER DEFAULT 0");
|
|
13599
|
-
}
|
|
13600
|
-
if (!cols.has("time_exact")) {
|
|
13601
|
-
db.exec("ALTER TABLE events ADD COLUMN time_exact TEXT");
|
|
13602
|
-
}
|
|
13603
|
-
if (!cols.has("start_time")) {
|
|
13604
|
-
db.exec("ALTER TABLE events ADD COLUMN start_time TEXT");
|
|
13605
|
-
}
|
|
13606
|
-
if (!cols.has("duration_min")) {
|
|
13607
|
-
db.exec("ALTER TABLE events ADD COLUMN duration_min INTEGER");
|
|
13608
|
-
}
|
|
13609
|
-
if (!cols.has("created_channel")) {
|
|
13610
|
-
db.exec("ALTER TABLE events ADD COLUMN created_channel TEXT");
|
|
13611
|
-
}
|
|
13612
|
-
if (!cols.has("created_channel_target")) {
|
|
13613
|
-
db.exec("ALTER TABLE events ADD COLUMN created_channel_target TEXT");
|
|
13614
|
-
}
|
|
13615
|
-
if (!cols.has("repeat_type")) {
|
|
13616
|
-
db.exec("ALTER TABLE events ADD COLUMN repeat_type TEXT DEFAULT 'once'");
|
|
13617
|
-
}
|
|
13618
|
-
if (!cols.has("doc_path")) {
|
|
13619
|
-
db.exec("ALTER TABLE events ADD COLUMN doc_path TEXT");
|
|
13620
|
-
}
|
|
13621
|
-
}
|
|
13622
|
-
var _sqlite, DatabaseSync, TZ_OFFSET_MS;
|
|
13623
|
-
var init_db = __esm({
|
|
13624
|
-
"src/calendar/db.ts"() {
|
|
13625
|
-
"use strict";
|
|
13626
|
-
_sqlite = null;
|
|
13627
|
-
DatabaseSync = new Proxy(function() {
|
|
13628
|
-
}, {
|
|
13629
|
-
construct(_t, args) {
|
|
13630
|
-
return new (getSqlite()).DatabaseSync(...args);
|
|
13631
|
-
},
|
|
13632
|
-
get(_t, prop) {
|
|
13633
|
-
return getSqlite().DatabaseSync[prop];
|
|
13634
|
-
}
|
|
13635
|
-
});
|
|
13636
|
-
TZ_OFFSET_MS = 8 * 60 * 60 * 1e3;
|
|
13637
|
-
}
|
|
13638
|
-
});
|
|
13639
|
-
|
|
13640
13888
|
// src/calendar/helpers.ts
|
|
13641
13889
|
function nowIso() {
|
|
13642
13890
|
return new Date(Date.now() + TZ_OFFSET_MS2 - (/* @__PURE__ */ new Date()).getTimezoneOffset() * 6e4).toISOString().replace("Z", "+08:00");
|
|
@@ -13862,14 +14110,14 @@ function fmtEnd(start, durationMin) {
|
|
|
13862
14110
|
const total = hh * 60 + mm + durationMin;
|
|
13863
14111
|
return `${Math.floor(total / 60)}:${String(total % 60).padStart(2, "0")}`;
|
|
13864
14112
|
}
|
|
13865
|
-
function addWeekly(
|
|
14113
|
+
function addWeekly(db2, args) {
|
|
13866
14114
|
const { day, event } = args;
|
|
13867
14115
|
if (!WEEKDAYS2.includes(day)) return `\u9519\u8BEF: \u661F\u671F\u5FC5\u987B\u662F ${WEEKDAYS2.join("/")}`;
|
|
13868
14116
|
if (!args.time) return `\u9519\u8BEF: \u5468\u671F\u65E5\u7A0B\u5FC5\u987B\u586B start_time\uFF08\u5982 time='14:00'\uFF09`;
|
|
13869
14117
|
if (!args.duration) return `\u9519\u8BEF: \u5468\u671F\u65E5\u7A0B\u5FC5\u987B\u586B duration\uFF08\u5982 duration='1h'\uFF09`;
|
|
13870
14118
|
const durationMin = parseDuration(args.duration);
|
|
13871
14119
|
if (!durationMin) return `\u9519\u8BEF: duration \u683C\u5F0F\u4E0D\u5BF9\uFF08\u5982 '30m' / '1h'\uFF09`;
|
|
13872
|
-
const conflictRows =
|
|
14120
|
+
const conflictRows = db2.prepare(
|
|
13873
14121
|
"SELECT * FROM events WHERE status='pending' AND type='weekly' AND day=?"
|
|
13874
14122
|
).all(day);
|
|
13875
14123
|
const conflict = checkScheduleConflict(conflictRows, args.time, durationMin);
|
|
@@ -13884,16 +14132,16 @@ function addWeekly(db, args) {
|
|
|
13884
14132
|
else remindMin = parseInt(v) || 60;
|
|
13885
14133
|
}
|
|
13886
14134
|
const remindAt = computeWeeklyRemindAt(day, args.time, remindMin);
|
|
13887
|
-
const r =
|
|
14135
|
+
const r = db2.prepare(
|
|
13888
14136
|
`INSERT INTO events (type,status,event,day,time,start_time,duration_min,remind_before_min,remind_at,reminded,created_at,created_channel,created_channel_target)
|
|
13889
14137
|
VALUES ('weekly','pending',?,?,?,?,?,?,?,?,?,?,?)`
|
|
13890
14138
|
).run(event, day, args.time, args.time, durationMin, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
|
|
13891
14139
|
return `#${r.lastInsertRowid} \u5DF2\u6DFB\u52A0: [\u6BCF\u5468] ${day} ${args.time} (${durationMin}min) ${event} (\u63D0\u524D${remindMin}min\u63D0\u9192)`;
|
|
13892
14140
|
}
|
|
13893
|
-
function addDaily(
|
|
14141
|
+
function addDaily(db2, args) {
|
|
13894
14142
|
const { time, event, repeatType } = args;
|
|
13895
14143
|
if (!time) return `\u9519\u8BEF: \u6BCF\u65E5\u4EFB\u52A1\u5FC5\u987B\u586B time\uFF08\u5982 time='23:00'\uFF09`;
|
|
13896
|
-
const dailyRows =
|
|
14144
|
+
const dailyRows = db2.prepare(
|
|
13897
14145
|
"SELECT * FROM events WHERE status='pending' AND type='daily'"
|
|
13898
14146
|
).all();
|
|
13899
14147
|
const [hh, mm] = time.split(":").map(Number);
|
|
@@ -13915,21 +14163,21 @@ function addDaily(db, args) {
|
|
|
13915
14163
|
}
|
|
13916
14164
|
const remindAt = repeatType === "daily" ? computeDailyRemindAt(time, remindMin) : computeWeekdaysRemindAt(time, remindMin);
|
|
13917
14165
|
if (!remindAt) return `\u9519\u8BEF: \u65E0\u6CD5\u8BA1\u7B97 remind_at`;
|
|
13918
|
-
const r =
|
|
14166
|
+
const r = db2.prepare(
|
|
13919
14167
|
`INSERT INTO events (type,status,event,time,start_time,repeat_type,remind_before_min,remind_at,reminded,created_at,created_channel,created_channel_target)
|
|
13920
14168
|
VALUES ('daily','pending',?,?,?,?,?,?,?,?,?,?)`
|
|
13921
14169
|
).run(event, time, time, repeatType, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
|
|
13922
14170
|
const label = repeatType === "daily" ? "\u6BCF\u5929" : "\u5DE5\u4F5C\u65E5";
|
|
13923
14171
|
return `#${r.lastInsertRowid} \u5DF2\u6DFB\u52A0: [${label}] ${time} ${event} (\u63D0\u524D${remindMin}min\u63D0\u9192)`;
|
|
13924
14172
|
}
|
|
13925
|
-
function addDate(
|
|
14173
|
+
function addDate(db2, args) {
|
|
13926
14174
|
const { dateStr, event } = args;
|
|
13927
14175
|
if (!args.time) return `\u9519\u8BEF: \u4E00\u6B21\u6027\u65E5\u7A0B\u5FC5\u987B\u586B start_time\uFF08\u5982 time='14:00'\uFF09`;
|
|
13928
14176
|
if (!args.duration) return `\u9519\u8BEF: \u4E00\u6B21\u6027\u65E5\u7A0B\u5FC5\u987B\u586B duration\uFF08\u5982 duration='1h'\uFF09`;
|
|
13929
14177
|
const durationMin = parseDuration(args.duration);
|
|
13930
14178
|
if (!durationMin) return `\u9519\u8BEF: duration \u683C\u5F0F\u4E0D\u5BF9\uFF08\u5982 '30m' / '1h'\uFF09`;
|
|
13931
14179
|
const todayWeekday = getTodayWeekday();
|
|
13932
|
-
const dateRows =
|
|
14180
|
+
const dateRows = db2.prepare(
|
|
13933
14181
|
"SELECT * FROM events WHERE status='pending' AND type='date' AND date_str=?"
|
|
13934
14182
|
).all(dateStr);
|
|
13935
14183
|
const parsed = parseDateRange(dateStr);
|
|
@@ -13939,7 +14187,7 @@ function addDate(db, args) {
|
|
|
13939
14187
|
const year = now.getUTCFullYear();
|
|
13940
14188
|
const d = new Date(Date.UTC(year, parsed.month - 1, parsed.dStart));
|
|
13941
14189
|
const weekday = WEEKDAYS2[d.getUTCDay() === 0 ? 6 : d.getUTCDay() - 1];
|
|
13942
|
-
weeklyRows =
|
|
14190
|
+
weeklyRows = db2.prepare(
|
|
13943
14191
|
"SELECT * FROM events WHERE status='pending' AND type='weekly' AND day=?"
|
|
13944
14192
|
).all(weekday);
|
|
13945
14193
|
}
|
|
@@ -13956,13 +14204,13 @@ function addDate(db, args) {
|
|
|
13956
14204
|
else remindMin = parseInt(v) || 60;
|
|
13957
14205
|
}
|
|
13958
14206
|
const remindAt = computeRemindAt(dateStr, args.time, remindMin);
|
|
13959
|
-
const r =
|
|
14207
|
+
const r = db2.prepare(
|
|
13960
14208
|
`INSERT INTO events (type,status,event,date_str,time,start_time,duration_min,remind_before_min,remind_at,reminded,created_at,created_channel,created_channel_target)
|
|
13961
14209
|
VALUES ('date','pending',?,?,?,?,?,?,?,?,?,?,?)`
|
|
13962
14210
|
).run(event, dateStr, args.time, args.time, durationMin, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
|
|
13963
14211
|
return `#${r.lastInsertRowid} \u5DF2\u6DFB\u52A0: [${dateStr} ${args.time} (${durationMin}min)] ${event} (\u63D0\u524D${remindMin}min\u63D0\u9192)`;
|
|
13964
14212
|
}
|
|
13965
|
-
function addBatch(
|
|
14213
|
+
function addBatch(db2, args) {
|
|
13966
14214
|
if (!args.time) return `\u9519\u8BEF: \u6279\u91CF\u6DFB\u52A0\u5FC5\u987B\u586B time\uFF08\u5982 time='14:00'\uFF09`;
|
|
13967
14215
|
if (!args.duration) return `\u9519\u8BEF: \u6279\u91CF\u6DFB\u52A0\u5FC5\u987B\u586B duration\uFF08\u5982 duration='1h'\uFF09`;
|
|
13968
14216
|
const durationMin = parseDuration(args.duration);
|
|
@@ -13979,7 +14227,7 @@ function addBatch(db, args) {
|
|
|
13979
14227
|
const ok = [];
|
|
13980
14228
|
const skipped = [];
|
|
13981
14229
|
for (const dateStr of dates) {
|
|
13982
|
-
const dateRows =
|
|
14230
|
+
const dateRows = db2.prepare(
|
|
13983
14231
|
"SELECT * FROM events WHERE status='pending' AND type='date' AND date_str=?"
|
|
13984
14232
|
).all(dateStr);
|
|
13985
14233
|
const parsed = parseDateRange(dateStr);
|
|
@@ -13989,7 +14237,7 @@ function addBatch(db, args) {
|
|
|
13989
14237
|
const year = now.getUTCFullYear();
|
|
13990
14238
|
const d = new Date(Date.UTC(year, parsed.month - 1, parsed.dStart));
|
|
13991
14239
|
const weekday = WEEKDAYS2[d.getUTCDay() === 0 ? 6 : d.getUTCDay() - 1];
|
|
13992
|
-
weeklyRows =
|
|
14240
|
+
weeklyRows = db2.prepare(
|
|
13993
14241
|
"SELECT * FROM events WHERE status='pending' AND type='weekly' AND day=?"
|
|
13994
14242
|
).all(weekday);
|
|
13995
14243
|
}
|
|
@@ -14000,7 +14248,7 @@ function addBatch(db, args) {
|
|
|
14000
14248
|
continue;
|
|
14001
14249
|
}
|
|
14002
14250
|
const remindAt = computeRemindAt(dateStr, args.time, remindMin);
|
|
14003
|
-
const r =
|
|
14251
|
+
const r = db2.prepare(
|
|
14004
14252
|
`INSERT INTO events (type,status,event,date_str,time,start_time,duration_min,remind_before_min,remind_at,reminded,created_at,created_channel,created_channel_target)
|
|
14005
14253
|
VALUES ('date','pending',?,?,?,?,?,?,?,?,?,?,?)`
|
|
14006
14254
|
).run(args.event, dateStr, args.time, args.time, durationMin, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
|
|
@@ -14017,7 +14265,7 @@ ${skipped.map((s) => ` ${s}`).join("\n")}`;
|
|
|
14017
14265
|
}
|
|
14018
14266
|
return result2;
|
|
14019
14267
|
}
|
|
14020
|
-
function addTask(
|
|
14268
|
+
function addTask(db2, args) {
|
|
14021
14269
|
const { dateStr, timeExact, event, docPath } = args;
|
|
14022
14270
|
if (!docPath || !docPath.trim()) {
|
|
14023
14271
|
return `\u274C \u521B\u5EFA\u5931\u8D25\uFF1Aadd-task \u5FC5\u987B\u4F20 doc_path\u3002
|
|
@@ -14048,12 +14296,12 @@ function addTask(db, args) {
|
|
|
14048
14296
|
else if (v.endsWith("h")) remindMin = parseInt(v.slice(0, -1)) * 60;
|
|
14049
14297
|
else remindMin = parseInt(v) || 60;
|
|
14050
14298
|
}
|
|
14051
|
-
const taskRows =
|
|
14299
|
+
const taskRows = db2.prepare(
|
|
14052
14300
|
"SELECT * FROM events WHERE status='pending' AND type='task' AND date_str=?"
|
|
14053
14301
|
).all(dateStr);
|
|
14054
14302
|
const prox = checkTaskProximity(taskRows, timeExact);
|
|
14055
14303
|
const remindAt = computeRemindAt(dateStr, timeExact, remindMin);
|
|
14056
|
-
const r =
|
|
14304
|
+
const r = db2.prepare(
|
|
14057
14305
|
`INSERT INTO events (type,status,event,date_str,time_exact,remind_before_min,remind_at,reminded,created_at,created_channel,created_channel_target,doc_path)
|
|
14058
14306
|
VALUES ('task','pending',?,?,?,?,?,?,?,?,?,?)`
|
|
14059
14307
|
).run(event, dateStr, timeExact, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null, docPath);
|
|
@@ -14065,9 +14313,9 @@ function addTask(db, args) {
|
|
|
14065
14313
|
}
|
|
14066
14314
|
return msg2;
|
|
14067
14315
|
}
|
|
14068
|
-
function reschedule(
|
|
14316
|
+
function reschedule(db2, args) {
|
|
14069
14317
|
const { id, dateStr, timeExact } = args;
|
|
14070
|
-
const row =
|
|
14318
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=?").get(id);
|
|
14071
14319
|
if (!row) return `\u672A\u627E\u5230\u4E8B\u4EF6 #${id}`;
|
|
14072
14320
|
if (row.type !== "task") return `#${id} \u4E0D\u662F task \u7C7B\u578B\uFF08${row.type}\uFF09\uFF0Creschedule \u4EC5\u652F\u6301 task`;
|
|
14073
14321
|
let remindMin = row.remind_before_min || 60;
|
|
@@ -14078,12 +14326,12 @@ function reschedule(db, args) {
|
|
|
14078
14326
|
else remindMin = parseInt(v) || remindMin;
|
|
14079
14327
|
}
|
|
14080
14328
|
const remindAt = computeRemindAt(dateStr, timeExact, remindMin);
|
|
14081
|
-
|
|
14329
|
+
db2.prepare("UPDATE events SET date_str=?, time_exact=?, remind_before_min=?, remind_at=?, reminded=0 WHERE id=?").run(dateStr, timeExact, remindMin, remindAt, id);
|
|
14082
14330
|
return `#${id} \u5DF2\u6539\u671F: [${dateStr} ${timeExact}] ${row.event} (\u63D0\u524D${remindMin}min\u63D0\u9192)`;
|
|
14083
14331
|
}
|
|
14084
|
-
function list(
|
|
14332
|
+
function list(db2, opts = {}) {
|
|
14085
14333
|
if (opts.all) {
|
|
14086
|
-
const rows =
|
|
14334
|
+
const rows = db2.prepare("SELECT * FROM events WHERE status NOT IN ('archived', 'deleted') ORDER BY type, id").all();
|
|
14087
14335
|
const out2 = ["## \u6BCF\u5468\u56FA\u5B9A"];
|
|
14088
14336
|
for (const r of rows) if (r.type === "weekly") out2.push(fmtRow(r));
|
|
14089
14337
|
out2.push("\n## \u6BCF\u65E5\u56FA\u5B9A");
|
|
@@ -14097,17 +14345,17 @@ function list(db, opts = {}) {
|
|
|
14097
14345
|
const out = [`\u5F53\u524D\u65F6\u95F4: ${fmtNow()}`];
|
|
14098
14346
|
const todayWeekday = getTodayWeekday();
|
|
14099
14347
|
const events = [];
|
|
14100
|
-
for (const r of
|
|
14348
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='weekly' AND status='pending' AND day=?").all(todayWeekday)) {
|
|
14101
14349
|
events.push(` #${r.id} ${r.time || ""} ${r.event}`);
|
|
14102
14350
|
}
|
|
14103
|
-
for (const r of
|
|
14351
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='daily' AND status='pending'").all()) {
|
|
14104
14352
|
if (r.repeat_type === "weekdays") {
|
|
14105
14353
|
const idx = new Date(Date.now() + 8 * 60 * 60 * 1e3).getUTCDay();
|
|
14106
14354
|
if (idx === 0 || idx === 6) continue;
|
|
14107
14355
|
}
|
|
14108
14356
|
events.push(` #${r.id} ${r.time || ""} ${r.event}`);
|
|
14109
14357
|
}
|
|
14110
|
-
for (const r of
|
|
14358
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='date' AND status='pending'").all()) {
|
|
14111
14359
|
const p = parseDateRange(r.date_str);
|
|
14112
14360
|
if (p && isToday(p.month, p.dStart, p.dEnd)) {
|
|
14113
14361
|
events.push(` #${r.id} ${r.event}`);
|
|
@@ -14121,14 +14369,14 @@ function list(db, opts = {}) {
|
|
|
14121
14369
|
}
|
|
14122
14370
|
return out.join("\n");
|
|
14123
14371
|
}
|
|
14124
|
-
function pending(
|
|
14372
|
+
function pending(db2) {
|
|
14125
14373
|
const out = [`\u5F53\u524D\u65F6\u95F4: ${fmtNow()}`];
|
|
14126
14374
|
const todayWeekday = getTodayWeekday();
|
|
14127
14375
|
const events = [];
|
|
14128
|
-
for (const r of
|
|
14376
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='weekly' AND status='pending' AND day=?").all(todayWeekday)) {
|
|
14129
14377
|
events.push(` #${r.id} [\u6BCF\u5468] ${r.time || ""} ${r.event}`);
|
|
14130
14378
|
}
|
|
14131
|
-
for (const r of
|
|
14379
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='daily' AND status='pending'").all()) {
|
|
14132
14380
|
if (r.repeat_type === "weekdays") {
|
|
14133
14381
|
const idx = new Date(Date.now() + 8 * 60 * 60 * 1e3).getUTCDay();
|
|
14134
14382
|
if (idx === 0 || idx === 6) continue;
|
|
@@ -14136,7 +14384,7 @@ function pending(db) {
|
|
|
14136
14384
|
const label = r.repeat_type === "weekdays" ? "[\u5DE5\u4F5C\u65E5]" : "[\u6BCF\u5929]";
|
|
14137
14385
|
events.push(` #${r.id} ${label} ${r.time || ""} ${r.event}`);
|
|
14138
14386
|
}
|
|
14139
|
-
for (const r of
|
|
14387
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='date' AND status='pending'").all()) {
|
|
14140
14388
|
const p = parseDateRange(r.date_str);
|
|
14141
14389
|
if (!p) continue;
|
|
14142
14390
|
if (isToday(p.month, p.dStart, p.dEnd)) {
|
|
@@ -14155,31 +14403,31 @@ function pending(db) {
|
|
|
14155
14403
|
}
|
|
14156
14404
|
return out.join("\n");
|
|
14157
14405
|
}
|
|
14158
|
-
function done(
|
|
14159
|
-
const row =
|
|
14406
|
+
function done(db2, id) {
|
|
14407
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=? AND status=?").get(id, "pending");
|
|
14160
14408
|
if (!row) return `\u672A\u627E\u5230 pending \u4E8B\u4EF6 #${id}`;
|
|
14161
14409
|
if (row.type === "daily" || row.type === "weekly") {
|
|
14162
14410
|
return `\u274C ${row.type === "daily" ? "\u6BCF\u65E5/\u5DE5\u4F5C\u65E5" : "\u6BCF\u5468"}\u7C7B\u578B\u4E0D\u652F\u6301 done\uFF08\u4F1A\u505C\u6B62\u5FAA\u73AF\uFF09\u3002\u4E0D\u9700\u8981\u4E86\u8BF7\u7528 delete ${id}`;
|
|
14163
14411
|
}
|
|
14164
|
-
|
|
14412
|
+
db2.prepare("UPDATE events SET status=?, done_at=?, reminded=1 WHERE id=?").run("done", nowIso(), id);
|
|
14165
14413
|
return `#${id} \u5DF2\u6807\u8BB0\u5B8C\u6210: ${row.event}`;
|
|
14166
14414
|
}
|
|
14167
|
-
function linkDoc(
|
|
14168
|
-
const row =
|
|
14415
|
+
function linkDoc(db2, id, docPath) {
|
|
14416
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=?").get(id);
|
|
14169
14417
|
if (!row) return `\u672A\u627E\u5230\u4E8B\u4EF6 #${id}`;
|
|
14170
|
-
|
|
14418
|
+
db2.prepare("UPDATE events SET doc_path=? WHERE id=?").run(docPath, id);
|
|
14171
14419
|
return `#${id} \u5DF2\u5173\u8054\u6587\u6863: ${docPath}`;
|
|
14172
14420
|
}
|
|
14173
|
-
function findDoc(
|
|
14174
|
-
const row =
|
|
14421
|
+
function findDoc(db2, id) {
|
|
14422
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=?").get(id);
|
|
14175
14423
|
if (!row) return `\u672A\u627E\u5230\u4E8B\u4EF6 #${id}`;
|
|
14176
14424
|
const parts = [`#${id} ${row.event}`];
|
|
14177
14425
|
if (row.doc_path) parts.push(`\u{1F4C4} doc_path: ${row.doc_path}`);
|
|
14178
14426
|
else parts.push(`\u{1F4C4} doc_path: (\u672A\u5173\u8054)`);
|
|
14179
14427
|
return parts.join("\n");
|
|
14180
14428
|
}
|
|
14181
|
-
function search(
|
|
14182
|
-
const rows =
|
|
14429
|
+
function search(db2, keyword) {
|
|
14430
|
+
const rows = db2.prepare("SELECT * FROM events WHERE event LIKE ? ORDER BY id").all(`%${keyword}%`);
|
|
14183
14431
|
if (rows.length > 0) {
|
|
14184
14432
|
const out = [`\u67E5\u8BE2 '${keyword}' (${rows.length} \u6761):`];
|
|
14185
14433
|
rows.forEach((r) => out.push(fmtRow(r)));
|
|
@@ -14187,29 +14435,29 @@ function search(db, keyword) {
|
|
|
14187
14435
|
}
|
|
14188
14436
|
return `\u67E5\u8BE2 '${keyword}' \u65E0\u7ED3\u679C`;
|
|
14189
14437
|
}
|
|
14190
|
-
function archive(
|
|
14191
|
-
const row =
|
|
14438
|
+
function archive(db2, id) {
|
|
14439
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=? AND status!=?").get(id, "archived");
|
|
14192
14440
|
if (!row) return `\u672A\u627E\u5230\u4E8B\u4EF6 #${id}`;
|
|
14193
|
-
|
|
14441
|
+
db2.prepare("UPDATE events SET status=?, archived_at=?, reminded=1 WHERE id=?").run("archived", nowIso(), id);
|
|
14194
14442
|
return `#${id} \u5DF2\u5F52\u6863: ${row.event}`;
|
|
14195
14443
|
}
|
|
14196
|
-
function cleanup(
|
|
14197
|
-
const rows =
|
|
14444
|
+
function cleanup(db2) {
|
|
14445
|
+
const rows = db2.prepare("SELECT * FROM events WHERE type='date' AND status='done'").all();
|
|
14198
14446
|
let archived = 0;
|
|
14199
14447
|
for (const r of rows) {
|
|
14200
14448
|
const p = parseDateRange(r.date_str);
|
|
14201
14449
|
if (p && isOverdue(p.month, p.dStart, p.dEnd)) {
|
|
14202
|
-
|
|
14450
|
+
db2.prepare("UPDATE events SET status=?, archived_at=? WHERE id=?").run("archived", nowIso(), r.id);
|
|
14203
14451
|
archived++;
|
|
14204
14452
|
}
|
|
14205
14453
|
}
|
|
14206
14454
|
return archived > 0 ? `\u5DF2\u81EA\u52A8\u5F52\u6863 ${archived} \u6761\u8FC7\u671F\u5B8C\u6210\u65E5\u7A0B` : "\u65E0\u8FC7\u671F\u5B8C\u6210\u65E5\u7A0B\u9700\u8981\u5F52\u6863";
|
|
14207
14455
|
}
|
|
14208
|
-
function stats(
|
|
14209
|
-
const total =
|
|
14210
|
-
const pending2 =
|
|
14211
|
-
const done2 =
|
|
14212
|
-
const archived =
|
|
14456
|
+
function stats(db2) {
|
|
14457
|
+
const total = db2.prepare("SELECT COUNT(*) as c FROM events").get().c;
|
|
14458
|
+
const pending2 = db2.prepare("SELECT COUNT(*) as c FROM events WHERE status='pending'").get().c;
|
|
14459
|
+
const done2 = db2.prepare("SELECT COUNT(*) as c FROM events WHERE status='done'").get().c;
|
|
14460
|
+
const archived = db2.prepare("SELECT COUNT(*) as c FROM events WHERE status='archived'").get().c;
|
|
14213
14461
|
return `\u65E5\u5386\u7EDF\u8BA1: \u603B\u8BA1 ${total} | pending ${pending2} | done ${done2} | archived ${archived}`;
|
|
14214
14462
|
}
|
|
14215
14463
|
var WEEKDAYS2;
|
|
@@ -14255,7 +14503,7 @@ var init_calendar = __esm({
|
|
|
14255
14503
|
const action = args.action;
|
|
14256
14504
|
if (!action) return { content: "Error: action is required", isError: true };
|
|
14257
14505
|
try {
|
|
14258
|
-
const
|
|
14506
|
+
const db2 = openDb(ctx.workspace);
|
|
14259
14507
|
let result2;
|
|
14260
14508
|
let isAddTask = false;
|
|
14261
14509
|
if (action === "add") {
|
|
@@ -14265,22 +14513,22 @@ var init_calendar = __esm({
|
|
|
14265
14513
|
const repeat = args.repeat || (args.weekly ? "weekly" : "once");
|
|
14266
14514
|
if (repeat === "daily" || repeat === "weekdays") {
|
|
14267
14515
|
if (!args.time) return { content: "Error: add daily/weekdays needs time (e.g. 23:00)", isError: true };
|
|
14268
|
-
result2 = addDaily(
|
|
14516
|
+
result2 = addDaily(db2, { time: args.time, event, repeatType: repeat, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
|
|
14269
14517
|
} else if (repeat === "weekly") {
|
|
14270
14518
|
const day = args.day;
|
|
14271
14519
|
if (!day) return { content: "Error: add weekly needs day", isError: true };
|
|
14272
|
-
result2 = addWeekly(
|
|
14520
|
+
result2 = addWeekly(db2, { day, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
|
|
14273
14521
|
} else {
|
|
14274
14522
|
const date = args.date?.trim();
|
|
14275
14523
|
if (!date) return { content: "Error: add once needs date (e.g. 5/26)", isError: true };
|
|
14276
|
-
result2 = addDate(
|
|
14524
|
+
result2 = addDate(db2, { dateStr: date, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
|
|
14277
14525
|
}
|
|
14278
14526
|
} else if (action === "add-batch") {
|
|
14279
14527
|
const event = args.event?.trim();
|
|
14280
14528
|
const datesInput = args.dates?.trim();
|
|
14281
14529
|
if (!event) return { content: "Error: add-batch needs event", isError: true };
|
|
14282
14530
|
if (!datesInput) return { content: 'Error: add-batch needs dates (e.g. "7/2,7/4,7/6-7/10")', isError: true };
|
|
14283
|
-
result2 = addBatch(
|
|
14531
|
+
result2 = addBatch(db2, { datesInput, event, time: args.time, duration: args.duration, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
|
|
14284
14532
|
} else if (action === "add-task") {
|
|
14285
14533
|
isAddTask = true;
|
|
14286
14534
|
const event = args.event?.trim();
|
|
@@ -14291,47 +14539,47 @@ var init_calendar = __esm({
|
|
|
14291
14539
|
if (!date) return { content: "Error: add-task needs date (e.g. 7/5)", isError: true };
|
|
14292
14540
|
if (!timeExact || !timeExact.includes(":")) return { content: "Error: add-task needs time_exact (HH:MM, e.g. 14:00)", isError: true };
|
|
14293
14541
|
if (!docPath) return { content: "\u274C \u521B\u5EFA\u5931\u8D25\uFF1Aadd-task \u5FC5\u987B\u4F20 doc_path\u3002\n\u6CA1\u6709\u6587\u6863\u652F\u6491\u7684 task \u4E0D\u662F\u5408\u683C\u7684 task\u3002\n\u8BF7\u5148\u5728 docs/todo/ \u4E0B\u521B\u5EFA\u6587\u6863\uFF08\u547D\u540D\uFF1AYYYY-MM-DD_\u4E3B\u9898.md \u6216 \u4EFB\u52A1\u540D.md\uFF09\uFF0C\u7136\u540E\u4F20 doc_path \u53C2\u6570\u3002", isError: true };
|
|
14294
|
-
result2 = addTask(
|
|
14542
|
+
result2 = addTask(db2, { dateStr: date, timeExact, event, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget, docPath });
|
|
14295
14543
|
} else if (action === "reschedule") {
|
|
14296
14544
|
if (args.id == null) return { content: "Error: reschedule needs id", isError: true };
|
|
14297
14545
|
const date = args.date?.trim();
|
|
14298
14546
|
const timeExact = args.time_exact?.trim();
|
|
14299
14547
|
if (!date) return { content: "Error: reschedule needs date (e.g. 7/10)", isError: true };
|
|
14300
14548
|
if (!timeExact || !timeExact.includes(":")) return { content: "Error: reschedule needs time_exact (HH:MM)", isError: true };
|
|
14301
|
-
result2 = reschedule(
|
|
14549
|
+
result2 = reschedule(db2, { id: args.id, dateStr: date, timeExact, remind: args.remind });
|
|
14302
14550
|
} else if (action === "link-doc") {
|
|
14303
14551
|
if (args.id == null) return { content: "Error: link-doc needs id", isError: true };
|
|
14304
14552
|
const docPath = args.doc_path?.trim();
|
|
14305
14553
|
if (!docPath) return { content: "Error: link-doc needs doc_path", isError: true };
|
|
14306
|
-
result2 = linkDoc(
|
|
14554
|
+
result2 = linkDoc(db2, args.id, docPath);
|
|
14307
14555
|
} else if (action === "find-doc") {
|
|
14308
14556
|
if (args.id == null) return { content: "Error: find-doc needs id", isError: true };
|
|
14309
|
-
result2 = findDoc(
|
|
14557
|
+
result2 = findDoc(db2, args.id);
|
|
14310
14558
|
} else if (action === "list") {
|
|
14311
|
-
result2 = list(
|
|
14559
|
+
result2 = list(db2, { all: !!args.all });
|
|
14312
14560
|
} else if (action === "done") {
|
|
14313
14561
|
if (args.id == null) return { content: "Error: done needs id", isError: true };
|
|
14314
|
-
result2 = done(
|
|
14562
|
+
result2 = done(db2, args.id);
|
|
14315
14563
|
} else if (action === "pending") {
|
|
14316
|
-
result2 = pending(
|
|
14564
|
+
result2 = pending(db2);
|
|
14317
14565
|
} else if (action === "search") {
|
|
14318
14566
|
const kw = args.event?.trim();
|
|
14319
14567
|
if (!kw) return { content: "Error: search needs keyword (event field)", isError: true };
|
|
14320
|
-
result2 = search(
|
|
14568
|
+
result2 = search(db2, kw);
|
|
14321
14569
|
} else if (action === "archive") {
|
|
14322
14570
|
if (args.id == null) return { content: "Error: archive needs id", isError: true };
|
|
14323
|
-
result2 = archive(
|
|
14571
|
+
result2 = archive(db2, args.id);
|
|
14324
14572
|
} else if (action === "delete") {
|
|
14325
14573
|
if (args.id == null) return { content: "Error: delete needs id", isError: true };
|
|
14326
|
-
result2 = archive(
|
|
14574
|
+
result2 = archive(db2, args.id);
|
|
14327
14575
|
} else if (action === "cleanup") {
|
|
14328
|
-
result2 = cleanup(
|
|
14576
|
+
result2 = cleanup(db2);
|
|
14329
14577
|
} else if (action === "stats") {
|
|
14330
|
-
result2 = stats(
|
|
14578
|
+
result2 = stats(db2);
|
|
14331
14579
|
} else {
|
|
14332
14580
|
return { content: `Error: unknown action '${action}'`, isError: true };
|
|
14333
14581
|
}
|
|
14334
|
-
|
|
14582
|
+
db2.close();
|
|
14335
14583
|
const isFailed = result2.startsWith("\u274C") || result2.includes("Error") || result2.includes("\u7528\u6CD5");
|
|
14336
14584
|
if (isAddTask && !isFailed) {
|
|
14337
14585
|
const { enqueueNotification: enqueueNotification2, buildCalendarNotification: buildCalendarNotification2 } = await Promise.resolve().then(() => (init_task_manager(), task_manager_exports));
|
|
@@ -14575,24 +14823,24 @@ var init_constants5 = __esm({
|
|
|
14575
14823
|
});
|
|
14576
14824
|
|
|
14577
14825
|
// src/tools/TodoWriteTool/TodoWriteTool.ts
|
|
14578
|
-
import
|
|
14579
|
-
import
|
|
14826
|
+
import fs22 from "node:fs";
|
|
14827
|
+
import path23 from "node:path";
|
|
14580
14828
|
function todoFilePath(sessionId) {
|
|
14581
|
-
return
|
|
14829
|
+
return path23.join(todosDir, `${sessionId}.json`);
|
|
14582
14830
|
}
|
|
14583
14831
|
function loadTodos(sessionId) {
|
|
14584
14832
|
if (!todosDir) return [];
|
|
14585
14833
|
try {
|
|
14586
14834
|
const filePath = todoFilePath(sessionId);
|
|
14587
|
-
if (!
|
|
14588
|
-
return JSON.parse(
|
|
14835
|
+
if (!fs22.existsSync(filePath)) return [];
|
|
14836
|
+
return JSON.parse(fs22.readFileSync(filePath, "utf-8"));
|
|
14589
14837
|
} catch {
|
|
14590
14838
|
return [];
|
|
14591
14839
|
}
|
|
14592
14840
|
}
|
|
14593
14841
|
function saveTodos(sessionId, todos) {
|
|
14594
14842
|
if (!todosDir) return;
|
|
14595
|
-
|
|
14843
|
+
fs22.writeFileSync(todoFilePath(sessionId), JSON.stringify(todos, null, 2), "utf-8");
|
|
14596
14844
|
}
|
|
14597
14845
|
var todosDir;
|
|
14598
14846
|
var init_TodoWriteTool = __esm({
|
|
@@ -14849,15 +15097,15 @@ var init_constants7 = __esm({
|
|
|
14849
15097
|
});
|
|
14850
15098
|
|
|
14851
15099
|
// src/utils/plans.ts
|
|
14852
|
-
import * as
|
|
14853
|
-
import * as
|
|
15100
|
+
import * as fs23 from "node:fs";
|
|
15101
|
+
import * as path24 from "node:path";
|
|
14854
15102
|
import * as crypto4 from "node:crypto";
|
|
14855
15103
|
function generateSlug() {
|
|
14856
15104
|
return crypto4.randomBytes(4).toString("hex");
|
|
14857
15105
|
}
|
|
14858
15106
|
function getPlansDirectory(stateDir) {
|
|
14859
|
-
const plansDir =
|
|
14860
|
-
|
|
15107
|
+
const plansDir = path24.join(stateDir, "plans");
|
|
15108
|
+
fs23.mkdirSync(plansDir, { recursive: true });
|
|
14861
15109
|
return plansDir;
|
|
14862
15110
|
}
|
|
14863
15111
|
function getPlanSlug(sessionId, stateDir) {
|
|
@@ -14866,8 +15114,8 @@ function getPlanSlug(sessionId, stateDir) {
|
|
|
14866
15114
|
const plansDir = getPlansDirectory(stateDir);
|
|
14867
15115
|
for (let i = 0; i < MAX_SLUG_RETRIES; i++) {
|
|
14868
15116
|
slug = generateSlug();
|
|
14869
|
-
const filePath =
|
|
14870
|
-
if (!
|
|
15117
|
+
const filePath = path24.join(plansDir, `${slug}.md`);
|
|
15118
|
+
if (!fs23.existsSync(filePath)) {
|
|
14871
15119
|
break;
|
|
14872
15120
|
}
|
|
14873
15121
|
}
|
|
@@ -14878,21 +15126,21 @@ function getPlanSlug(sessionId, stateDir) {
|
|
|
14878
15126
|
function getPlanFilePath(sessionId, stateDir, agentId) {
|
|
14879
15127
|
const slug = getPlanSlug(sessionId, stateDir);
|
|
14880
15128
|
if (!agentId) {
|
|
14881
|
-
return
|
|
15129
|
+
return path24.join(getPlansDirectory(stateDir), `${slug}.md`);
|
|
14882
15130
|
}
|
|
14883
|
-
return
|
|
15131
|
+
return path24.join(getPlansDirectory(stateDir), `${slug}-agent-${agentId}.md`);
|
|
14884
15132
|
}
|
|
14885
15133
|
function getPlan(sessionId, stateDir, agentId) {
|
|
14886
15134
|
const filePath = getPlanFilePath(sessionId, stateDir, agentId);
|
|
14887
15135
|
try {
|
|
14888
|
-
return
|
|
15136
|
+
return fs23.readFileSync(filePath, "utf-8");
|
|
14889
15137
|
} catch {
|
|
14890
15138
|
return null;
|
|
14891
15139
|
}
|
|
14892
15140
|
}
|
|
14893
15141
|
function writePlan(sessionId, stateDir, content, agentId) {
|
|
14894
15142
|
const filePath = getPlanFilePath(sessionId, stateDir, agentId);
|
|
14895
|
-
|
|
15143
|
+
fs23.writeFileSync(filePath, content, "utf-8");
|
|
14896
15144
|
return filePath;
|
|
14897
15145
|
}
|
|
14898
15146
|
var MAX_SLUG_RETRIES, planSlugCache;
|
|
@@ -15040,28 +15288,28 @@ var init_constants8 = __esm({
|
|
|
15040
15288
|
});
|
|
15041
15289
|
|
|
15042
15290
|
// src/utils/tasks.ts
|
|
15043
|
-
import * as
|
|
15044
|
-
import * as
|
|
15291
|
+
import * as fs24 from "node:fs";
|
|
15292
|
+
import * as path25 from "node:path";
|
|
15045
15293
|
function sanitizePathComponent2(input) {
|
|
15046
15294
|
return input.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
15047
15295
|
}
|
|
15048
15296
|
function getTasksDir2(stateDir, listId) {
|
|
15049
|
-
return
|
|
15297
|
+
return path25.join(stateDir, "tasks", sanitizePathComponent2(listId));
|
|
15050
15298
|
}
|
|
15051
15299
|
function getTaskPath(stateDir, listId, taskId) {
|
|
15052
|
-
return
|
|
15300
|
+
return path25.join(getTasksDir2(stateDir, listId), `${sanitizePathComponent2(taskId)}.json`);
|
|
15053
15301
|
}
|
|
15054
15302
|
function ensureTasksDir2(stateDir, listId) {
|
|
15055
15303
|
const dir = getTasksDir2(stateDir, listId);
|
|
15056
|
-
|
|
15304
|
+
fs24.mkdirSync(dir, { recursive: true });
|
|
15057
15305
|
return dir;
|
|
15058
15306
|
}
|
|
15059
15307
|
function getHighWaterMarkPath(stateDir, listId) {
|
|
15060
|
-
return
|
|
15308
|
+
return path25.join(getTasksDir2(stateDir, listId), HIGH_WATER_MARK_FILE);
|
|
15061
15309
|
}
|
|
15062
15310
|
function readHighWaterMark(stateDir, listId) {
|
|
15063
15311
|
try {
|
|
15064
|
-
const content =
|
|
15312
|
+
const content = fs24.readFileSync(getHighWaterMarkPath(stateDir, listId), "utf-8").trim();
|
|
15065
15313
|
const value = parseInt(content, 10);
|
|
15066
15314
|
return isNaN(value) ? 0 : value;
|
|
15067
15315
|
} catch {
|
|
@@ -15069,20 +15317,20 @@ function readHighWaterMark(stateDir, listId) {
|
|
|
15069
15317
|
}
|
|
15070
15318
|
}
|
|
15071
15319
|
function writeHighWaterMark(stateDir, listId, value) {
|
|
15072
|
-
|
|
15320
|
+
fs24.writeFileSync(getHighWaterMarkPath(stateDir, listId), String(value));
|
|
15073
15321
|
}
|
|
15074
15322
|
function findHighestTaskIdFromFiles(stateDir, listId) {
|
|
15075
15323
|
const dir = getTasksDir2(stateDir, listId);
|
|
15076
15324
|
let files;
|
|
15077
15325
|
try {
|
|
15078
|
-
files =
|
|
15326
|
+
files = fs24.readdirSync(dir);
|
|
15079
15327
|
} catch {
|
|
15080
15328
|
return 0;
|
|
15081
15329
|
}
|
|
15082
15330
|
let highest = 0;
|
|
15083
|
-
for (const
|
|
15084
|
-
if (!
|
|
15085
|
-
const taskId = parseInt(
|
|
15331
|
+
for (const file2 of files) {
|
|
15332
|
+
if (!file2.endsWith(".json")) continue;
|
|
15333
|
+
const taskId = parseInt(file2.replace(".json", ""), 10);
|
|
15086
15334
|
if (!isNaN(taskId) && taskId > highest) {
|
|
15087
15335
|
highest = taskId;
|
|
15088
15336
|
}
|
|
@@ -15101,14 +15349,14 @@ function createTask(stateDir, listId, taskData) {
|
|
|
15101
15349
|
const id = String(highestId + 1);
|
|
15102
15350
|
const task = { id, ...taskData };
|
|
15103
15351
|
const filePath = getTaskPath(stateDir, listId, id);
|
|
15104
|
-
|
|
15352
|
+
fs24.writeFileSync(filePath, JSON.stringify(task, null, 2));
|
|
15105
15353
|
return id;
|
|
15106
15354
|
});
|
|
15107
15355
|
}
|
|
15108
15356
|
function getTask2(stateDir, listId, taskId) {
|
|
15109
15357
|
const filePath = getTaskPath(stateDir, listId, taskId);
|
|
15110
15358
|
try {
|
|
15111
|
-
const content =
|
|
15359
|
+
const content = fs24.readFileSync(filePath, "utf-8");
|
|
15112
15360
|
return JSON.parse(content);
|
|
15113
15361
|
} catch {
|
|
15114
15362
|
return null;
|
|
@@ -15118,7 +15366,7 @@ function listTasks2(stateDir, listId) {
|
|
|
15118
15366
|
const dir = getTasksDir2(stateDir, listId);
|
|
15119
15367
|
let files;
|
|
15120
15368
|
try {
|
|
15121
|
-
files =
|
|
15369
|
+
files = fs24.readdirSync(dir);
|
|
15122
15370
|
} catch {
|
|
15123
15371
|
return [];
|
|
15124
15372
|
}
|
|
@@ -15130,7 +15378,7 @@ function updateTask(stateDir, listId, taskId, updates) {
|
|
|
15130
15378
|
if (!existing) return null;
|
|
15131
15379
|
const updated = { ...existing, ...updates, id: taskId };
|
|
15132
15380
|
const filePath = getTaskPath(stateDir, listId, taskId);
|
|
15133
|
-
|
|
15381
|
+
fs24.writeFileSync(filePath, JSON.stringify(updated, null, 2));
|
|
15134
15382
|
return updated;
|
|
15135
15383
|
}
|
|
15136
15384
|
function deleteTask(stateDir, listId, taskId) {
|
|
@@ -15144,7 +15392,7 @@ function deleteTask(stateDir, listId, taskId) {
|
|
|
15144
15392
|
}
|
|
15145
15393
|
}
|
|
15146
15394
|
try {
|
|
15147
|
-
|
|
15395
|
+
fs24.unlinkSync(filePath);
|
|
15148
15396
|
} catch {
|
|
15149
15397
|
return false;
|
|
15150
15398
|
}
|
|
@@ -16577,10 +16825,10 @@ function ensureLoaded(workspace, configIds) {
|
|
|
16577
16825
|
if (!state.blockedUserIds.includes(id)) state.blockedUserIds.push(id);
|
|
16578
16826
|
}
|
|
16579
16827
|
}
|
|
16580
|
-
const
|
|
16828
|
+
const path31 = join23(workspace, ".reply-blocklist.json");
|
|
16581
16829
|
try {
|
|
16582
|
-
if (existsSync18(
|
|
16583
|
-
const raw = readFileSync18(
|
|
16830
|
+
if (existsSync18(path31)) {
|
|
16831
|
+
const raw = readFileSync18(path31, "utf-8");
|
|
16584
16832
|
const parsed = JSON.parse(raw);
|
|
16585
16833
|
if (parsed.blockedUserIds) {
|
|
16586
16834
|
for (const id of parsed.blockedUserIds) {
|
|
@@ -16596,9 +16844,9 @@ function ensureLoaded(workspace, configIds) {
|
|
|
16596
16844
|
loaded = true;
|
|
16597
16845
|
}
|
|
16598
16846
|
function save(workspace) {
|
|
16599
|
-
const
|
|
16847
|
+
const path31 = join23(workspace, ".reply-blocklist.json");
|
|
16600
16848
|
try {
|
|
16601
|
-
writeFileSync14(
|
|
16849
|
+
writeFileSync14(path31, JSON.stringify(state, null, 2), "utf-8");
|
|
16602
16850
|
} catch (err) {
|
|
16603
16851
|
console.warn(`[reply-blocklist] Failed to save: ${err.message}`);
|
|
16604
16852
|
}
|
|
@@ -17115,9 +17363,9 @@ function cosineSim(a, b) {
|
|
|
17115
17363
|
}
|
|
17116
17364
|
function readDbEmbeddings(dbPath) {
|
|
17117
17365
|
const { DatabaseSync: DatabaseSync2 } = require3("node:sqlite");
|
|
17118
|
-
const
|
|
17366
|
+
const db2 = new DatabaseSync2(dbPath, { readOnly: true });
|
|
17119
17367
|
try {
|
|
17120
|
-
const stmt =
|
|
17368
|
+
const stmt = db2.prepare(`
|
|
17121
17369
|
SELECT file_path, name, description, mtime, embedding
|
|
17122
17370
|
FROM files
|
|
17123
17371
|
WHERE embedding IS NOT NULL AND deprecated_by IS NULL
|
|
@@ -17134,7 +17382,7 @@ function readDbEmbeddings(dbPath) {
|
|
|
17134
17382
|
}
|
|
17135
17383
|
return rows;
|
|
17136
17384
|
} finally {
|
|
17137
|
-
|
|
17385
|
+
db2.close();
|
|
17138
17386
|
}
|
|
17139
17387
|
}
|
|
17140
17388
|
async function llmRerank(query, candidates, topK, ollamaChatUrl, model) {
|
|
@@ -17511,6 +17759,69 @@ var init_light_mode = __esm({
|
|
|
17511
17759
|
}
|
|
17512
17760
|
});
|
|
17513
17761
|
|
|
17762
|
+
// src/compact/voiceFastView.ts
|
|
17763
|
+
function blocksText(content) {
|
|
17764
|
+
if (typeof content === "string") return content;
|
|
17765
|
+
if (Array.isArray(content)) return content.filter((b) => b && b.type === "text").map((b) => b.text || "").join(" ");
|
|
17766
|
+
return "";
|
|
17767
|
+
}
|
|
17768
|
+
function splitTurns(history) {
|
|
17769
|
+
const turns = [];
|
|
17770
|
+
let cur = [];
|
|
17771
|
+
for (const m of history) {
|
|
17772
|
+
if (m.role === "user" && cur.length > 0) {
|
|
17773
|
+
turns.push(cur);
|
|
17774
|
+
cur = [m];
|
|
17775
|
+
} else cur.push(m);
|
|
17776
|
+
}
|
|
17777
|
+
if (cur.length > 0) turns.push(cur);
|
|
17778
|
+
return turns;
|
|
17779
|
+
}
|
|
17780
|
+
function voiceFastView(history, opts = VOICE_FAST_DEFAULTS) {
|
|
17781
|
+
const { keepTurns, toolCap, argCap } = opts;
|
|
17782
|
+
const turns = splitTurns(history);
|
|
17783
|
+
const oldTurns = turns.slice(0, Math.max(0, turns.length - keepTurns));
|
|
17784
|
+
const keepTurnsArr = turns.slice(Math.max(0, turns.length - keepTurns));
|
|
17785
|
+
const folded = oldTurns.map(
|
|
17786
|
+
(turn) => turn.map((m) => {
|
|
17787
|
+
if (m.role === "toolResult") {
|
|
17788
|
+
const text = blocksText(m.content);
|
|
17789
|
+
if (text.length > toolCap) {
|
|
17790
|
+
const compressed = smartCompressToolResult(text, void 0, toolCap);
|
|
17791
|
+
return { ...m, content: [{ type: "text", text: compressed }] };
|
|
17792
|
+
}
|
|
17793
|
+
return m;
|
|
17794
|
+
}
|
|
17795
|
+
if (m.role === "assistant" && Array.isArray(m.content)) {
|
|
17796
|
+
const newContent = m.content.map((b) => {
|
|
17797
|
+
if (b && b.type === "toolCall" && b.arguments) {
|
|
17798
|
+
const argStr = typeof b.arguments === "string" ? b.arguments : JSON.stringify(b.arguments);
|
|
17799
|
+
if (argStr.length > argCap) {
|
|
17800
|
+
return { ...b, arguments: argStr.slice(0, argCap) + "\u2026[voice-fold]" };
|
|
17801
|
+
}
|
|
17802
|
+
}
|
|
17803
|
+
return b;
|
|
17804
|
+
});
|
|
17805
|
+
return { ...m, content: newContent };
|
|
17806
|
+
}
|
|
17807
|
+
return m;
|
|
17808
|
+
})
|
|
17809
|
+
);
|
|
17810
|
+
const out = [...folded.flat(), ...keepTurnsArr.flat()];
|
|
17811
|
+
const before = JSON.stringify(history).length;
|
|
17812
|
+
const saved = before - JSON.stringify(out).length;
|
|
17813
|
+
console.log(`[voice-fast] ${history.length} \u2192 ${out.length} \u6761 (keepTurns=${keepTurns}, toolCap=${toolCap}, argCap=${argCap}, -${(saved * 100 / Math.max(1, before)).toFixed(0)}%)`);
|
|
17814
|
+
return out;
|
|
17815
|
+
}
|
|
17816
|
+
var VOICE_FAST_DEFAULTS;
|
|
17817
|
+
var init_voiceFastView = __esm({
|
|
17818
|
+
"src/compact/voiceFastView.ts"() {
|
|
17819
|
+
"use strict";
|
|
17820
|
+
init_ruleCompact();
|
|
17821
|
+
VOICE_FAST_DEFAULTS = { keepTurns: 5, toolCap: 500, argCap: 100 };
|
|
17822
|
+
}
|
|
17823
|
+
});
|
|
17824
|
+
|
|
17514
17825
|
// src/sender-context.ts
|
|
17515
17826
|
import { readFileSync as readFileSync21, existsSync as existsSync20 } from "node:fs";
|
|
17516
17827
|
import { join as join28 } from "node:path";
|
|
@@ -17678,8 +17989,8 @@ var extractMemories_exports = {};
|
|
|
17678
17989
|
__export(extractMemories_exports, {
|
|
17679
17990
|
createMemoryExtractor: () => createMemoryExtractor
|
|
17680
17991
|
});
|
|
17681
|
-
import * as
|
|
17682
|
-
import * as
|
|
17992
|
+
import * as fs25 from "fs";
|
|
17993
|
+
import * as path26 from "path";
|
|
17683
17994
|
function isModelVisibleMessage(message) {
|
|
17684
17995
|
return message.role === "user" || message.role === "assistant";
|
|
17685
17996
|
}
|
|
@@ -17702,13 +18013,13 @@ function getMemoryTools() {
|
|
|
17702
18013
|
return allDefs.filter((d) => MEMORY_TOOL_NAMES.includes(d.function.name));
|
|
17703
18014
|
}
|
|
17704
18015
|
function getStatePath(workspace) {
|
|
17705
|
-
return
|
|
18016
|
+
return path26.join(workspace, STATE_FILE);
|
|
17706
18017
|
}
|
|
17707
18018
|
function loadPersistedState(workspace) {
|
|
17708
18019
|
try {
|
|
17709
18020
|
const p = getStatePath(workspace);
|
|
17710
|
-
if (
|
|
17711
|
-
const data = JSON.parse(
|
|
18021
|
+
if (fs25.existsSync(p)) {
|
|
18022
|
+
const data = JSON.parse(fs25.readFileSync(p, "utf-8"));
|
|
17712
18023
|
for (const [sid, ts] of Object.entries(data.lastTs ?? {})) {
|
|
17713
18024
|
lastTsMap.set(sid, ts);
|
|
17714
18025
|
}
|
|
@@ -17728,7 +18039,7 @@ function persistState(workspace) {
|
|
|
17728
18039
|
for (const [sid, ts] of lastTsMap.entries()) lastTs[sid] = ts;
|
|
17729
18040
|
for (const [sid, ts] of lastExtractTimeMap.entries()) timestamps[sid] = ts;
|
|
17730
18041
|
const data = JSON.stringify({ lastTs, timestamps }, null, 2);
|
|
17731
|
-
|
|
18042
|
+
fs25.writeFileSync(getStatePath(workspace), data, "utf-8");
|
|
17732
18043
|
} catch (e) {
|
|
17733
18044
|
console.warn(`[memory] failed to persist extract state: ${e?.message ?? e}`);
|
|
17734
18045
|
}
|
|
@@ -17769,11 +18080,11 @@ function createMemoryExtractor(workspace, enabled) {
|
|
|
17769
18080
|
const existingMemories = formatMemoryManifest(
|
|
17770
18081
|
await scanMemoryFiles2(memoryDir, new AbortController().signal)
|
|
17771
18082
|
);
|
|
17772
|
-
const extractOverridePath =
|
|
18083
|
+
const extractOverridePath = path26.join(workspace, "prompts", "extract.md");
|
|
17773
18084
|
let systemPrompt;
|
|
17774
18085
|
try {
|
|
17775
|
-
if (
|
|
17776
|
-
systemPrompt =
|
|
18086
|
+
if (fs25.existsSync(extractOverridePath)) {
|
|
18087
|
+
systemPrompt = fs25.readFileSync(extractOverridePath, { encoding: "utf-8" });
|
|
17777
18088
|
if (existingMemories.length > 0) {
|
|
17778
18089
|
systemPrompt += `
|
|
17779
18090
|
|
|
@@ -17874,8 +18185,8 @@ var ingest_exports = {};
|
|
|
17874
18185
|
__export(ingest_exports, {
|
|
17875
18186
|
pushConversation: () => pushConversation
|
|
17876
18187
|
});
|
|
17877
|
-
import
|
|
17878
|
-
import
|
|
18188
|
+
import fs26 from "node:fs";
|
|
18189
|
+
import path27 from "node:path";
|
|
17879
18190
|
function parseMeta(text) {
|
|
17880
18191
|
const m = text.match(/^\[meta:\s*(.+?)\s*\((.+?)\)\s*@(\S+)\s*[^\]]*\]/);
|
|
17881
18192
|
if (!m) return null;
|
|
@@ -17908,9 +18219,9 @@ async function readConfig() {
|
|
|
17908
18219
|
}
|
|
17909
18220
|
function loadPushTs(workspace, sessionId) {
|
|
17910
18221
|
try {
|
|
17911
|
-
const p =
|
|
17912
|
-
if (
|
|
17913
|
-
const data = JSON.parse(
|
|
18222
|
+
const p = path27.join(workspace, PUSH_STATE_FILE);
|
|
18223
|
+
if (fs26.existsSync(p)) {
|
|
18224
|
+
const data = JSON.parse(fs26.readFileSync(p, "utf-8"));
|
|
17914
18225
|
return typeof data[sessionId] === "number" ? data[sessionId] : 0;
|
|
17915
18226
|
}
|
|
17916
18227
|
} catch (e) {
|
|
@@ -17920,14 +18231,14 @@ function loadPushTs(workspace, sessionId) {
|
|
|
17920
18231
|
}
|
|
17921
18232
|
function savePushTs(workspace, sessionId, ts) {
|
|
17922
18233
|
try {
|
|
17923
|
-
const p =
|
|
18234
|
+
const p = path27.join(workspace, PUSH_STATE_FILE);
|
|
17924
18235
|
let data = {};
|
|
17925
18236
|
try {
|
|
17926
|
-
if (
|
|
18237
|
+
if (fs26.existsSync(p)) data = JSON.parse(fs26.readFileSync(p, "utf-8"));
|
|
17927
18238
|
} catch {
|
|
17928
18239
|
}
|
|
17929
18240
|
data[sessionId] = ts;
|
|
17930
|
-
|
|
18241
|
+
fs26.writeFileSync(p, JSON.stringify(data, null, 2), "utf-8");
|
|
17931
18242
|
} catch (e) {
|
|
17932
18243
|
console.warn(`[everos-ingest] save pushTs failed: ${e?.message ?? e}`);
|
|
17933
18244
|
}
|
|
@@ -18576,11 +18887,11 @@ async function readLastConsolidatedAt(memoryDir) {
|
|
|
18576
18887
|
}
|
|
18577
18888
|
}
|
|
18578
18889
|
async function tryAcquireConsolidationLock(memoryDir) {
|
|
18579
|
-
const
|
|
18890
|
+
const path31 = lockPath(memoryDir);
|
|
18580
18891
|
let mtimeMs;
|
|
18581
18892
|
let holderPid;
|
|
18582
18893
|
try {
|
|
18583
|
-
const [s, raw] = await Promise.all([stat3(
|
|
18894
|
+
const [s, raw] = await Promise.all([stat3(path31), readFile5(path31, "utf8")]);
|
|
18584
18895
|
mtimeMs = s.mtimeMs;
|
|
18585
18896
|
const parsed = parseInt(raw.trim(), 10);
|
|
18586
18897
|
holderPid = Number.isFinite(parsed) ? parsed : void 0;
|
|
@@ -18593,10 +18904,10 @@ async function tryAcquireConsolidationLock(memoryDir) {
|
|
|
18593
18904
|
}
|
|
18594
18905
|
}
|
|
18595
18906
|
await mkdir3(memoryDir, { recursive: true });
|
|
18596
|
-
await writeFile4(
|
|
18907
|
+
await writeFile4(path31, String(process.pid));
|
|
18597
18908
|
let verify;
|
|
18598
18909
|
try {
|
|
18599
|
-
verify = await readFile5(
|
|
18910
|
+
verify = await readFile5(path31, "utf8");
|
|
18600
18911
|
} catch {
|
|
18601
18912
|
return null;
|
|
18602
18913
|
}
|
|
@@ -18604,15 +18915,15 @@ async function tryAcquireConsolidationLock(memoryDir) {
|
|
|
18604
18915
|
return mtimeMs ?? 0;
|
|
18605
18916
|
}
|
|
18606
18917
|
async function rollbackConsolidationLock(memoryDir, priorMtime) {
|
|
18607
|
-
const
|
|
18918
|
+
const path31 = lockPath(memoryDir);
|
|
18608
18919
|
try {
|
|
18609
18920
|
if (priorMtime === 0) {
|
|
18610
|
-
await unlink(
|
|
18921
|
+
await unlink(path31);
|
|
18611
18922
|
return;
|
|
18612
18923
|
}
|
|
18613
|
-
await writeFile4(
|
|
18924
|
+
await writeFile4(path31, "");
|
|
18614
18925
|
const t = priorMtime / 1e3;
|
|
18615
|
-
await utimes(
|
|
18926
|
+
await utimes(path31, t, t);
|
|
18616
18927
|
} catch (e) {
|
|
18617
18928
|
console.log(`[autoDream] rollback failed: ${e.message} \u2014 next trigger delayed to minHours`);
|
|
18618
18929
|
}
|
|
@@ -18895,34 +19206,30 @@ var handle_query_exports = {};
|
|
|
18895
19206
|
__export(handle_query_exports, {
|
|
18896
19207
|
handleQuery: () => handleQuery,
|
|
18897
19208
|
resetSessionStartInjection: () => resetSessionStartInjection,
|
|
18898
|
-
resetWorkModeInjection: () => resetWorkModeInjection,
|
|
18899
19209
|
resolveSystemPrompt: () => resolveSystemPrompt
|
|
18900
19210
|
});
|
|
18901
19211
|
import { readFileSync as readFileSync25, existsSync as existsSync22 } from "node:fs";
|
|
18902
19212
|
import { join as join33, resolve as resolve8 } from "node:path";
|
|
18903
|
-
import * as
|
|
19213
|
+
import * as path28 from "node:path";
|
|
18904
19214
|
function resolveSystemPrompt(v) {
|
|
18905
19215
|
return typeof v === "function" ? v() : v || "";
|
|
18906
19216
|
}
|
|
18907
19217
|
function resetSessionStartInjection(sessionId) {
|
|
18908
19218
|
sessionStartDone.delete(sessionId);
|
|
18909
19219
|
}
|
|
18910
|
-
function resetWorkModeInjection(sessionId) {
|
|
18911
|
-
workModeInjected.delete(sessionId);
|
|
18912
|
-
}
|
|
18913
19220
|
function loadExternalChanRules(workspace) {
|
|
18914
|
-
const
|
|
18915
|
-
if (externalChanRulesCache && externalChanRulesCache.path ===
|
|
19221
|
+
const path31 = join33(workspace, "prompts", "external-chan-rules.md");
|
|
19222
|
+
if (externalChanRulesCache && externalChanRulesCache.path === path31) return externalChanRulesCache;
|
|
18916
19223
|
let content = "";
|
|
18917
|
-
if (existsSync22(
|
|
19224
|
+
if (existsSync22(path31)) {
|
|
18918
19225
|
try {
|
|
18919
|
-
content = readFileSync25(
|
|
19226
|
+
content = readFileSync25(path31, "utf-8").trim();
|
|
18920
19227
|
} catch (e) {
|
|
18921
19228
|
console.warn(`[external-chan-rules] Failed to load: ${e}`);
|
|
18922
19229
|
}
|
|
18923
19230
|
}
|
|
18924
|
-
externalChanRulesCache = { path:
|
|
18925
|
-
console.log(`[external-chan-rules] Loaded ${content.length} chars from ${
|
|
19231
|
+
externalChanRulesCache = { path: path31, content };
|
|
19232
|
+
console.log(`[external-chan-rules] Loaded ${content.length} chars from ${path31}`);
|
|
18926
19233
|
return externalChanRulesCache;
|
|
18927
19234
|
}
|
|
18928
19235
|
function getExternalChanRulesBlock(inboundMeta, workspace) {
|
|
@@ -19130,7 +19437,13 @@ ${text}` : text });
|
|
|
19130
19437
|
const isLight = isLightMode(chatMode, channelName) && chatMode !== "emotion";
|
|
19131
19438
|
const lightN = resolveLightN(channelName);
|
|
19132
19439
|
const lightHistory = buildLightHistory(history, { isLight, lightN, channelName, chatMode, recallFull: emotionStripped });
|
|
19133
|
-
const
|
|
19440
|
+
const voiceFastOn = channelName === "voice-chat" && chatMode === "work";
|
|
19441
|
+
const finalHistory = voiceFastOn ? voiceFastView(lightHistory, {
|
|
19442
|
+
keepTurns: liveConfig.get("voiceChat.voiceFast.keepTurns") ?? 5,
|
|
19443
|
+
toolCap: liveConfig.get("voiceChat.voiceFast.toolCap") ?? 500,
|
|
19444
|
+
argCap: liveConfig.get("voiceChat.voiceFast.argCap") ?? 100
|
|
19445
|
+
}) : lightHistory;
|
|
19446
|
+
const messages = [...finalHistory, msg.user(userMsgContent)];
|
|
19134
19447
|
if (deps.mcpManager && !deps.mcpManager.isMcpDeltaSent(sessionId)) {
|
|
19135
19448
|
const delta = deps.mcpManager.getMcpDelta();
|
|
19136
19449
|
if (delta && delta.addedBlocks.length > 0) {
|
|
@@ -19184,30 +19497,6 @@ ${text}` : text });
|
|
|
19184
19497
|
}
|
|
19185
19498
|
}
|
|
19186
19499
|
}
|
|
19187
|
-
if (chatMode === "emotion") {
|
|
19188
|
-
if (workModeInjected.has(sessionId)) workModeInjected.delete(sessionId);
|
|
19189
|
-
} else if (!workModeInjected.has(sessionId)) {
|
|
19190
|
-
workModeInjected.add(sessionId);
|
|
19191
|
-
try {
|
|
19192
|
-
const sr = await executeSessionStartHooks(channelName === "cli" ? "cli" : "channel", {
|
|
19193
|
-
sessionId,
|
|
19194
|
-
workspace,
|
|
19195
|
-
cwd: workspace,
|
|
19196
|
-
channel: channelName === "cli" ? "console" : channelName,
|
|
19197
|
-
senderId: inboundMeta?.from || "",
|
|
19198
|
-
channelType: inboundMeta?.channelType || "",
|
|
19199
|
-
source
|
|
19200
|
-
});
|
|
19201
|
-
if (sr.additionalContexts && sr.additionalContexts.length > 0) {
|
|
19202
|
-
const att = createAttachmentMessage({ type: "session_start", text: sr.additionalContexts.join("\n\n") });
|
|
19203
|
-
history.push(att);
|
|
19204
|
-
messages.push(att);
|
|
19205
|
-
console.log(`[hooks] work-mode injection: ${sr.additionalContexts.length} additionalContext(s) at END of messages (session ${sessionId}, cache-safe, persisted)`);
|
|
19206
|
-
}
|
|
19207
|
-
} catch (err) {
|
|
19208
|
-
console.warn(`[hooks] work-mode injection error: ${err.message}`);
|
|
19209
|
-
}
|
|
19210
|
-
}
|
|
19211
19500
|
const pendingNotifications2 = drainPendingNotifications();
|
|
19212
19501
|
if (pendingNotifications2.length > 0) {
|
|
19213
19502
|
messages.push(createAttachmentMessage({
|
|
@@ -19228,7 +19517,7 @@ ${text}` : text });
|
|
|
19228
19517
|
}));
|
|
19229
19518
|
console.log(`[handle-query] Injected ${teammateMsgs.length} teammate message(s): ${teammateMsgs.map((m) => `[from=${m.from}] ${(m.text || "").slice(0, 80).replace(/\n/g, " ")}`).join(" | ")}`);
|
|
19230
19519
|
}
|
|
19231
|
-
if (channelName !== "heartbeat" && channelName !== "cron" && channelName !== "inner-voice" && channelName !== "
|
|
19520
|
+
if (channelName !== "heartbeat" && channelName !== "cron" && channelName !== "inner-voice" && channelName !== "proactive") {
|
|
19232
19521
|
sessions.touch(sessionId);
|
|
19233
19522
|
}
|
|
19234
19523
|
const toolContext = {
|
|
@@ -19672,7 +19961,7 @@ stack: ${err.stack ?? "(none)"}`);
|
|
|
19672
19961
|
}
|
|
19673
19962
|
} catch (err) {
|
|
19674
19963
|
try {
|
|
19675
|
-
(await import("node:fs")).appendFileSync(join33(process.env.ENGINE7_STATE_DIR ||
|
|
19964
|
+
(await import("node:fs")).appendFileSync(join33(process.env.ENGINE7_STATE_DIR || path28.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7"), "logs", "autoDream-debug.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] [handle-query] autoDream trigger TRY-CATCH: ${err.message}
|
|
19676
19965
|
stack: ${err.stack ?? "(none)"}
|
|
19677
19966
|
`);
|
|
19678
19967
|
} catch {
|
|
@@ -19690,7 +19979,7 @@ function roughTokenCount(messages) {
|
|
|
19690
19979
|
}
|
|
19691
19980
|
return total;
|
|
19692
19981
|
}
|
|
19693
|
-
var sessionStartDone,
|
|
19982
|
+
var sessionStartDone, externalChanRulesCache;
|
|
19694
19983
|
var init_handle_query = __esm({
|
|
19695
19984
|
"src/handle-query.ts"() {
|
|
19696
19985
|
"use strict";
|
|
@@ -19710,9 +19999,9 @@ var init_handle_query = __esm({
|
|
|
19710
19999
|
init_findRelevantMemoriesEveros();
|
|
19711
20000
|
init_paths();
|
|
19712
20001
|
init_light_mode();
|
|
20002
|
+
init_voiceFastView();
|
|
19713
20003
|
init_sender_context();
|
|
19714
20004
|
sessionStartDone = /* @__PURE__ */ new Set();
|
|
19715
|
-
workModeInjected = /* @__PURE__ */ new Set();
|
|
19716
20005
|
externalChanRulesCache = null;
|
|
19717
20006
|
}
|
|
19718
20007
|
});
|
|
@@ -20218,20 +20507,20 @@ __export(cli_travel_exports, {
|
|
|
20218
20507
|
loadTravelConfig: () => loadTravelConfig,
|
|
20219
20508
|
saveTravelConfig: () => saveTravelConfig
|
|
20220
20509
|
});
|
|
20221
|
-
import * as
|
|
20222
|
-
import * as
|
|
20510
|
+
import * as path29 from "node:path";
|
|
20511
|
+
import * as fs27 from "node:fs";
|
|
20223
20512
|
import * as os4 from "node:os";
|
|
20224
20513
|
import { execSync as execSync2 } from "node:child_process";
|
|
20225
20514
|
function loadTravelConfig() {
|
|
20226
20515
|
try {
|
|
20227
|
-
if (!
|
|
20228
|
-
return JSON.parse(
|
|
20516
|
+
if (!fs27.existsSync(CONFIG_PATH)) return null;
|
|
20517
|
+
return JSON.parse(fs27.readFileSync(CONFIG_PATH, "utf-8"));
|
|
20229
20518
|
} catch {
|
|
20230
20519
|
return null;
|
|
20231
20520
|
}
|
|
20232
20521
|
}
|
|
20233
20522
|
function saveTravelConfig(cfg) {
|
|
20234
|
-
|
|
20523
|
+
fs27.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
|
|
20235
20524
|
}
|
|
20236
20525
|
function sanitizeContent(content, dirs) {
|
|
20237
20526
|
let result2 = content;
|
|
@@ -20256,7 +20545,7 @@ function restoreContent(content, dirs) {
|
|
|
20256
20545
|
return result2;
|
|
20257
20546
|
}
|
|
20258
20547
|
function isTextFile(filePath) {
|
|
20259
|
-
const ext =
|
|
20548
|
+
const ext = path29.extname(filePath).toLowerCase();
|
|
20260
20549
|
return TEXT_EXTENSIONS.has(ext);
|
|
20261
20550
|
}
|
|
20262
20551
|
function shouldExclude(name) {
|
|
@@ -20271,14 +20560,14 @@ function shouldExclude(name) {
|
|
|
20271
20560
|
}
|
|
20272
20561
|
function collectFiles(rootDir, includeSet, optionalSet) {
|
|
20273
20562
|
const files = [];
|
|
20274
|
-
const entries2 =
|
|
20563
|
+
const entries2 = fs27.readdirSync(rootDir, { withFileTypes: true });
|
|
20275
20564
|
for (const entry of entries2) {
|
|
20276
20565
|
if (shouldExclude(entry.name)) continue;
|
|
20277
|
-
const fullPath =
|
|
20278
|
-
const realPath =
|
|
20566
|
+
const fullPath = path29.join(rootDir, entry.name);
|
|
20567
|
+
const realPath = fs27.realpathSync(fullPath);
|
|
20279
20568
|
if (realPath !== fullPath) {
|
|
20280
20569
|
try {
|
|
20281
|
-
const lstat =
|
|
20570
|
+
const lstat = fs27.lstatSync(fullPath);
|
|
20282
20571
|
if (lstat.isSymbolicLink()) {
|
|
20283
20572
|
continue;
|
|
20284
20573
|
}
|
|
@@ -20299,12 +20588,12 @@ function collectFiles(rootDir, includeSet, optionalSet) {
|
|
|
20299
20588
|
function collectAllFiles(dir) {
|
|
20300
20589
|
const files = [];
|
|
20301
20590
|
try {
|
|
20302
|
-
const entries2 =
|
|
20591
|
+
const entries2 = fs27.readdirSync(dir, { withFileTypes: true });
|
|
20303
20592
|
for (const entry of entries2) {
|
|
20304
20593
|
if (shouldExclude(entry.name)) continue;
|
|
20305
|
-
const fullPath =
|
|
20594
|
+
const fullPath = path29.join(dir, entry.name);
|
|
20306
20595
|
try {
|
|
20307
|
-
if (
|
|
20596
|
+
if (fs27.lstatSync(fullPath).isSymbolicLink()) continue;
|
|
20308
20597
|
} catch {
|
|
20309
20598
|
}
|
|
20310
20599
|
if (entry.isDirectory()) {
|
|
@@ -20319,16 +20608,16 @@ function collectAllFiles(dir) {
|
|
|
20319
20608
|
}
|
|
20320
20609
|
function readMainEngineUuid(agentsDir) {
|
|
20321
20610
|
try {
|
|
20322
|
-
const platformMapPath =
|
|
20323
|
-
const indexMapPath =
|
|
20324
|
-
if (!
|
|
20325
|
-
const platformMap = JSON.parse(
|
|
20611
|
+
const platformMapPath = path29.join(agentsDir, "main", "sessions", "platform-map.json");
|
|
20612
|
+
const indexMapPath = path29.join(agentsDir, "main", "sessions", "session-index.json");
|
|
20613
|
+
if (!fs27.existsSync(platformMapPath) || !fs27.existsSync(indexMapPath)) return null;
|
|
20614
|
+
const platformMap = JSON.parse(fs27.readFileSync(platformMapPath, "utf-8"));
|
|
20326
20615
|
const mainPlatformId = platformMap["scope:main"] || platformMap["main"];
|
|
20327
20616
|
if (!mainPlatformId) return null;
|
|
20328
|
-
const indexMap = JSON.parse(
|
|
20617
|
+
const indexMap = JSON.parse(fs27.readFileSync(indexMapPath, "utf-8"));
|
|
20329
20618
|
const entry = indexMap[mainPlatformId];
|
|
20330
20619
|
if (!entry || !entry.file) return null;
|
|
20331
|
-
const basename8 =
|
|
20620
|
+
const basename8 = path29.basename(entry.file).replace(/\.jsonl$/, "");
|
|
20332
20621
|
return basename8;
|
|
20333
20622
|
} catch {
|
|
20334
20623
|
return null;
|
|
@@ -20336,13 +20625,13 @@ function readMainEngineUuid(agentsDir) {
|
|
|
20336
20625
|
}
|
|
20337
20626
|
function collectRecentSessions(agentsDir, _days = 7) {
|
|
20338
20627
|
const files = [];
|
|
20339
|
-
if (!
|
|
20628
|
+
if (!fs27.existsSync(agentsDir)) return files;
|
|
20340
20629
|
const sessionGroups = /* @__PURE__ */ new Map();
|
|
20341
20630
|
function scanSessionsDir(dir) {
|
|
20342
20631
|
try {
|
|
20343
|
-
const entries2 =
|
|
20632
|
+
const entries2 = fs27.readdirSync(dir, { withFileTypes: true });
|
|
20344
20633
|
for (const entry of entries2) {
|
|
20345
|
-
const fullPath =
|
|
20634
|
+
const fullPath = path29.join(dir, entry.name);
|
|
20346
20635
|
if (entry.isDirectory()) {
|
|
20347
20636
|
scanSessionsDir(fullPath);
|
|
20348
20637
|
continue;
|
|
@@ -20366,7 +20655,7 @@ function collectRecentSessions(agentsDir, _days = 7) {
|
|
|
20366
20655
|
if (entry.name.endsWith(".jsonl")) {
|
|
20367
20656
|
group.jsonl = fullPath;
|
|
20368
20657
|
} else {
|
|
20369
|
-
const stat4 =
|
|
20658
|
+
const stat4 = fs27.statSync(fullPath);
|
|
20370
20659
|
group.archived.push({ file: fullPath, mtime: stat4.mtimeMs });
|
|
20371
20660
|
}
|
|
20372
20661
|
}
|
|
@@ -20385,37 +20674,37 @@ function collectRecentSessions(agentsDir, _days = 7) {
|
|
|
20385
20674
|
}
|
|
20386
20675
|
async function doExport(opts) {
|
|
20387
20676
|
const { agentName, stateDir, note, dryRun: dryRun2 } = opts;
|
|
20388
|
-
const workspace = (opts.workspace ||
|
|
20389
|
-
const engineHome =
|
|
20677
|
+
const workspace = (opts.workspace || path29.join(stateDir, "workspace")).replace(/[/\\]+$/, "");
|
|
20678
|
+
const engineHome = path29.join(os4.homedir(), ".engine7").replace(/[/\\]+$/, "");
|
|
20390
20679
|
console.log(`\u{1F4E6} engine7 export`);
|
|
20391
20680
|
console.log(` agent: ${agentName}`);
|
|
20392
20681
|
console.log(` state: ${stateDir}`);
|
|
20393
20682
|
console.log(` workspace: ${workspace}`);
|
|
20394
|
-
if (!
|
|
20683
|
+
if (!fs27.existsSync(workspace)) {
|
|
20395
20684
|
console.error(`\u274C workspace \u4E0D\u5B58\u5728: ${workspace}`);
|
|
20396
20685
|
process.exit(1);
|
|
20397
20686
|
}
|
|
20398
20687
|
const dirs = { workspace, stateDir, engineHome };
|
|
20399
20688
|
const wsFiles = collectFiles(workspace, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL);
|
|
20400
|
-
const sessionFiles = collectRecentSessions(
|
|
20401
|
-
const configsDir =
|
|
20689
|
+
const sessionFiles = collectRecentSessions(path29.join(stateDir, "agents"), 7);
|
|
20690
|
+
const configsDir = path29.join(stateDir, "configs");
|
|
20402
20691
|
const configFiles = [];
|
|
20403
|
-
if (
|
|
20692
|
+
if (fs27.existsSync(configsDir)) {
|
|
20404
20693
|
for (const f of collectAllFiles(configsDir)) {
|
|
20405
|
-
if (shouldExclude(
|
|
20694
|
+
if (shouldExclude(path29.basename(f))) continue;
|
|
20406
20695
|
configFiles.push(f);
|
|
20407
20696
|
}
|
|
20408
20697
|
}
|
|
20409
20698
|
const EVEROS_SKIP = /* @__PURE__ */ new Set([".tmp", ".lock", "import.log", "import_progress.json"]);
|
|
20410
|
-
const everosDir =
|
|
20699
|
+
const everosDir = path29.join(stateDir, ".everos");
|
|
20411
20700
|
const everosFiles = [];
|
|
20412
|
-
if (
|
|
20701
|
+
if (fs27.existsSync(everosDir)) {
|
|
20413
20702
|
for (const f of collectAllFiles(everosDir)) {
|
|
20414
|
-
if (EVEROS_SKIP.has(
|
|
20703
|
+
if (EVEROS_SKIP.has(path29.basename(f))) continue;
|
|
20415
20704
|
everosFiles.push(f);
|
|
20416
20705
|
}
|
|
20417
|
-
const walFile =
|
|
20418
|
-
if (
|
|
20706
|
+
const walFile = path29.join(everosDir, ".index", "sqlite", "system.db-wal");
|
|
20707
|
+
if (fs27.existsSync(walFile) && fs27.statSync(walFile).size > 0) {
|
|
20419
20708
|
console.warn(`\u26A0\uFE0F .everos/system.db-wal \u975E\u7A7A\u2014\u2014everos \u670D\u52A1\u53EF\u80FD\u6B63\u5728\u5199\u5165\uFF0C\u5FEB\u7167\u53EF\u80FD\u4E0D\u4E00\u81F4`);
|
|
20420
20709
|
console.warn(` \u5EFA\u8BAE: \u5148\u505C everos \u670D\u52A1\u518D export\uFF0C\u6216 import \u540E\u91CD\u5EFA\u7D22\u5F15`);
|
|
20421
20710
|
}
|
|
@@ -20423,16 +20712,16 @@ async function doExport(opts) {
|
|
|
20423
20712
|
console.log(` workspace \u6587\u4EF6: ${wsFiles.length}`);
|
|
20424
20713
|
console.log(` session jsonl: ${sessionFiles.length} (\u6700\u8FD17\u5929)`);
|
|
20425
20714
|
console.log(` configs: ${configFiles.length}`);
|
|
20426
|
-
console.log(` everos: ${everosFiles.length} (${(everosFiles.reduce((s, f) => s +
|
|
20715
|
+
console.log(` everos: ${everosFiles.length} (${(everosFiles.reduce((s, f) => s + fs27.statSync(f).size, 0) / 1024 / 1024).toFixed(1)} MB)`);
|
|
20427
20716
|
if (dryRun2) {
|
|
20428
20717
|
console.log(`
|
|
20429
20718
|
[DRY RUN] \u4F1A\u6253\u5305\u4EE5\u4E0B\u6587\u4EF6:`);
|
|
20430
|
-
wsFiles.slice(0, 20).forEach((f) => console.log(` ${
|
|
20719
|
+
wsFiles.slice(0, 20).forEach((f) => console.log(` ${path29.relative(workspace, f)}`));
|
|
20431
20720
|
if (wsFiles.length > 20) console.log(` ... \u8FD8\u6709 ${wsFiles.length - 20} \u4E2A\u6587\u4EF6`);
|
|
20432
20721
|
if (everosFiles.length > 0) {
|
|
20433
20722
|
console.log(`
|
|
20434
20723
|
[DRY RUN] everos (${everosFiles.length} \u6587\u4EF6):`);
|
|
20435
|
-
everosFiles.slice(0, 10).forEach((f) => console.log(` ${
|
|
20724
|
+
everosFiles.slice(0, 10).forEach((f) => console.log(` ${path29.relative(stateDir, f)}`));
|
|
20436
20725
|
if (everosFiles.length > 10) console.log(` ... \u8FD8\u6709 ${everosFiles.length - 10} \u4E2A\u6587\u4EF6`);
|
|
20437
20726
|
}
|
|
20438
20727
|
console.log(`
|
|
@@ -20441,46 +20730,46 @@ async function doExport(opts) {
|
|
|
20441
20730
|
}
|
|
20442
20731
|
const now = /* @__PURE__ */ new Date();
|
|
20443
20732
|
const version = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, "0")}${String(now.getDate()).padStart(2, "0")}-${String(now.getHours()).padStart(2, "0")}${String(now.getMinutes()).padStart(2, "0")}`;
|
|
20444
|
-
const tmpDir =
|
|
20445
|
-
|
|
20446
|
-
const stagingDir =
|
|
20447
|
-
|
|
20733
|
+
const tmpDir = path29.join(os4.tmpdir(), `engine7-export-${agentName}-${version}`);
|
|
20734
|
+
fs27.mkdirSync(tmpDir, { recursive: true });
|
|
20735
|
+
const stagingDir = path29.join(tmpDir, agentName);
|
|
20736
|
+
fs27.mkdirSync(stagingDir, { recursive: true });
|
|
20448
20737
|
let fileCount = 0;
|
|
20449
20738
|
let totalSize = 0;
|
|
20450
20739
|
let copyFail = 0;
|
|
20451
20740
|
const copyOne = (srcFile, relRoot, destRoot) => {
|
|
20452
|
-
const relPath =
|
|
20453
|
-
const destFile =
|
|
20454
|
-
|
|
20741
|
+
const relPath = path29.relative(relRoot, srcFile);
|
|
20742
|
+
const destFile = path29.join(destRoot, relPath);
|
|
20743
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20455
20744
|
try {
|
|
20456
20745
|
if (isTextFile(srcFile)) {
|
|
20457
|
-
const content =
|
|
20458
|
-
|
|
20746
|
+
const content = fs27.readFileSync(srcFile, "utf-8");
|
|
20747
|
+
fs27.writeFileSync(destFile, sanitizeContent(content, dirs));
|
|
20459
20748
|
} else {
|
|
20460
|
-
|
|
20749
|
+
fs27.copyFileSync(srcFile, destFile);
|
|
20461
20750
|
}
|
|
20462
20751
|
fileCount++;
|
|
20463
|
-
totalSize +=
|
|
20752
|
+
totalSize += fs27.statSync(srcFile).size;
|
|
20464
20753
|
} catch (e) {
|
|
20465
20754
|
copyFail++;
|
|
20466
20755
|
console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
|
|
20467
20756
|
}
|
|
20468
20757
|
};
|
|
20469
|
-
for (const srcFile of wsFiles) copyOne(srcFile, workspace,
|
|
20758
|
+
for (const srcFile of wsFiles) copyOne(srcFile, workspace, path29.join(stagingDir, "workspace"));
|
|
20470
20759
|
for (const srcFile of sessionFiles) {
|
|
20471
|
-
const relPath =
|
|
20472
|
-
const destFile =
|
|
20473
|
-
|
|
20760
|
+
const relPath = path29.relative(stateDir, srcFile);
|
|
20761
|
+
const destFile = path29.join(stagingDir, relPath);
|
|
20762
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20474
20763
|
try {
|
|
20475
|
-
let content =
|
|
20764
|
+
let content = fs27.readFileSync(srcFile, "utf-8");
|
|
20476
20765
|
content = sanitizeContent(content, dirs);
|
|
20477
|
-
const baseName =
|
|
20766
|
+
const baseName = path29.basename(srcFile);
|
|
20478
20767
|
if (baseName === "session-index.json" || baseName === "platform-map.json") {
|
|
20479
20768
|
content = content.split("\\\\").join("/");
|
|
20480
20769
|
}
|
|
20481
|
-
|
|
20770
|
+
fs27.writeFileSync(destFile, content);
|
|
20482
20771
|
fileCount++;
|
|
20483
|
-
totalSize +=
|
|
20772
|
+
totalSize += fs27.statSync(srcFile).size;
|
|
20484
20773
|
} catch (e) {
|
|
20485
20774
|
copyFail++;
|
|
20486
20775
|
console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
|
|
@@ -20502,13 +20791,13 @@ async function doExport(opts) {
|
|
|
20502
20791
|
totalSize,
|
|
20503
20792
|
note
|
|
20504
20793
|
};
|
|
20505
|
-
|
|
20506
|
-
const archiveFile =
|
|
20794
|
+
fs27.writeFileSync(path29.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2));
|
|
20795
|
+
const archiveFile = path29.join(tmpDir, `${agentName}-${version}.tar.gz`);
|
|
20507
20796
|
console.log(`
|
|
20508
20797
|
\u{1F5DC}\uFE0F \u6253\u5305\u4E2D...`);
|
|
20509
20798
|
const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
|
|
20510
20799
|
execSync2(`"${tarExe}" -czf "${archiveFile}" -C "${tmpDir}" ${agentName}`, { stdio: "pipe" });
|
|
20511
|
-
const archiveSize =
|
|
20800
|
+
const archiveSize = fs27.statSync(archiveFile).size;
|
|
20512
20801
|
console.log(`\u2705 \u6253\u5305\u5B8C\u6210: ${archiveFile} (${(archiveSize / 1024 / 1024).toFixed(1)} MB, ${fileCount} \u6587\u4EF6${copyFail ? `, \u5931\u8D25 ${copyFail}` : ""})`);
|
|
20513
20802
|
const cfg = loadTravelConfig();
|
|
20514
20803
|
if (!cfg || !cfg.githubToken) {
|
|
@@ -20531,8 +20820,8 @@ async function doImport(opts) {
|
|
|
20531
20820
|
console.error(` \u914D\u7F6E: \u7F16\u8F91 ${CONFIG_PATH}`);
|
|
20532
20821
|
process.exit(1);
|
|
20533
20822
|
}
|
|
20534
|
-
const tmpDir =
|
|
20535
|
-
|
|
20823
|
+
const tmpDir = path29.join(os4.tmpdir(), `engine7-import-${agentName}-${Date.now()}`);
|
|
20824
|
+
fs27.mkdirSync(tmpDir, { recursive: true });
|
|
20536
20825
|
const archiveFile = await downloadFromGitHub(cfg, agentName, version, tmpDir);
|
|
20537
20826
|
console.log(`\u2705 \u4E0B\u8F7D\u5B8C\u6210: ${archiveFile}`);
|
|
20538
20827
|
if (dryRun2) {
|
|
@@ -20543,99 +20832,99 @@ async function doImport(opts) {
|
|
|
20543
20832
|
console.log(`\u{1F4C2} \u89E3\u5305\u4E2D...`);
|
|
20544
20833
|
const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
|
|
20545
20834
|
execSync2(`"${tarExe}" -xzf "${archiveFile}" -C "${tmpDir}"`, { stdio: "pipe" });
|
|
20546
|
-
const stagingDir =
|
|
20547
|
-
const manifestPath =
|
|
20548
|
-
if (!
|
|
20835
|
+
const stagingDir = path29.join(tmpDir, agentName);
|
|
20836
|
+
const manifestPath = path29.join(stagingDir, "manifest.json");
|
|
20837
|
+
if (!fs27.existsSync(manifestPath)) {
|
|
20549
20838
|
console.error(`\u274C manifest.json \u4E0D\u5B58\u5728\uFF0C\u6587\u4EF6\u53EF\u80FD\u635F\u574F`);
|
|
20550
20839
|
process.exit(1);
|
|
20551
20840
|
}
|
|
20552
|
-
const manifest = JSON.parse(
|
|
20553
|
-
const workspace =
|
|
20554
|
-
const engineHome =
|
|
20841
|
+
const manifest = JSON.parse(fs27.readFileSync(manifestPath, "utf-8"));
|
|
20842
|
+
const workspace = path29.join(stateDir, "workspace").replace(/\\/g, "/").replace(/[/\\]+$/, "");
|
|
20843
|
+
const engineHome = path29.join(os4.homedir(), ".engine7").replace(/\\/g, "/").replace(/[/\\]+$/, "");
|
|
20555
20844
|
const dirs = { workspace, stateDir: stateDir.replace(/\\/g, "/").replace(/[/\\]+$/, ""), engineHome };
|
|
20556
20845
|
console.log(` \u7248\u672C: ${manifest.version}`);
|
|
20557
20846
|
console.log(` \u521B\u5EFA: ${manifest.createdAt}`);
|
|
20558
20847
|
console.log(` \u6587\u4EF6\u6570: ${manifest.fileCount}`);
|
|
20559
|
-
const wsStaging =
|
|
20848
|
+
const wsStaging = path29.join(stagingDir, "workspace");
|
|
20560
20849
|
let restoredCount = 0;
|
|
20561
20850
|
let skipCount = 0;
|
|
20562
|
-
if (
|
|
20851
|
+
if (fs27.existsSync(wsStaging)) {
|
|
20563
20852
|
const allFiles = collectAllFiles(wsStaging);
|
|
20564
20853
|
for (const srcFile of allFiles) {
|
|
20565
|
-
const relPath =
|
|
20566
|
-
const destFile =
|
|
20567
|
-
|
|
20854
|
+
const relPath = path29.relative(wsStaging, srcFile);
|
|
20855
|
+
const destFile = path29.join(workspace, relPath);
|
|
20856
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20568
20857
|
try {
|
|
20569
20858
|
if (isTextFile(srcFile)) {
|
|
20570
|
-
const content =
|
|
20571
|
-
|
|
20859
|
+
const content = fs27.readFileSync(srcFile, "utf-8");
|
|
20860
|
+
fs27.writeFileSync(destFile, restoreContent(content, dirs));
|
|
20572
20861
|
} else {
|
|
20573
|
-
|
|
20862
|
+
fs27.copyFileSync(srcFile, destFile);
|
|
20574
20863
|
}
|
|
20575
20864
|
restoredCount++;
|
|
20576
20865
|
} catch (e) {
|
|
20577
20866
|
skipCount++;
|
|
20578
|
-
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${
|
|
20867
|
+
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path29.relative(wsStaging, srcFile)} (${e.code || e.message})`);
|
|
20579
20868
|
}
|
|
20580
20869
|
}
|
|
20581
20870
|
}
|
|
20582
|
-
const agentsStaging =
|
|
20583
|
-
if (
|
|
20871
|
+
const agentsStaging = path29.join(stagingDir, "agents");
|
|
20872
|
+
if (fs27.existsSync(agentsStaging)) {
|
|
20584
20873
|
const sessionFiles = collectAllFiles(agentsStaging);
|
|
20585
20874
|
for (const srcFile of sessionFiles) {
|
|
20586
|
-
const relPath =
|
|
20587
|
-
const destFile =
|
|
20588
|
-
|
|
20589
|
-
const content =
|
|
20590
|
-
|
|
20875
|
+
const relPath = path29.relative(stagingDir, srcFile);
|
|
20876
|
+
const destFile = path29.join(stateDir, relPath);
|
|
20877
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20878
|
+
const content = fs27.readFileSync(srcFile, "utf-8");
|
|
20879
|
+
fs27.writeFileSync(destFile, restoreContent(content, dirs));
|
|
20591
20880
|
restoredCount++;
|
|
20592
20881
|
}
|
|
20593
20882
|
}
|
|
20594
|
-
const configsStaging =
|
|
20595
|
-
if (
|
|
20883
|
+
const configsStaging = path29.join(stagingDir, "configs");
|
|
20884
|
+
if (fs27.existsSync(configsStaging)) {
|
|
20596
20885
|
const cfgFiles = collectAllFiles(configsStaging);
|
|
20597
20886
|
for (const srcFile of cfgFiles) {
|
|
20598
|
-
const relPath =
|
|
20599
|
-
const destFile =
|
|
20600
|
-
|
|
20887
|
+
const relPath = path29.relative(stagingDir, srcFile);
|
|
20888
|
+
const destFile = path29.join(stateDir, relPath);
|
|
20889
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20601
20890
|
if (isTextFile(srcFile)) {
|
|
20602
|
-
const content =
|
|
20603
|
-
|
|
20891
|
+
const content = fs27.readFileSync(srcFile, "utf-8");
|
|
20892
|
+
fs27.writeFileSync(destFile, restoreContent(content, dirs));
|
|
20604
20893
|
} else {
|
|
20605
|
-
|
|
20894
|
+
fs27.copyFileSync(srcFile, destFile);
|
|
20606
20895
|
}
|
|
20607
20896
|
restoredCount++;
|
|
20608
20897
|
}
|
|
20609
20898
|
}
|
|
20610
|
-
const everosStaging =
|
|
20611
|
-
if (
|
|
20899
|
+
const everosStaging = path29.join(stagingDir, ".everos");
|
|
20900
|
+
if (fs27.existsSync(everosStaging)) {
|
|
20612
20901
|
const everosFiles = collectAllFiles(everosStaging);
|
|
20613
20902
|
for (const srcFile of everosFiles) {
|
|
20614
|
-
const relPath =
|
|
20615
|
-
const destFile =
|
|
20616
|
-
|
|
20903
|
+
const relPath = path29.relative(stagingDir, srcFile);
|
|
20904
|
+
const destFile = path29.join(stateDir, relPath);
|
|
20905
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20617
20906
|
try {
|
|
20618
20907
|
if (isTextFile(srcFile)) {
|
|
20619
|
-
const content =
|
|
20620
|
-
|
|
20908
|
+
const content = fs27.readFileSync(srcFile, "utf-8");
|
|
20909
|
+
fs27.writeFileSync(destFile, restoreContent(content, dirs));
|
|
20621
20910
|
} else {
|
|
20622
|
-
|
|
20911
|
+
fs27.copyFileSync(srcFile, destFile);
|
|
20623
20912
|
}
|
|
20624
20913
|
restoredCount++;
|
|
20625
20914
|
} catch (e) {
|
|
20626
20915
|
skipCount++;
|
|
20627
|
-
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${
|
|
20916
|
+
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path29.relative(everosStaging, srcFile)} (${e.code || e.message})`);
|
|
20628
20917
|
}
|
|
20629
20918
|
}
|
|
20630
20919
|
console.log(` everos: ${everosFiles.length} \u6587\u4EF6\u5DF2\u6062\u590D`);
|
|
20631
20920
|
}
|
|
20632
20921
|
console.log(`\u2705 \u6062\u590D\u5B8C\u6210: ${restoredCount} \u6587\u4EF6 \u2192 ${stateDir}${skipCount ? ` (\u8DF3\u8FC7 ${skipCount})` : ""}`);
|
|
20633
20922
|
const platformConfigName = process.platform === "darwin" ? "xiaoke-mac.json" : "xiaoke-win.json";
|
|
20634
|
-
const restoredConfigPath =
|
|
20635
|
-
const configToUse =
|
|
20923
|
+
const restoredConfigPath = path29.join(stateDir, "configs", platformConfigName);
|
|
20924
|
+
const configToUse = fs27.existsSync(restoredConfigPath) ? restoredConfigPath : path29.join(stateDir, "configs", "xiaoke.json");
|
|
20636
20925
|
console.log(`
|
|
20637
20926
|
\u{1F4A1} \u4E0B\u4E00\u6B65: engine7 start --config "${configToUse}"`);
|
|
20638
|
-
|
|
20927
|
+
fs27.rmSync(tmpDir, { recursive: true, force: true });
|
|
20639
20928
|
}
|
|
20640
20929
|
async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
|
|
20641
20930
|
const repo = `${cfg.githubOwner}/${cfg.repoName}`;
|
|
@@ -20665,8 +20954,8 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
|
|
|
20665
20954
|
}
|
|
20666
20955
|
const release2 = await createRes.json();
|
|
20667
20956
|
const uploadUrl = release2.upload_url.replace("{?name,label}", "");
|
|
20668
|
-
const fileBuffer =
|
|
20669
|
-
const fileName =
|
|
20957
|
+
const fileBuffer = fs27.readFileSync(archiveFile);
|
|
20958
|
+
const fileName = path29.basename(archiveFile);
|
|
20670
20959
|
const uploadRes = await fetch(`${uploadUrl}?name=${fileName}`, {
|
|
20671
20960
|
method: "POST",
|
|
20672
20961
|
headers: {
|
|
@@ -20689,7 +20978,7 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
|
|
|
20689
20978
|
throw e;
|
|
20690
20979
|
}
|
|
20691
20980
|
try {
|
|
20692
|
-
|
|
20981
|
+
fs27.rmSync(path29.dirname(archiveFile), { recursive: true, force: true });
|
|
20693
20982
|
} catch {
|
|
20694
20983
|
}
|
|
20695
20984
|
}
|
|
@@ -20721,8 +21010,8 @@ async function downloadFromGitHub(cfg, agentName, version, destDir) {
|
|
|
20721
21010
|
throw new Error(`\u4E0B\u8F7D asset \u5931\u8D25: ${downloadRes.status}`);
|
|
20722
21011
|
}
|
|
20723
21012
|
const buffer = Buffer.from(await downloadRes.arrayBuffer());
|
|
20724
|
-
const archiveFile =
|
|
20725
|
-
|
|
21013
|
+
const archiveFile = path29.join(destDir, asset.name);
|
|
21014
|
+
fs27.writeFileSync(archiveFile, buffer);
|
|
20726
21015
|
return archiveFile;
|
|
20727
21016
|
}
|
|
20728
21017
|
async function getLatestReleaseTag(cfg, agentName) {
|
|
@@ -20747,7 +21036,7 @@ var CONFIG_PATH, PATH_PLACEHOLDERS, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL, WORKS
|
|
|
20747
21036
|
var init_cli_travel = __esm({
|
|
20748
21037
|
"src/cli-travel.ts"() {
|
|
20749
21038
|
"use strict";
|
|
20750
|
-
CONFIG_PATH =
|
|
21039
|
+
CONFIG_PATH = path29.join(os4.homedir(), ".engine7-travel.json");
|
|
20751
21040
|
PATH_PLACEHOLDERS = [
|
|
20752
21041
|
{ placeholder: "{{WORKSPACE}}", getOriginal: (d) => d.workspace },
|
|
20753
21042
|
{ placeholder: "{{ENGINE_HOME}}", getOriginal: (d) => d.engineHome },
|
|
@@ -20823,8 +21112,8 @@ var init_cli_travel = __esm({
|
|
|
20823
21112
|
init_feishu_quick_register();
|
|
20824
21113
|
init_wechat();
|
|
20825
21114
|
init_qr_render();
|
|
20826
|
-
import * as
|
|
20827
|
-
import * as
|
|
21115
|
+
import * as path30 from "node:path";
|
|
21116
|
+
import * as fs28 from "node:fs";
|
|
20828
21117
|
import * as readline3 from "node:readline";
|
|
20829
21118
|
import { fileURLToPath } from "node:url";
|
|
20830
21119
|
var origEmitWarning = process.emitWarning.bind(process);
|
|
@@ -20835,7 +21124,7 @@ process.emitWarning = (warning, ...rest) => {
|
|
|
20835
21124
|
return origEmitWarning(warning, ...rest);
|
|
20836
21125
|
};
|
|
20837
21126
|
var __filename = fileURLToPath(import.meta.url);
|
|
20838
|
-
var __dirname =
|
|
21127
|
+
var __dirname = path30.dirname(__filename);
|
|
20839
21128
|
var SCHEMA_VERSION = 1;
|
|
20840
21129
|
function parseArgs() {
|
|
20841
21130
|
const args = process.argv.slice(2);
|
|
@@ -20860,10 +21149,10 @@ function parseArgs() {
|
|
|
20860
21149
|
}
|
|
20861
21150
|
}
|
|
20862
21151
|
if (!stateDir) {
|
|
20863
|
-
stateDir =
|
|
21152
|
+
stateDir = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
20864
21153
|
console.log(` \u4F7F\u7528\u9ED8\u8BA4\u76EE\u5F55: ${stateDir}`);
|
|
20865
21154
|
}
|
|
20866
|
-
stateDir =
|
|
21155
|
+
stateDir = path30.resolve(stateDir);
|
|
20867
21156
|
return { stateDir, quick, dryRun: dryRun2, force };
|
|
20868
21157
|
}
|
|
20869
21158
|
function printHelp() {
|
|
@@ -20964,10 +21253,10 @@ function getDefaultValues(stateDir) {
|
|
|
20964
21253
|
};
|
|
20965
21254
|
}
|
|
20966
21255
|
function loadExistingValues(stateDir) {
|
|
20967
|
-
const configPath =
|
|
21256
|
+
const configPath = path30.join(stateDir, "configs", "main7.json");
|
|
20968
21257
|
try {
|
|
20969
|
-
if (!
|
|
20970
|
-
const j = JSON.parse(
|
|
21258
|
+
if (!fs28.existsSync(configPath)) return {};
|
|
21259
|
+
const j = JSON.parse(fs28.readFileSync(configPath, "utf8"));
|
|
20971
21260
|
const out = {};
|
|
20972
21261
|
if (j.agents?.defaults?.name) out.agentName = j.agents.defaults.name;
|
|
20973
21262
|
const providers = j.models?.providers || {};
|
|
@@ -21022,15 +21311,15 @@ function loadExistingValues(stateDir) {
|
|
|
21022
21311
|
}
|
|
21023
21312
|
function readSecretsValue(stateDir, envName) {
|
|
21024
21313
|
try {
|
|
21025
|
-
const secretsDir =
|
|
21026
|
-
const cfgBase =
|
|
21314
|
+
const secretsDir = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7-secrets");
|
|
21315
|
+
const cfgBase = path30.basename(stateDir) === ".engine7" ? "main7" : path30.basename(stateDir);
|
|
21027
21316
|
const candidates = [
|
|
21028
|
-
|
|
21029
|
-
|
|
21317
|
+
path30.join(secretsDir, `${cfgBase}.env`),
|
|
21318
|
+
path30.join(stateDir, "configs", `.env.${cfgBase}`)
|
|
21030
21319
|
];
|
|
21031
21320
|
for (const p of candidates) {
|
|
21032
|
-
if (
|
|
21033
|
-
for (const line of
|
|
21321
|
+
if (fs28.existsSync(p)) {
|
|
21322
|
+
for (const line of fs28.readFileSync(p, "utf8").split("\n")) {
|
|
21034
21323
|
const eq = line.indexOf("=");
|
|
21035
21324
|
if (eq > 0 && line.slice(0, eq).trim() === envName) {
|
|
21036
21325
|
return line.slice(eq + 1).trim();
|
|
@@ -21256,7 +21545,7 @@ async function configureWechat(rl, v) {
|
|
|
21256
21545
|
}
|
|
21257
21546
|
}
|
|
21258
21547
|
function generateConfig(v) {
|
|
21259
|
-
const workspace =
|
|
21548
|
+
const workspace = path30.join(v.stateDir, "workspace").replace(/\\/g, "/");
|
|
21260
21549
|
const config = {
|
|
21261
21550
|
schemaVersion: SCHEMA_VERSION,
|
|
21262
21551
|
stateDir: v.stateDir.replace(/\\/g, "/"),
|
|
@@ -21406,45 +21695,45 @@ function generateConfig(v) {
|
|
|
21406
21695
|
}
|
|
21407
21696
|
function buildDirTree(v) {
|
|
21408
21697
|
const d = v.stateDir;
|
|
21409
|
-
const w =
|
|
21698
|
+
const w = path30.join(d, "workspace");
|
|
21410
21699
|
const now = (/* @__PURE__ */ new Date()).toLocaleString("sv-SE", { timeZone: "Asia/Shanghai", hour12: false });
|
|
21411
21700
|
return [
|
|
21412
21701
|
// 目录
|
|
21413
|
-
{ path:
|
|
21414
|
-
{ path:
|
|
21415
|
-
{ path:
|
|
21416
|
-
{ path:
|
|
21417
|
-
{ path:
|
|
21418
|
-
{ path:
|
|
21419
|
-
{ path:
|
|
21420
|
-
{ path:
|
|
21421
|
-
{ path:
|
|
21422
|
-
{ path:
|
|
21423
|
-
{ path:
|
|
21702
|
+
{ path: path30.join(d, "configs"), type: "dir" },
|
|
21703
|
+
{ path: path30.join(d, "state", "agents", "main", "sessions"), type: "dir" },
|
|
21704
|
+
{ path: path30.join(w, "prompts"), type: "dir" },
|
|
21705
|
+
{ path: path30.join(w, "memory", "daily"), type: "dir" },
|
|
21706
|
+
{ path: path30.join(w, "docs", "research"), type: "dir" },
|
|
21707
|
+
{ path: path30.join(w, "docs", "todo"), type: "dir" },
|
|
21708
|
+
{ path: path30.join(w, "docs", "decisions"), type: "dir" },
|
|
21709
|
+
{ path: path30.join(w, "docs", "knowledge"), type: "dir" },
|
|
21710
|
+
{ path: path30.join(w, "docs", "sop"), type: "dir" },
|
|
21711
|
+
{ path: path30.join(d, "logs"), type: "dir" },
|
|
21712
|
+
{ path: path30.join(d, "media", "inbound"), type: "dir" },
|
|
21424
21713
|
// workspace 文件
|
|
21425
21714
|
{
|
|
21426
|
-
path:
|
|
21715
|
+
path: path30.join(w, "SESSION-STATE.md"),
|
|
21427
21716
|
type: "file",
|
|
21428
21717
|
content: readTemplate("workspace/SESSION-STATE.md").replace("{{CURRENT_TIME}}", now)
|
|
21429
21718
|
},
|
|
21430
|
-
{ path:
|
|
21719
|
+
{ path: path30.join(w, "HEARTBEAT.md"), type: "file", content: readTemplate("workspace/HEARTBEAT.md") },
|
|
21431
21720
|
{
|
|
21432
|
-
path:
|
|
21721
|
+
path: path30.join(w, "SOUL.md"),
|
|
21433
21722
|
type: "file",
|
|
21434
21723
|
content: readTemplate("workspace/SOUL.md").replace(/\{\{AGENT_NAME\}\}/g, v.agentName)
|
|
21435
21724
|
},
|
|
21436
|
-
{ path:
|
|
21725
|
+
{ path: path30.join(w, "AGENTS.md"), type: "file", content: readTemplate("workspace/AGENTS.md") },
|
|
21437
21726
|
{
|
|
21438
|
-
path:
|
|
21727
|
+
path: path30.join(w, "prompts", "contacts.md"),
|
|
21439
21728
|
type: "file",
|
|
21440
21729
|
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")
|
|
21441
21730
|
},
|
|
21442
|
-
{ path:
|
|
21443
|
-
{ path:
|
|
21444
|
-
{ path:
|
|
21731
|
+
{ path: path30.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
|
|
21732
|
+
{ path: path30.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" },
|
|
21733
|
+
{ path: path30.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" },
|
|
21445
21734
|
// package.json — 让 agent 目录成为独立 npm 项目根,防止 npm hoisting
|
|
21446
21735
|
{
|
|
21447
|
-
path:
|
|
21736
|
+
path: path30.join(d, "package.json"),
|
|
21448
21737
|
type: "file",
|
|
21449
21738
|
content: JSON.stringify({
|
|
21450
21739
|
name: v.agentName.toLowerCase().replace(/[^a-z0-9-]/g, "-") || "agent",
|
|
@@ -21455,7 +21744,7 @@ function buildDirTree(v) {
|
|
|
21455
21744
|
},
|
|
21456
21745
|
// 启动脚本(根据 OS 生成)
|
|
21457
21746
|
...process.platform === "win32" ? [{
|
|
21458
|
-
path:
|
|
21747
|
+
path: path30.join(d, "start.cmd"),
|
|
21459
21748
|
type: "file",
|
|
21460
21749
|
content: `@echo off
|
|
21461
21750
|
rem Engine 7 startup script
|
|
@@ -21487,7 +21776,7 @@ if %ERRORLEVEL% NEQ 0 (
|
|
|
21487
21776
|
)
|
|
21488
21777
|
`
|
|
21489
21778
|
}] : [{
|
|
21490
|
-
path:
|
|
21779
|
+
path: path30.join(d, "start.sh"),
|
|
21491
21780
|
type: "file",
|
|
21492
21781
|
content: `#!/bin/bash
|
|
21493
21782
|
# Engine 7 startup script
|
|
@@ -21520,13 +21809,13 @@ node "$ENGINE7_BIN" --engine-config configs/main7.json
|
|
|
21520
21809
|
}
|
|
21521
21810
|
function readTemplate(relativePath) {
|
|
21522
21811
|
const candidates = [
|
|
21523
|
-
|
|
21524
|
-
|
|
21525
|
-
|
|
21812
|
+
path30.join(__dirname, "..", "templates", relativePath),
|
|
21813
|
+
path30.join(__dirname, "..", "..", "templates", relativePath),
|
|
21814
|
+
path30.join(process.cwd(), "templates", relativePath)
|
|
21526
21815
|
];
|
|
21527
21816
|
for (const p of candidates) {
|
|
21528
|
-
if (
|
|
21529
|
-
return
|
|
21817
|
+
if (fs28.existsSync(p)) {
|
|
21818
|
+
return fs28.readFileSync(p, "utf-8");
|
|
21530
21819
|
}
|
|
21531
21820
|
}
|
|
21532
21821
|
throw new Error(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${relativePath}\uFF08\u627E\u4E86: ${candidates.join(", ")}\uFF09`);
|
|
@@ -21541,11 +21830,11 @@ function dryRun(entries2) {
|
|
|
21541
21830
|
function execute(entries2) {
|
|
21542
21831
|
for (const e of entries2) {
|
|
21543
21832
|
if (e.type === "dir") {
|
|
21544
|
-
|
|
21833
|
+
fs28.mkdirSync(e.path, { recursive: true });
|
|
21545
21834
|
console.log(` \u{1F4C1} ${e.path}`);
|
|
21546
21835
|
} else {
|
|
21547
|
-
|
|
21548
|
-
|
|
21836
|
+
fs28.mkdirSync(path30.dirname(e.path), { recursive: true });
|
|
21837
|
+
fs28.writeFileSync(e.path, e.content || "", "utf-8");
|
|
21549
21838
|
console.log(` \u{1F4C4} ${e.path}`);
|
|
21550
21839
|
}
|
|
21551
21840
|
}
|
|
@@ -21579,8 +21868,8 @@ async function main() {
|
|
|
21579
21868
|
if (subcommand === "--version" || subcommand === "-v") {
|
|
21580
21869
|
let ver = "unknown";
|
|
21581
21870
|
try {
|
|
21582
|
-
const pkgPath =
|
|
21583
|
-
ver = JSON.parse(
|
|
21871
|
+
const pkgPath = path30.join(path30.dirname(__filename), "..", "package.json");
|
|
21872
|
+
ver = JSON.parse(fs28.readFileSync(pkgPath, "utf8")).version || "unknown";
|
|
21584
21873
|
} catch {
|
|
21585
21874
|
}
|
|
21586
21875
|
console.log(`engine7 ${ver}`);
|
|
@@ -21598,18 +21887,18 @@ async function main() {
|
|
|
21598
21887
|
else if (args[i] === "--config" && args[i + 1]) configName = args[++i].trim();
|
|
21599
21888
|
}
|
|
21600
21889
|
if (!stateDir) {
|
|
21601
|
-
const cwd =
|
|
21602
|
-
if (
|
|
21890
|
+
const cwd = path30.resolve(process.cwd());
|
|
21891
|
+
if (fs28.existsSync(path30.join(cwd, "configs"))) {
|
|
21603
21892
|
stateDir = cwd;
|
|
21604
21893
|
} else {
|
|
21605
|
-
const pointer =
|
|
21606
|
-
if (
|
|
21894
|
+
const pointer = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
|
|
21895
|
+
if (fs28.existsSync(pointer)) {
|
|
21607
21896
|
try {
|
|
21608
|
-
stateDir = JSON.parse(
|
|
21897
|
+
stateDir = JSON.parse(fs28.readFileSync(pointer, "utf8")).stateDir || "";
|
|
21609
21898
|
} catch {
|
|
21610
21899
|
}
|
|
21611
21900
|
}
|
|
21612
|
-
if (!stateDir) stateDir =
|
|
21901
|
+
if (!stateDir) stateDir = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
21613
21902
|
}
|
|
21614
21903
|
}
|
|
21615
21904
|
if (!target && !isLegacyAddchannel) {
|
|
@@ -21629,12 +21918,12 @@ async function main() {
|
|
|
21629
21918
|
process.exit(0);
|
|
21630
21919
|
}
|
|
21631
21920
|
if (channel === "channels") {
|
|
21632
|
-
const configsDir =
|
|
21633
|
-
if (
|
|
21634
|
-
const files =
|
|
21921
|
+
const configsDir = path30.join(stateDir, "configs");
|
|
21922
|
+
if (fs28.existsSync(configsDir)) {
|
|
21923
|
+
const files = fs28.readdirSync(configsDir).filter((f) => f.endsWith(".json"));
|
|
21635
21924
|
for (const f of files) {
|
|
21636
21925
|
try {
|
|
21637
|
-
const j = JSON.parse(
|
|
21926
|
+
const j = JSON.parse(fs28.readFileSync(path30.join(configsDir, f), "utf8"));
|
|
21638
21927
|
if (!j.channels) continue;
|
|
21639
21928
|
console.log(`
|
|
21640
21929
|
\u{1F4C4} ${f}:`);
|
|
@@ -21680,14 +21969,14 @@ async function main() {
|
|
|
21680
21969
|
console.error("\u274C \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25");
|
|
21681
21970
|
process.exit(1);
|
|
21682
21971
|
}
|
|
21683
|
-
const configsDir2 =
|
|
21684
|
-
let configFile2 = configName ?
|
|
21685
|
-
if (!configFile2 || !
|
|
21686
|
-
if (
|
|
21687
|
-
for (const f of
|
|
21688
|
-
const full =
|
|
21972
|
+
const configsDir2 = path30.join(stateDir, "configs");
|
|
21973
|
+
let configFile2 = configName ? path30.join(configsDir2, configName) : "";
|
|
21974
|
+
if (!configFile2 || !fs28.existsSync(configFile2)) {
|
|
21975
|
+
if (fs28.existsSync(configsDir2)) {
|
|
21976
|
+
for (const f of fs28.readdirSync(configsDir2).filter((f2) => f2.endsWith(".json"))) {
|
|
21977
|
+
const full = path30.join(configsDir2, f);
|
|
21689
21978
|
try {
|
|
21690
|
-
if (JSON.parse(
|
|
21979
|
+
if (JSON.parse(fs28.readFileSync(full, "utf8")).channels) {
|
|
21691
21980
|
configFile2 = full;
|
|
21692
21981
|
break;
|
|
21693
21982
|
}
|
|
@@ -21696,11 +21985,11 @@ async function main() {
|
|
|
21696
21985
|
}
|
|
21697
21986
|
}
|
|
21698
21987
|
}
|
|
21699
|
-
if (configFile2 &&
|
|
21700
|
-
const j = JSON.parse(
|
|
21988
|
+
if (configFile2 && fs28.existsSync(configFile2)) {
|
|
21989
|
+
const j = JSON.parse(fs28.readFileSync(configFile2, "utf8"));
|
|
21701
21990
|
j.channels = j.channels || {};
|
|
21702
21991
|
j.channels.feishu = { enabled: true, appId: result2.appId, appSecret: result2.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" };
|
|
21703
|
-
|
|
21992
|
+
fs28.writeFileSync(configFile2, JSON.stringify(j, null, 2), "utf8");
|
|
21704
21993
|
console.log("\u2705 \u98DE\u4E66\u901A\u9053\u5DF2\u5199\u5165: " + configFile2);
|
|
21705
21994
|
console.log("\u91CD\u542F\u751F\u6548: engine7 restart");
|
|
21706
21995
|
} else {
|
|
@@ -21718,16 +22007,16 @@ async function main() {
|
|
|
21718
22007
|
console.error("\u274C \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25\uFF0C\u672A\u4FEE\u6539\u4EFB\u4F55\u914D\u7F6E");
|
|
21719
22008
|
process.exit(1);
|
|
21720
22009
|
}
|
|
21721
|
-
const configsDir =
|
|
22010
|
+
const configsDir = path30.join(stateDir, "configs");
|
|
21722
22011
|
let configFile = "";
|
|
21723
22012
|
if (configName) {
|
|
21724
|
-
configFile =
|
|
21725
|
-
} else if (
|
|
21726
|
-
const candidates =
|
|
22013
|
+
configFile = path30.join(configsDir, configName);
|
|
22014
|
+
} else if (fs28.existsSync(configsDir)) {
|
|
22015
|
+
const candidates = fs28.readdirSync(configsDir).filter((f) => f.endsWith(".json"));
|
|
21727
22016
|
for (const f of candidates) {
|
|
21728
|
-
const full =
|
|
22017
|
+
const full = path30.join(configsDir, f);
|
|
21729
22018
|
try {
|
|
21730
|
-
const j2 = JSON.parse(
|
|
22019
|
+
const j2 = JSON.parse(fs28.readFileSync(full, "utf8"));
|
|
21731
22020
|
if (j2.channels) {
|
|
21732
22021
|
configFile = full;
|
|
21733
22022
|
break;
|
|
@@ -21735,14 +22024,14 @@ async function main() {
|
|
|
21735
22024
|
} catch {
|
|
21736
22025
|
}
|
|
21737
22026
|
}
|
|
21738
|
-
if (!configFile && candidates.length) configFile =
|
|
22027
|
+
if (!configFile && candidates.length) configFile = path30.join(configsDir, candidates[0]);
|
|
21739
22028
|
}
|
|
21740
|
-
if (!configFile || !
|
|
22029
|
+
if (!configFile || !fs28.existsSync(configFile)) {
|
|
21741
22030
|
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");
|
|
21742
22031
|
console.log(JSON.stringify({ wechat: { enabled: true, token: cred.token, accountId: cred.accountId, dmPolicy: "pairing", group: { policy: "disabled" } } }, null, 2));
|
|
21743
22032
|
process.exit(0);
|
|
21744
22033
|
}
|
|
21745
|
-
const j = JSON.parse(
|
|
22034
|
+
const j = JSON.parse(fs28.readFileSync(configFile, "utf8"));
|
|
21746
22035
|
j.channels = j.channels || {};
|
|
21747
22036
|
j.channels.wechat = {
|
|
21748
22037
|
enabled: true,
|
|
@@ -21751,7 +22040,7 @@ async function main() {
|
|
|
21751
22040
|
dmPolicy: "pairing",
|
|
21752
22041
|
group: { policy: "disabled" }
|
|
21753
22042
|
};
|
|
21754
|
-
|
|
22043
|
+
fs28.writeFileSync(configFile, JSON.stringify(j, null, 2), "utf8");
|
|
21755
22044
|
console.log(`
|
|
21756
22045
|
\u2705 \u5FAE\u4FE1\u901A\u9053\u5DF2\u5199\u5165: ${configFile}`);
|
|
21757
22046
|
console.log(` accountId: ${cred.accountId}`);
|
|
@@ -21779,8 +22068,8 @@ async function main() {
|
|
|
21779
22068
|
else if (args[i] === "--note" && args[i + 1]) note = args[++i];
|
|
21780
22069
|
else if (args[i] === "--dry-run") dryRun2 = true;
|
|
21781
22070
|
}
|
|
21782
|
-
if (!exportStateDir) exportStateDir =
|
|
21783
|
-
if (!agentName) agentName =
|
|
22071
|
+
if (!exportStateDir) exportStateDir = path30.resolve(process.cwd());
|
|
22072
|
+
if (!agentName) agentName = path30.basename(exportStateDir);
|
|
21784
22073
|
await doExport2({ agentName, stateDir: exportStateDir, note, dryRun: dryRun2 });
|
|
21785
22074
|
process.exit(0);
|
|
21786
22075
|
}
|
|
@@ -21800,7 +22089,7 @@ async function main() {
|
|
|
21800
22089
|
console.error("\u274C import \u9700\u8981 --state-dir <path>");
|
|
21801
22090
|
process.exit(1);
|
|
21802
22091
|
}
|
|
21803
|
-
if (!agentName) agentName =
|
|
22092
|
+
if (!agentName) agentName = path30.basename(importStateDir);
|
|
21804
22093
|
await doImport2({ agentName, stateDir: importStateDir, version, dryRun: dryRun2 });
|
|
21805
22094
|
process.exit(0);
|
|
21806
22095
|
}
|
|
@@ -21825,18 +22114,18 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
21825
22114
|
}
|
|
21826
22115
|
}
|
|
21827
22116
|
if (!configPath2) {
|
|
21828
|
-
const defaultCfg =
|
|
21829
|
-
const homeCfg =
|
|
21830
|
-
if (
|
|
22117
|
+
const defaultCfg = path30.join("configs", "main7.json");
|
|
22118
|
+
const homeCfg = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
|
|
22119
|
+
if (fs28.existsSync(defaultCfg)) {
|
|
21831
22120
|
configPath2 = defaultCfg;
|
|
21832
|
-
} else if (
|
|
22121
|
+
} else if (fs28.existsSync(homeCfg)) {
|
|
21833
22122
|
configPath2 = homeCfg;
|
|
21834
22123
|
console.log(` \u4F7F\u7528\u9ED8\u8BA4 config: ${homeCfg}`);
|
|
21835
22124
|
} else {
|
|
21836
22125
|
const ptr = readHomePointer();
|
|
21837
22126
|
if (ptr?.stateDir) {
|
|
21838
|
-
const ptrCfg =
|
|
21839
|
-
if (
|
|
22127
|
+
const ptrCfg = path30.join(ptr.stateDir, "configs", "main7.json");
|
|
22128
|
+
if (fs28.existsSync(ptrCfg)) {
|
|
21840
22129
|
configPath2 = ptrCfg;
|
|
21841
22130
|
console.log(` \u4F7F\u7528 config: ${ptrCfg}`);
|
|
21842
22131
|
}
|
|
@@ -21851,19 +22140,19 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
21851
22140
|
}
|
|
21852
22141
|
const { execSync: execSync3, spawn: spawn5 } = await import("node:child_process");
|
|
21853
22142
|
let enginePath;
|
|
21854
|
-
const localPath =
|
|
21855
|
-
if (
|
|
22143
|
+
const localPath = path30.join("node_modules", "engine7", "dist", "main.mjs");
|
|
22144
|
+
if (fs28.existsSync(localPath)) {
|
|
21856
22145
|
enginePath = localPath;
|
|
21857
22146
|
} else {
|
|
21858
|
-
const cliPath =
|
|
21859
|
-
const distDir =
|
|
21860
|
-
const candidate =
|
|
21861
|
-
if (
|
|
22147
|
+
const cliPath = path30.resolve(process.argv[1]);
|
|
22148
|
+
const distDir = path30.dirname(cliPath);
|
|
22149
|
+
const candidate = path30.join(distDir, "main.mjs");
|
|
22150
|
+
if (fs28.existsSync(candidate)) {
|
|
21862
22151
|
enginePath = candidate;
|
|
21863
22152
|
} else {
|
|
21864
22153
|
try {
|
|
21865
22154
|
const globalRoot = execSync3("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
21866
|
-
enginePath =
|
|
22155
|
+
enginePath = path30.join(globalRoot, "engine7", "dist", "main.mjs");
|
|
21867
22156
|
} catch {
|
|
21868
22157
|
console.error("\u274C \u627E\u4E0D\u5230 engine7 main.mjs");
|
|
21869
22158
|
process.exit(1);
|
|
@@ -21873,7 +22162,7 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
21873
22162
|
console.log(label);
|
|
21874
22163
|
console.log(` config: ${configPath2}`);
|
|
21875
22164
|
console.log(` engine: ${enginePath}`);
|
|
21876
|
-
const configName =
|
|
22165
|
+
const configName = path30.basename(configPath2);
|
|
21877
22166
|
const myPid = process.pid;
|
|
21878
22167
|
try {
|
|
21879
22168
|
if (process.platform === "win32") {
|
|
@@ -21891,16 +22180,16 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
21891
22180
|
}
|
|
21892
22181
|
console.log("");
|
|
21893
22182
|
const envForChild = { ...process.env };
|
|
21894
|
-
const secretsDir =
|
|
21895
|
-
const cfgBase =
|
|
22183
|
+
const secretsDir = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7-secrets");
|
|
22184
|
+
const cfgBase = path30.basename(configPath2, ".json");
|
|
21896
22185
|
const secretCandidates = [
|
|
21897
|
-
|
|
21898
|
-
|
|
21899
|
-
|
|
22186
|
+
path30.join(secretsDir, `${cfgBase}.env`),
|
|
22187
|
+
path30.join(path30.dirname(configPath2), `.env.${cfgBase}`),
|
|
22188
|
+
path30.join(path30.dirname(configPath2), ".env")
|
|
21900
22189
|
];
|
|
21901
22190
|
for (const secretPath of secretCandidates) {
|
|
21902
|
-
if (
|
|
21903
|
-
const content =
|
|
22191
|
+
if (fs28.existsSync(secretPath)) {
|
|
22192
|
+
const content = fs28.readFileSync(secretPath, "utf-8");
|
|
21904
22193
|
for (const line of content.split("\n")) {
|
|
21905
22194
|
const trimmed = line.trim();
|
|
21906
22195
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -21975,14 +22264,14 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
21975
22264
|
console.error(`\u274C \u672A\u77E5\u6A21\u5F0F: ${mode}\uFF08\u53EF\u9009: archive / drop-last / strip-images\uFF09`);
|
|
21976
22265
|
process.exit(1);
|
|
21977
22266
|
}
|
|
21978
|
-
const configRaw = JSON.parse(
|
|
22267
|
+
const configRaw = JSON.parse(fs28.readFileSync(configPath2, "utf-8"));
|
|
21979
22268
|
const stateDir = configRaw.stateDir;
|
|
21980
22269
|
if (!stateDir) {
|
|
21981
22270
|
console.error("\u274C config \u91CC\u6CA1\u6709 stateDir");
|
|
21982
22271
|
process.exit(1);
|
|
21983
22272
|
}
|
|
21984
|
-
const sessionsDir =
|
|
21985
|
-
if (!
|
|
22273
|
+
const sessionsDir = path30.join(stateDir, "agents", "main", "sessions");
|
|
22274
|
+
if (!fs28.existsSync(sessionsDir)) {
|
|
21986
22275
|
console.error(`\u274C sessions \u76EE\u5F55\u4E0D\u5B58\u5728: ${sessionsDir}`);
|
|
21987
22276
|
process.exit(1);
|
|
21988
22277
|
}
|
|
@@ -21990,37 +22279,37 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
21990
22279
|
console.log(` config: ${configPath2}`);
|
|
21991
22280
|
console.log(` mode: ${mode}`);
|
|
21992
22281
|
if (mode === "drop-last") console.log(` n: ${dropN}`);
|
|
21993
|
-
const platformMapPath =
|
|
21994
|
-
const indexPath =
|
|
22282
|
+
const platformMapPath = path30.join(sessionsDir, "platform-map.json");
|
|
22283
|
+
const indexPath = path30.join(sessionsDir, "session-index.json");
|
|
21995
22284
|
let sessionFileUUID = null;
|
|
21996
|
-
if (
|
|
21997
|
-
const index = JSON.parse(
|
|
22285
|
+
if (fs28.existsSync(indexPath)) {
|
|
22286
|
+
const index = JSON.parse(fs28.readFileSync(indexPath, "utf-8"));
|
|
21998
22287
|
const entries2 = Object.values(index);
|
|
21999
22288
|
if (entries2.length > 0) {
|
|
22000
22289
|
const fileVal = entries2[0].file || "";
|
|
22001
|
-
sessionFileUUID =
|
|
22290
|
+
sessionFileUUID = path30.isAbsolute(fileVal) ? path30.basename(fileVal, ".jsonl") : fileVal.replace(".jsonl", "");
|
|
22002
22291
|
}
|
|
22003
22292
|
}
|
|
22004
22293
|
if (!sessionFileUUID) {
|
|
22005
|
-
const jsonlFiles =
|
|
22294
|
+
const jsonlFiles = fs28.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs28.statSync(path30.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
22006
22295
|
if (jsonlFiles.length === 0) {
|
|
22007
22296
|
console.error("\u274C \u627E\u4E0D\u5230\u6D3B\u8DC3\u7684 session JSONL \u6587\u4EF6");
|
|
22008
22297
|
process.exit(1);
|
|
22009
22298
|
}
|
|
22010
22299
|
sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
|
|
22011
22300
|
}
|
|
22012
|
-
let jsonlPath =
|
|
22013
|
-
if (!
|
|
22014
|
-
const jsonlFiles =
|
|
22301
|
+
let jsonlPath = path30.join(sessionsDir, `${sessionFileUUID}.jsonl`);
|
|
22302
|
+
if (!fs28.existsSync(jsonlPath)) {
|
|
22303
|
+
const jsonlFiles = fs28.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs28.statSync(path30.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
22015
22304
|
if (jsonlFiles.length === 0) {
|
|
22016
22305
|
console.error(`\u274C JSONL \u6587\u4EF6\u4E0D\u5B58\u5728: ${jsonlPath}`);
|
|
22017
22306
|
process.exit(1);
|
|
22018
22307
|
}
|
|
22019
22308
|
sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
|
|
22020
|
-
jsonlPath =
|
|
22309
|
+
jsonlPath = path30.join(sessionsDir, `${sessionFileUUID}.jsonl`);
|
|
22021
22310
|
}
|
|
22022
22311
|
console.log(` file: ${jsonlPath}`);
|
|
22023
|
-
const configName =
|
|
22312
|
+
const configName = path30.basename(configPath2);
|
|
22024
22313
|
if (autoRestart) {
|
|
22025
22314
|
try {
|
|
22026
22315
|
const myPid = process.pid;
|
|
@@ -22036,10 +22325,10 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
22036
22325
|
}
|
|
22037
22326
|
}
|
|
22038
22327
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
22039
|
-
const { readFileSync: readFileSync29, writeFileSync: writeFileSync20, renameSync:
|
|
22328
|
+
const { readFileSync: readFileSync29, writeFileSync: writeFileSync20, renameSync: renameSync5 } = fs28;
|
|
22040
22329
|
if (mode === "archive") {
|
|
22041
22330
|
const archiveName = `${sessionFileUUID}.jsonl.archived.${timestamp}`;
|
|
22042
|
-
|
|
22331
|
+
renameSync5(jsonlPath, path30.join(sessionsDir, archiveName));
|
|
22043
22332
|
console.log(`
|
|
22044
22333
|
\u2705 \u5F52\u6863\u5B8C\u6210: ${archiveName}`);
|
|
22045
22334
|
console.log(` \u91CD\u542F\u540E\u5C06\u4ECE\u7A7A\u767D\u4F1A\u8BDD\u5F00\u59CB`);
|
|
@@ -22114,12 +22403,12 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
22114
22403
|
\u2705 \u6458\u9664 ${stripped} \u884C\u56FE\u7247\u76F8\u5173\u5185\u5BB9`);
|
|
22115
22404
|
}
|
|
22116
22405
|
if (autoRestart) {
|
|
22117
|
-
const realCliPath =
|
|
22118
|
-
const cliDir =
|
|
22119
|
-
const pkgRoot =
|
|
22120
|
-
let enginePath =
|
|
22121
|
-
if (!
|
|
22122
|
-
enginePath =
|
|
22406
|
+
const realCliPath = fs28.realpathSync(process.argv[1]);
|
|
22407
|
+
const cliDir = path30.dirname(realCliPath);
|
|
22408
|
+
const pkgRoot = path30.resolve(cliDir, "..");
|
|
22409
|
+
let enginePath = path30.join(pkgRoot, "dist", "main.mjs");
|
|
22410
|
+
if (!fs28.existsSync(enginePath)) {
|
|
22411
|
+
enginePath = path30.join(cliDir, "main.mjs");
|
|
22123
22412
|
}
|
|
22124
22413
|
console.log(`
|
|
22125
22414
|
\u{1F680} \u62C9\u8D77 engine...`);
|
|
@@ -22162,18 +22451,18 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
|
|
|
22162
22451
|
else if (args[i] === "--cwd" && args[i + 1]) cwd = args[++i];
|
|
22163
22452
|
}
|
|
22164
22453
|
if (!configPath2) {
|
|
22165
|
-
const defaultCfg =
|
|
22166
|
-
const homeCfg =
|
|
22167
|
-
if (
|
|
22454
|
+
const defaultCfg = path30.join(cwd, "configs", "main7.json");
|
|
22455
|
+
const homeCfg = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
|
|
22456
|
+
if (fs28.existsSync(defaultCfg)) {
|
|
22168
22457
|
configPath2 = defaultCfg;
|
|
22169
|
-
} else if (
|
|
22458
|
+
} else if (fs28.existsSync(homeCfg)) {
|
|
22170
22459
|
configPath2 = homeCfg;
|
|
22171
|
-
cwd =
|
|
22460
|
+
cwd = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
22172
22461
|
} else {
|
|
22173
22462
|
const ptr = readHomePointer();
|
|
22174
22463
|
if (ptr?.stateDir) {
|
|
22175
|
-
const ptrCfg =
|
|
22176
|
-
if (
|
|
22464
|
+
const ptrCfg = path30.join(ptr.stateDir, "configs", "main7.json");
|
|
22465
|
+
if (fs28.existsSync(ptrCfg)) {
|
|
22177
22466
|
configPath2 = ptrCfg;
|
|
22178
22467
|
cwd = ptr.stateDir;
|
|
22179
22468
|
}
|
|
@@ -22192,14 +22481,14 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
|
|
|
22192
22481
|
if (process.platform === "win32") {
|
|
22193
22482
|
const taskName = "Engine7";
|
|
22194
22483
|
const nodeExe = process.execPath;
|
|
22195
|
-
const cliMjs =
|
|
22196
|
-
const absConfig =
|
|
22197
|
-
const wrapperPath =
|
|
22484
|
+
const cliMjs = path30.resolve(engine7Bin);
|
|
22485
|
+
const absConfig = path30.resolve(configPath2);
|
|
22486
|
+
const wrapperPath = path30.join(cwd, "engine7-start.cmd");
|
|
22198
22487
|
const wrapperContent = `@echo off\r
|
|
22199
22488
|
cd /d "${cwd}"\r
|
|
22200
22489
|
"${nodeExe}" "${cliMjs}" start --config "${absConfig}"\r
|
|
22201
22490
|
`;
|
|
22202
|
-
|
|
22491
|
+
fs28.writeFileSync(wrapperPath, wrapperContent);
|
|
22203
22492
|
try {
|
|
22204
22493
|
execSync3(`schtasks /create /tn "${taskName}" /tr "${wrapperPath}" /sc onlogon /rl highest /f`, { stdio: "inherit", shell: true });
|
|
22205
22494
|
console.log(`\u2705 Windows \u8BA1\u5212\u4EFB\u52A1 "${taskName}" \u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
|
|
@@ -22210,11 +22499,11 @@ cd /d "${cwd}"\r
|
|
|
22210
22499
|
}
|
|
22211
22500
|
} else if (process.platform === "darwin") {
|
|
22212
22501
|
const label = "com.engine7.agent";
|
|
22213
|
-
const plistDir =
|
|
22214
|
-
|
|
22215
|
-
const plistPath =
|
|
22216
|
-
const localCli =
|
|
22217
|
-
const cliMjs =
|
|
22502
|
+
const plistDir = path30.join(process.env.HOME, "Library", "LaunchAgents");
|
|
22503
|
+
fs28.mkdirSync(plistDir, { recursive: true });
|
|
22504
|
+
const plistPath = path30.join(plistDir, `${label}.plist`);
|
|
22505
|
+
const localCli = path30.join("node_modules", "engine7", "dist", "cli.mjs");
|
|
22506
|
+
const cliMjs = fs28.existsSync(localCli) ? path30.resolve(localCli) : path30.join(path30.dirname(path30.dirname(engine7Bin)), "lib", "node_modules", "engine7", "dist", "cli.mjs");
|
|
22218
22507
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
22219
22508
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
22220
22509
|
<plist version="1.0">
|
|
@@ -22226,14 +22515,14 @@ cd /d "${cwd}"\r
|
|
|
22226
22515
|
<string>${cliMjs}</string>
|
|
22227
22516
|
<string>start</string>
|
|
22228
22517
|
<string>--config</string>
|
|
22229
|
-
<string>${
|
|
22518
|
+
<string>${path30.resolve(configPath2)}</string>
|
|
22230
22519
|
</array>
|
|
22231
22520
|
<key>WorkingDirectory</key><string>${cwd}</string>
|
|
22232
22521
|
<key>RunAtLoad</key><true/>
|
|
22233
22522
|
<key>KeepAlive</key><true/>
|
|
22234
22523
|
</dict>
|
|
22235
22524
|
</plist>`;
|
|
22236
|
-
|
|
22525
|
+
fs28.writeFileSync(plistPath, plist);
|
|
22237
22526
|
try {
|
|
22238
22527
|
execSync3(`launchctl load "${plistPath}"`, { stdio: "inherit" });
|
|
22239
22528
|
console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
|
|
@@ -22244,9 +22533,9 @@ cd /d "${cwd}"\r
|
|
|
22244
22533
|
}
|
|
22245
22534
|
} else {
|
|
22246
22535
|
const svcName = "engine7";
|
|
22247
|
-
const svcDir =
|
|
22248
|
-
|
|
22249
|
-
const svcPath =
|
|
22536
|
+
const svcDir = path30.join(process.env.HOME, ".config", "systemd", "user");
|
|
22537
|
+
fs28.mkdirSync(svcDir, { recursive: true });
|
|
22538
|
+
const svcPath = path30.join(svcDir, `${svcName}.service`);
|
|
22250
22539
|
const svc = `[Unit]
|
|
22251
22540
|
Description=Engine 7 Agent
|
|
22252
22541
|
After=network.target
|
|
@@ -22254,13 +22543,13 @@ After=network.target
|
|
|
22254
22543
|
[Service]
|
|
22255
22544
|
Type=simple
|
|
22256
22545
|
WorkingDirectory=${cwd}
|
|
22257
|
-
ExecStart=${process.execPath} ${engine7Bin} start --config ${
|
|
22546
|
+
ExecStart=${process.execPath} ${engine7Bin} start --config ${path30.resolve(configPath2)}
|
|
22258
22547
|
Restart=on-failure
|
|
22259
22548
|
RestartSec=10
|
|
22260
22549
|
|
|
22261
22550
|
[Install]
|
|
22262
22551
|
WantedBy=default.target`;
|
|
22263
|
-
|
|
22552
|
+
fs28.writeFileSync(svcPath, svc);
|
|
22264
22553
|
try {
|
|
22265
22554
|
execSync3(`systemctl --user daemon-reload`, { stdio: "inherit" });
|
|
22266
22555
|
execSync3(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
|
|
@@ -22281,13 +22570,13 @@ WantedBy=default.target`;
|
|
|
22281
22570
|
process.exit(1);
|
|
22282
22571
|
}
|
|
22283
22572
|
} else if (process.platform === "darwin") {
|
|
22284
|
-
const plistPath =
|
|
22573
|
+
const plistPath = path30.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
|
|
22285
22574
|
try {
|
|
22286
22575
|
execSync3(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
|
|
22287
22576
|
} catch {
|
|
22288
22577
|
}
|
|
22289
22578
|
try {
|
|
22290
|
-
|
|
22579
|
+
fs28.unlinkSync(plistPath);
|
|
22291
22580
|
} catch {
|
|
22292
22581
|
}
|
|
22293
22582
|
console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u5220\u9664`);
|
|
@@ -22296,9 +22585,9 @@ WantedBy=default.target`;
|
|
|
22296
22585
|
execSync3(`systemctl --user disable engine7`, { stdio: "inherit" });
|
|
22297
22586
|
} catch {
|
|
22298
22587
|
}
|
|
22299
|
-
const svcPath =
|
|
22588
|
+
const svcPath = path30.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
|
|
22300
22589
|
try {
|
|
22301
|
-
|
|
22590
|
+
fs28.unlinkSync(svcPath);
|
|
22302
22591
|
} catch {
|
|
22303
22592
|
}
|
|
22304
22593
|
try {
|
|
@@ -22315,8 +22604,8 @@ WantedBy=default.target`;
|
|
|
22315
22604
|
console.log("\u274C \u672A\u5B89\u88C5");
|
|
22316
22605
|
}
|
|
22317
22606
|
} else if (process.platform === "darwin") {
|
|
22318
|
-
const plistPath =
|
|
22319
|
-
if (
|
|
22607
|
+
const plistPath = path30.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
|
|
22608
|
+
if (fs28.existsSync(plistPath)) {
|
|
22320
22609
|
console.log("\u2705 \u5DF2\u5B89\u88C5\uFF08launchd\uFF09");
|
|
22321
22610
|
} else {
|
|
22322
22611
|
console.log("\u274C \u672A\u5B89\u88C5");
|
|
@@ -22339,16 +22628,16 @@ WantedBy=default.target`;
|
|
|
22339
22628
|
console.log(`
|
|
22340
22629
|
\u{1F680} engine7 init`);
|
|
22341
22630
|
console.log(` state-dir: ${opts.stateDir}`);
|
|
22342
|
-
if (
|
|
22343
|
-
const files =
|
|
22631
|
+
if (fs28.existsSync(opts.stateDir) && !opts.dryRun) {
|
|
22632
|
+
const files = fs28.readdirSync(opts.stateDir);
|
|
22344
22633
|
if (files.length > 0) {
|
|
22345
22634
|
if (opts.force) {
|
|
22346
22635
|
console.log(`
|
|
22347
22636
|
\u26A0\uFE0F --force: \u6E05\u7A7A\u5DF2\u6709\u76EE\u5F55 ${opts.stateDir}`);
|
|
22348
|
-
|
|
22637
|
+
fs28.rmSync(opts.stateDir, { recursive: true, force: true });
|
|
22349
22638
|
} else {
|
|
22350
|
-
const existingConfig =
|
|
22351
|
-
if (
|
|
22639
|
+
const existingConfig = path30.join(opts.stateDir, "configs", "main7.json");
|
|
22640
|
+
if (fs28.existsSync(existingConfig)) {
|
|
22352
22641
|
console.log(`
|
|
22353
22642
|
\u267B\uFE0F \u68C0\u6D4B\u5230\u5DF2\u6709\u914D\u7F6E: ${existingConfig}`);
|
|
22354
22643
|
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`);
|
|
@@ -22372,7 +22661,7 @@ WantedBy=default.target`;
|
|
|
22372
22661
|
rl.close();
|
|
22373
22662
|
}
|
|
22374
22663
|
const config = generateConfig(values);
|
|
22375
|
-
const configPath =
|
|
22664
|
+
const configPath = path30.join(opts.stateDir, "configs", "main7.json");
|
|
22376
22665
|
const tree = buildDirTree(values);
|
|
22377
22666
|
tree.push({
|
|
22378
22667
|
path: configPath,
|
|
@@ -22383,9 +22672,9 @@ WantedBy=default.target`;
|
|
|
22383
22672
|
dryRun(tree);
|
|
22384
22673
|
const skillsSrc = findTemplateDir("skills");
|
|
22385
22674
|
if (skillsSrc) {
|
|
22386
|
-
const skills =
|
|
22675
|
+
const skills = fs28.readdirSync(skillsSrc);
|
|
22387
22676
|
for (const s of skills) {
|
|
22388
|
-
console.log(` \u{1F4C1} ${
|
|
22677
|
+
console.log(` \u{1F4C1} ${path30.join(opts.stateDir, "workspace", "skills", s)}`);
|
|
22389
22678
|
}
|
|
22390
22679
|
}
|
|
22391
22680
|
} else {
|
|
@@ -22393,16 +22682,16 @@ WantedBy=default.target`;
|
|
|
22393
22682
|
execute(tree);
|
|
22394
22683
|
if (values.primaryApiKey && values.primaryApiKey.trim()) {
|
|
22395
22684
|
const envName = values.primaryProvider.toUpperCase().replace(/[^A-Z0-9_]/g, "_") + "_API_KEY";
|
|
22396
|
-
const secretsDir =
|
|
22397
|
-
if (!
|
|
22398
|
-
const envFile =
|
|
22685
|
+
const secretsDir = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7-secrets");
|
|
22686
|
+
if (!fs28.existsSync(secretsDir)) fs28.mkdirSync(secretsDir, { recursive: true });
|
|
22687
|
+
const envFile = path30.join(secretsDir, "main7.env");
|
|
22399
22688
|
let envContent = "";
|
|
22400
|
-
if (
|
|
22689
|
+
if (fs28.existsSync(envFile)) envContent = fs28.readFileSync(envFile, "utf8");
|
|
22401
22690
|
const lines = envContent.split("\n").filter((l) => l && !l.startsWith(envName + "="));
|
|
22402
22691
|
lines.push(envName + "=" + values.primaryApiKey.trim());
|
|
22403
|
-
|
|
22692
|
+
fs28.writeFileSync(envFile, lines.join("\n") + "\n", "utf8");
|
|
22404
22693
|
try {
|
|
22405
|
-
|
|
22694
|
+
fs28.chmodSync(envFile, 384);
|
|
22406
22695
|
} catch {
|
|
22407
22696
|
}
|
|
22408
22697
|
console.log("\u{1F511} API key \u5DF2\u5B58\u5165: " + envFile);
|
|
@@ -22410,55 +22699,55 @@ WantedBy=default.target`;
|
|
|
22410
22699
|
}
|
|
22411
22700
|
const skillsSrc = findTemplateDir("skills");
|
|
22412
22701
|
if (skillsSrc) {
|
|
22413
|
-
const skillsDest =
|
|
22414
|
-
|
|
22415
|
-
const skills =
|
|
22702
|
+
const skillsDest = path30.join(opts.stateDir, "workspace", "skills");
|
|
22703
|
+
fs28.mkdirSync(skillsDest, { recursive: true });
|
|
22704
|
+
const skills = fs28.readdirSync(skillsSrc);
|
|
22416
22705
|
for (const s of skills) {
|
|
22417
|
-
copyDirRecursive(
|
|
22706
|
+
copyDirRecursive(path30.join(skillsSrc, s), path30.join(skillsDest, s));
|
|
22418
22707
|
console.log(` \u{1F4E6} skill: ${s}`);
|
|
22419
22708
|
}
|
|
22420
22709
|
}
|
|
22421
22710
|
console.log(`
|
|
22422
22711
|
\u2705 \u521D\u59CB\u5316\u5B8C\u6210\uFF01
|
|
22423
22712
|
`);
|
|
22424
|
-
const homePointer =
|
|
22713
|
+
const homePointer = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
|
|
22425
22714
|
const pointerData = { stateDir: opts.stateDir };
|
|
22426
|
-
|
|
22715
|
+
fs28.writeFileSync(homePointer, JSON.stringify(pointerData, null, 2) + "\n");
|
|
22427
22716
|
console.log(` \u{1F4C4} ${homePointer}\uFF08\u4ECE\u4EFB\u610F\u76EE\u5F55\u90FD\u80FD\u627E\u5230\u6B64 agent\uFF09`);
|
|
22428
22717
|
console.log(`\u4E0B\u4E00\u6B65\uFF1A`);
|
|
22429
22718
|
console.log(` 1. \u68C0\u67E5\u5E76\u4FEE\u6539 ${opts.stateDir}/configs/main7.json`);
|
|
22430
22719
|
console.log(` 2. \u542F\u52A8 Engine: engine7 start\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
|
|
22431
22720
|
console.log(` 3. \u5F00\u673A\u81EA\u542F: engine7 service install\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
|
|
22432
|
-
console.log(` 4. \u67E5\u770B workspace: ${
|
|
22721
|
+
console.log(` 4. \u67E5\u770B workspace: ${path30.join(opts.stateDir, "workspace")}`);
|
|
22433
22722
|
}
|
|
22434
22723
|
}
|
|
22435
22724
|
function copyDirRecursive(src, dest) {
|
|
22436
|
-
|
|
22437
|
-
for (const entry of
|
|
22438
|
-
const srcPath =
|
|
22439
|
-
const destPath =
|
|
22725
|
+
fs28.mkdirSync(dest, { recursive: true });
|
|
22726
|
+
for (const entry of fs28.readdirSync(src, { withFileTypes: true })) {
|
|
22727
|
+
const srcPath = path30.join(src, entry.name);
|
|
22728
|
+
const destPath = path30.join(dest, entry.name);
|
|
22440
22729
|
if (entry.isDirectory()) {
|
|
22441
22730
|
copyDirRecursive(srcPath, destPath);
|
|
22442
22731
|
} else {
|
|
22443
|
-
|
|
22732
|
+
fs28.copyFileSync(srcPath, destPath);
|
|
22444
22733
|
}
|
|
22445
22734
|
}
|
|
22446
22735
|
}
|
|
22447
22736
|
function findTemplateDir(name) {
|
|
22448
22737
|
const candidates = [
|
|
22449
|
-
|
|
22450
|
-
|
|
22451
|
-
|
|
22738
|
+
path30.join(__dirname, "..", "templates", name),
|
|
22739
|
+
path30.join(__dirname, "..", "..", "templates", name),
|
|
22740
|
+
path30.join(process.cwd(), "templates", name)
|
|
22452
22741
|
];
|
|
22453
22742
|
for (const p of candidates) {
|
|
22454
|
-
if (
|
|
22743
|
+
if (fs28.existsSync(p)) return p;
|
|
22455
22744
|
}
|
|
22456
22745
|
return null;
|
|
22457
22746
|
}
|
|
22458
22747
|
function readHomePointer() {
|
|
22459
|
-
const ptrPath =
|
|
22748
|
+
const ptrPath = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
|
|
22460
22749
|
try {
|
|
22461
|
-
return JSON.parse(
|
|
22750
|
+
return JSON.parse(fs28.readFileSync(ptrPath, "utf-8"));
|
|
22462
22751
|
} catch {
|
|
22463
22752
|
return null;
|
|
22464
22753
|
}
|
|
@@ -22469,4 +22758,3 @@ main().catch((err) => {
|
|
|
22469
22758
|
console.error(err.stack);
|
|
22470
22759
|
process.exit(1);
|
|
22471
22760
|
});
|
|
22472
|
-
//# sourceMappingURL=cli.mjs.map
|