engine7 7.1.66 → 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 +1167 -872
- package/dist/engine-startup.mjs +2878 -1301
- package/dist/main.mjs +2873 -1296
- 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`);
|
|
@@ -7318,12 +7503,19 @@ async function readSessionHistory(filePath) {
|
|
|
7318
7503
|
let filtered = filterUnresolvedToolUses(sessionMsgs);
|
|
7319
7504
|
filtered = filterOrphanedThinkingOnly(filtered);
|
|
7320
7505
|
filtered = filterWhitespaceOnlyAssistant(filtered);
|
|
7321
|
-
const
|
|
7322
|
-
const
|
|
7506
|
+
const seenStartTexts = /* @__PURE__ */ new Set();
|
|
7507
|
+
const sessionStarts = attachmentMsgs.filter((m) => {
|
|
7508
|
+
if (m.attachment.type !== "session_start") return false;
|
|
7509
|
+
const key = JSON.stringify(m.attachment);
|
|
7510
|
+
if (seenStartTexts.has(key)) return false;
|
|
7511
|
+
seenStartTexts.add(key);
|
|
7512
|
+
return true;
|
|
7513
|
+
});
|
|
7514
|
+
const restAttachments = attachmentMsgs.filter((m) => m.type === "attachment" && m.attachment.type !== "session_start");
|
|
7323
7515
|
return [...sessionStarts, ...filtered, ...restAttachments];
|
|
7324
7516
|
}
|
|
7325
7517
|
async function readAllLines(filePath) {
|
|
7326
|
-
const stream =
|
|
7518
|
+
const stream = fs9.createReadStream(filePath, { encoding: "utf-8" });
|
|
7327
7519
|
const rl = readline.createInterface({ input: stream });
|
|
7328
7520
|
const lines = [];
|
|
7329
7521
|
return new Promise((resolve11, reject) => {
|
|
@@ -7473,12 +7665,12 @@ function extractText2(content) {
|
|
|
7473
7665
|
return content.filter((b) => b.type === "text").map((b) => b.text || "").join("") || null;
|
|
7474
7666
|
}
|
|
7475
7667
|
function listSessions(sessionsDir) {
|
|
7476
|
-
if (!
|
|
7477
|
-
const files =
|
|
7478
|
-
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),
|
|
7479
7671
|
id: f.replace(/\.jsonl.*$/, ""),
|
|
7480
7672
|
// strip .jsonl and everything after (archived suffix)
|
|
7481
|
-
modified: new Date(
|
|
7673
|
+
modified: new Date(fs9.statSync(path9.join(sessionsDir, f)).mtimeMs)
|
|
7482
7674
|
})).sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
7483
7675
|
return files;
|
|
7484
7676
|
}
|
|
@@ -7498,8 +7690,8 @@ var session_manager_exports = {};
|
|
|
7498
7690
|
__export(session_manager_exports, {
|
|
7499
7691
|
SessionManager: () => SessionManager
|
|
7500
7692
|
});
|
|
7501
|
-
import * as
|
|
7502
|
-
import * as
|
|
7693
|
+
import * as path10 from "node:path";
|
|
7694
|
+
import * as fs10 from "node:fs";
|
|
7503
7695
|
import * as crypto3 from "node:crypto";
|
|
7504
7696
|
var RESTORE_MAX_CHARS, CHARS_PER_TOKEN, SessionManager;
|
|
7505
7697
|
var init_session_manager = __esm({
|
|
@@ -7531,24 +7723,24 @@ var init_session_manager = __esm({
|
|
|
7531
7723
|
constructor(config) {
|
|
7532
7724
|
this.config = config;
|
|
7533
7725
|
this.scopeConfig = config.scopeConfig;
|
|
7534
|
-
this.sessionsDir =
|
|
7535
|
-
this.indexPath =
|
|
7536
|
-
this.platformMapPath =
|
|
7537
|
-
|
|
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 });
|
|
7538
7730
|
}
|
|
7539
7731
|
// === 索引操作 ===
|
|
7540
7732
|
loadIndex() {
|
|
7541
7733
|
try {
|
|
7542
|
-
if (
|
|
7543
|
-
const raw =
|
|
7734
|
+
if (fs10.existsSync(this.indexPath)) {
|
|
7735
|
+
const raw = fs10.readFileSync(this.indexPath, "utf-8");
|
|
7544
7736
|
const obj = JSON.parse(raw);
|
|
7545
7737
|
this.index = new Map(Object.entries(obj));
|
|
7546
7738
|
let fixed = 0;
|
|
7547
7739
|
for (const [key, entry] of this.index) {
|
|
7548
|
-
if (
|
|
7549
|
-
const basename8 =
|
|
7550
|
-
const localPath =
|
|
7551
|
-
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)) {
|
|
7552
7744
|
entry.file = localPath;
|
|
7553
7745
|
fixed++;
|
|
7554
7746
|
}
|
|
@@ -7567,7 +7759,7 @@ var init_session_manager = __esm({
|
|
|
7567
7759
|
try {
|
|
7568
7760
|
const obj = {};
|
|
7569
7761
|
for (const [k, v] of this.index) obj[k] = v;
|
|
7570
|
-
|
|
7762
|
+
fs10.writeFileSync(this.indexPath, JSON.stringify(obj, null, 2));
|
|
7571
7763
|
} catch (err) {
|
|
7572
7764
|
console.error(`[session] Failed to save index: ${err.message}`);
|
|
7573
7765
|
}
|
|
@@ -7575,8 +7767,8 @@ var init_session_manager = __esm({
|
|
|
7575
7767
|
// === 平台映射 ===
|
|
7576
7768
|
loadPlatformMap() {
|
|
7577
7769
|
try {
|
|
7578
|
-
if (
|
|
7579
|
-
const raw =
|
|
7770
|
+
if (fs10.existsSync(this.platformMapPath)) {
|
|
7771
|
+
const raw = fs10.readFileSync(this.platformMapPath, "utf-8");
|
|
7580
7772
|
const obj = JSON.parse(raw);
|
|
7581
7773
|
this.platformMap = new Map(Object.entries(obj));
|
|
7582
7774
|
console.log(`[session] Platform map loaded: ${this.platformMap.size} entries`);
|
|
@@ -7588,7 +7780,7 @@ var init_session_manager = __esm({
|
|
|
7588
7780
|
try {
|
|
7589
7781
|
const obj = {};
|
|
7590
7782
|
for (const [k, v] of this.platformMap) obj[k] = v;
|
|
7591
|
-
|
|
7783
|
+
fs10.writeFileSync(this.platformMapPath, JSON.stringify(obj, null, 2));
|
|
7592
7784
|
} catch (err) {
|
|
7593
7785
|
console.error(`[session] Failed to save platform map: ${err.message}`);
|
|
7594
7786
|
}
|
|
@@ -7627,17 +7819,17 @@ var init_session_manager = __esm({
|
|
|
7627
7819
|
*/
|
|
7628
7820
|
getSessionFilePath(sessionId) {
|
|
7629
7821
|
const entry = this.index.get(sessionId);
|
|
7630
|
-
if (entry &&
|
|
7631
|
-
const direct =
|
|
7632
|
-
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;
|
|
7633
7825
|
}
|
|
7634
7826
|
// === Writer 管理 ===
|
|
7635
7827
|
getWriter(sessionId) {
|
|
7636
7828
|
let writer = this.writers.get(sessionId);
|
|
7637
7829
|
if (!writer) {
|
|
7638
7830
|
const existing = this.index.get(sessionId);
|
|
7639
|
-
if (existing &&
|
|
7640
|
-
const existingFileId =
|
|
7831
|
+
if (existing && fs10.existsSync(existing.file)) {
|
|
7832
|
+
const existingFileId = path10.basename(existing.file, ".jsonl");
|
|
7641
7833
|
writer = new SessionWriter(this.sessionsDir, existingFileId);
|
|
7642
7834
|
writer.open(this.config.workspace, sessionId);
|
|
7643
7835
|
} else {
|
|
@@ -7649,7 +7841,7 @@ var init_session_manager = __esm({
|
|
|
7649
7841
|
this.saveIndex();
|
|
7650
7842
|
this.writers.set(sessionId, writer);
|
|
7651
7843
|
this.onWriterCreated?.(writer, sessionId);
|
|
7652
|
-
console.log(`[session] ${existing ? "Resumed" : "New"}: ${sessionId} \u2192 ${
|
|
7844
|
+
console.log(`[session] ${existing ? "Resumed" : "New"}: ${sessionId} \u2192 ${path10.basename(writer.path)}`);
|
|
7653
7845
|
}
|
|
7654
7846
|
return writer;
|
|
7655
7847
|
}
|
|
@@ -7668,7 +7860,7 @@ var init_session_manager = __esm({
|
|
|
7668
7860
|
if (!writer) return null;
|
|
7669
7861
|
try {
|
|
7670
7862
|
this.lastArchiveCheck = Date.now();
|
|
7671
|
-
const stat4 =
|
|
7863
|
+
const stat4 = fs10.statSync(writer.path);
|
|
7672
7864
|
if (stat4.size < threshold) return null;
|
|
7673
7865
|
const sizeMB = (stat4.size / 1024 / 1024).toFixed(1);
|
|
7674
7866
|
const thresholdMB = (threshold / 1024 / 1024).toFixed(1);
|
|
@@ -7677,10 +7869,10 @@ var init_session_manager = __esm({
|
|
|
7677
7869
|
if (archivedPath) {
|
|
7678
7870
|
this.index.set(sessionId, { file: writer.path, updatedAt: Date.now() });
|
|
7679
7871
|
this.saveIndex();
|
|
7680
|
-
const newSize =
|
|
7872
|
+
const newSize = fs10.statSync(writer.path).size;
|
|
7681
7873
|
const oldSizeMB = (stat4.size / 1024 / 1024).toFixed(1);
|
|
7682
|
-
console.log(`[session] Archive complete: ${
|
|
7683
|
-
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$/, "");
|
|
7684
7876
|
this.purgeOldArchives(fileId, 3);
|
|
7685
7877
|
return archivedPath;
|
|
7686
7878
|
}
|
|
@@ -7696,15 +7888,15 @@ var init_session_manager = __esm({
|
|
|
7696
7888
|
purgeOldArchives(sessionId, keepCount = 3) {
|
|
7697
7889
|
try {
|
|
7698
7890
|
const dir = this.sessionsDir;
|
|
7699
|
-
if (!
|
|
7700
|
-
const allFiles =
|
|
7891
|
+
if (!fs10.existsSync(dir)) return;
|
|
7892
|
+
const allFiles = fs10.readdirSync(dir);
|
|
7701
7893
|
const archiveFiles = allFiles.filter((f) => {
|
|
7702
7894
|
if (!f.startsWith(sessionId)) return false;
|
|
7703
7895
|
return f.includes(".archived.") || f.includes(".compaction.");
|
|
7704
7896
|
}).map((f) => ({
|
|
7705
7897
|
name: f,
|
|
7706
|
-
path:
|
|
7707
|
-
mtime:
|
|
7898
|
+
path: path10.join(dir, f),
|
|
7899
|
+
mtime: fs10.statSync(path10.join(dir, f)).mtimeMs
|
|
7708
7900
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
7709
7901
|
console.log(`[session] purgeOldArchives: sessionId=${sessionId.substring(0, 8)}... found=${archiveFiles.length} keep=${keepCount}`);
|
|
7710
7902
|
if (archiveFiles.length <= keepCount) return;
|
|
@@ -7714,7 +7906,7 @@ var init_session_manager = __esm({
|
|
|
7714
7906
|
console.log(`[session] Skipping archived (kept for history): ${f.name}`);
|
|
7715
7907
|
continue;
|
|
7716
7908
|
}
|
|
7717
|
-
|
|
7909
|
+
fs10.unlinkSync(f.path);
|
|
7718
7910
|
console.log(`[session] Purged old archive: ${f.name}`);
|
|
7719
7911
|
}
|
|
7720
7912
|
if (toDelete.length > 0) {
|
|
@@ -7763,29 +7955,29 @@ var init_session_manager = __esm({
|
|
|
7763
7955
|
/** 列出 session 的所有文件(当前 + 归档),按修改时间排序 */
|
|
7764
7956
|
findAllSessionFiles(sessionId) {
|
|
7765
7957
|
const results = [];
|
|
7766
|
-
const mainFile =
|
|
7767
|
-
if (
|
|
7958
|
+
const mainFile = path10.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
7959
|
+
if (fs10.existsSync(mainFile)) {
|
|
7768
7960
|
results.push(mainFile);
|
|
7769
7961
|
}
|
|
7770
|
-
if (
|
|
7771
|
-
const compactionFiles =
|
|
7962
|
+
if (fs10.existsSync(this.sessionsDir)) {
|
|
7963
|
+
const compactionFiles = fs10.readdirSync(this.sessionsDir).filter((f) => f.startsWith(`${sessionId}.jsonl.compaction.`)).map((f) => ({
|
|
7772
7964
|
name: f,
|
|
7773
|
-
path:
|
|
7774
|
-
mtime:
|
|
7965
|
+
path: path10.join(this.sessionsDir, f),
|
|
7966
|
+
mtime: fs10.statSync(path10.join(this.sessionsDir, f)).mtimeMs
|
|
7775
7967
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
7776
7968
|
if (compactionFiles.length > 0) {
|
|
7777
7969
|
results.push(compactionFiles[0].path);
|
|
7778
7970
|
}
|
|
7779
7971
|
}
|
|
7780
7972
|
results.sort((a, b) => {
|
|
7781
|
-
const ta =
|
|
7782
|
-
const tb =
|
|
7973
|
+
const ta = fs10.statSync(a).mtimeMs;
|
|
7974
|
+
const tb = fs10.statSync(b).mtimeMs;
|
|
7783
7975
|
return ta - tb;
|
|
7784
7976
|
});
|
|
7785
7977
|
return results;
|
|
7786
7978
|
}
|
|
7787
7979
|
async findSessionFiles(sessionId) {
|
|
7788
|
-
if (!
|
|
7980
|
+
if (!fs10.existsSync(this.sessionsDir)) {
|
|
7789
7981
|
console.log(`[session:find] SESSIONS_DIR not found: ${this.sessionsDir}`);
|
|
7790
7982
|
return [];
|
|
7791
7983
|
}
|
|
@@ -7797,15 +7989,15 @@ var init_session_manager = __esm({
|
|
|
7797
7989
|
return mappedFiles;
|
|
7798
7990
|
}
|
|
7799
7991
|
const indexedEntry = this.index.get(mappedId);
|
|
7800
|
-
if (indexedEntry &&
|
|
7801
|
-
const fileUuid =
|
|
7992
|
+
if (indexedEntry && fs10.existsSync(indexedEntry.file)) {
|
|
7993
|
+
const fileUuid = path10.basename(indexedEntry.file, ".jsonl");
|
|
7802
7994
|
return this.findAllSessionFiles(fileUuid);
|
|
7803
7995
|
}
|
|
7804
7996
|
}
|
|
7805
7997
|
const allFiles = this.findAllSessionFiles(sessionId);
|
|
7806
7998
|
if (allFiles.length > 0) {
|
|
7807
7999
|
const labels = allFiles.map((f) => {
|
|
7808
|
-
const base =
|
|
8000
|
+
const base = path10.basename(f);
|
|
7809
8001
|
return base.endsWith(".jsonl") ? base : `${base} (archived)`;
|
|
7810
8002
|
});
|
|
7811
8003
|
console.log(`[session:find] Found ${allFiles.length} file(s) for ${sessionId}: ${labels.join(", ")}`);
|
|
@@ -7813,9 +8005,9 @@ var init_session_manager = __esm({
|
|
|
7813
8005
|
}
|
|
7814
8006
|
const indexed = this.index.get(sessionId);
|
|
7815
8007
|
if (indexed) {
|
|
7816
|
-
console.log(`[session:find] Index hit: ${sessionId} \u2192 ${indexed.file} (exists=${
|
|
7817
|
-
if (
|
|
7818
|
-
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"));
|
|
7819
8011
|
}
|
|
7820
8012
|
} else {
|
|
7821
8013
|
console.log(`[session:find] Index miss: ${sessionId} (index has ${this.index.size} entries)`);
|
|
@@ -7844,8 +8036,8 @@ var init_session_manager = __esm({
|
|
|
7844
8036
|
return [];
|
|
7845
8037
|
}
|
|
7846
8038
|
files.sort((a, b) => {
|
|
7847
|
-
const ta =
|
|
7848
|
-
const tb =
|
|
8039
|
+
const ta = fs10.statSync(a).mtimeMs;
|
|
8040
|
+
const tb = fs10.statSync(b).mtimeMs;
|
|
7849
8041
|
return ta - tb;
|
|
7850
8042
|
});
|
|
7851
8043
|
const latestFile = files[files.length - 1];
|
|
@@ -7853,11 +8045,11 @@ var init_session_manager = __esm({
|
|
|
7853
8045
|
if (!currentEntry || currentEntry.file !== latestFile) {
|
|
7854
8046
|
this.index.set(sessionId, { file: latestFile, updatedAt: Date.now() });
|
|
7855
8047
|
this.saveIndex();
|
|
7856
|
-
console.log(`[session:restore] Synced index: ${sessionId} \u2192 ${
|
|
8048
|
+
console.log(`[session:restore] Synced index: ${sessionId} \u2192 ${path10.basename(latestFile)}`);
|
|
7857
8049
|
}
|
|
7858
8050
|
const allMessages = [];
|
|
7859
|
-
for (const
|
|
7860
|
-
const sessionMsgs = await readSessionHistory(
|
|
8051
|
+
for (const file2 of files) {
|
|
8052
|
+
const sessionMsgs = await readSessionHistory(file2);
|
|
7861
8053
|
for (const m of sessionMsgs) {
|
|
7862
8054
|
if (isAttachmentMessage(m)) {
|
|
7863
8055
|
allMessages.push(m);
|
|
@@ -7889,7 +8081,7 @@ var init_session_manager = __esm({
|
|
|
7889
8081
|
if (isAttachmentMessage(m) && m.attachment.type === "relevant_memories") {
|
|
7890
8082
|
for (const mem of m.attachment.memories) {
|
|
7891
8083
|
rawCount++;
|
|
7892
|
-
restoredPaths.add(
|
|
8084
|
+
restoredPaths.add(path10.resolve(mem.path));
|
|
7893
8085
|
}
|
|
7894
8086
|
}
|
|
7895
8087
|
}
|
|
@@ -7918,15 +8110,15 @@ var init_session_manager = __esm({
|
|
|
7918
8110
|
*/
|
|
7919
8111
|
rotateMainSession() {
|
|
7920
8112
|
const entry = this.index.get("main");
|
|
7921
|
-
if (!entry || !
|
|
7922
|
-
const oldFileId =
|
|
7923
|
-
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);
|
|
7924
8116
|
if (stat4.size < 1024) return;
|
|
7925
8117
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-");
|
|
7926
8118
|
const archivedPath = `${entry.file}.archived.${ts}`;
|
|
7927
|
-
|
|
8119
|
+
fs10.renameSync(entry.file, archivedPath);
|
|
7928
8120
|
const sizeMB = (stat4.size / 1024 / 1024).toFixed(1);
|
|
7929
|
-
console.log(`[session] Archived: ${
|
|
8121
|
+
console.log(`[session] Archived: ${path10.basename(entry.file)} \u2192 ${path10.basename(archivedPath)} (${sizeMB}MB)`);
|
|
7930
8122
|
const newWriter = new SessionWriter(this.sessionsDir);
|
|
7931
8123
|
newWriter.open(this.config.workspace, "main");
|
|
7932
8124
|
newWriter.writeModelChange(this.config.providerId, this.config.model);
|
|
@@ -7935,7 +8127,7 @@ var init_session_manager = __esm({
|
|
|
7935
8127
|
this.index.set("main", { file: newPath, updatedAt: Date.now() });
|
|
7936
8128
|
this.saveIndex();
|
|
7937
8129
|
this.purgeOldArchives(oldFileId, 3);
|
|
7938
|
-
console.log(`[session] Rotated main: ${oldFileId}.jsonl \u2192 ${
|
|
8130
|
+
console.log(`[session] Rotated main: ${oldFileId}.jsonl \u2192 ${path10.basename(newPath)}`);
|
|
7939
8131
|
}
|
|
7940
8132
|
// === 迁移 ===
|
|
7941
8133
|
/** 迁移旧索引:session-index.json 里有 "discord:xxx" 格式的 key 时,生成 UUID 替换 */
|
|
@@ -8000,7 +8192,7 @@ var init_session_manager = __esm({
|
|
|
8000
8192
|
});
|
|
8001
8193
|
|
|
8002
8194
|
// src/utils/path.ts
|
|
8003
|
-
import * as
|
|
8195
|
+
import * as path11 from "node:path";
|
|
8004
8196
|
function fixMsysPath(p) {
|
|
8005
8197
|
let fixed = p.includes("\\") ? p.replace(/\\/g, "/") : p;
|
|
8006
8198
|
if (process.platform === "win32") {
|
|
@@ -8010,15 +8202,15 @@ function fixMsysPath(p) {
|
|
|
8010
8202
|
}
|
|
8011
8203
|
function resolvePath(p, workspace) {
|
|
8012
8204
|
const fixed = fixMsysPath(p);
|
|
8013
|
-
const resolved =
|
|
8014
|
-
const normalized =
|
|
8015
|
-
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);
|
|
8016
8208
|
if (sandboxOff) return normalized;
|
|
8017
|
-
if (normalized === normalizedWorkspace || normalized.startsWith(normalizedWorkspace +
|
|
8209
|
+
if (normalized === normalizedWorkspace || normalized.startsWith(normalizedWorkspace + path11.sep)) {
|
|
8018
8210
|
return normalized;
|
|
8019
8211
|
}
|
|
8020
8212
|
for (const allowed of extraAllowedPaths) {
|
|
8021
|
-
if (normalized === allowed || normalized.startsWith(allowed +
|
|
8213
|
+
if (normalized === allowed || normalized.startsWith(allowed + path11.sep)) {
|
|
8022
8214
|
return normalized;
|
|
8023
8215
|
}
|
|
8024
8216
|
}
|
|
@@ -8034,15 +8226,15 @@ var init_path = __esm({
|
|
|
8034
8226
|
});
|
|
8035
8227
|
|
|
8036
8228
|
// src/tools/read.ts
|
|
8037
|
-
import * as
|
|
8038
|
-
import * as
|
|
8229
|
+
import * as fs11 from "node:fs";
|
|
8230
|
+
import * as path12 from "node:path";
|
|
8039
8231
|
function isBlockedDevicePath(filePath) {
|
|
8040
8232
|
if (BLOCKED_DEVICE_PATHS.has(filePath)) return true;
|
|
8041
8233
|
if (filePath.startsWith("/proc/") && (filePath.endsWith("/fd/0") || filePath.endsWith("/fd/1") || filePath.endsWith("/fd/2"))) return true;
|
|
8042
8234
|
return false;
|
|
8043
8235
|
}
|
|
8044
8236
|
function checkReadLoop(filePath, offset, limit) {
|
|
8045
|
-
const stat4 =
|
|
8237
|
+
const stat4 = fs11.statSync(filePath);
|
|
8046
8238
|
const mtimeMs = stat4.mtimeMs;
|
|
8047
8239
|
const prev = readHistory.get(filePath);
|
|
8048
8240
|
if (prev && prev.offset === offset && prev.limit === limit && prev.mtimeMs === mtimeMs) {
|
|
@@ -8056,19 +8248,19 @@ function checkReadLoop(filePath, offset, limit) {
|
|
|
8056
8248
|
return null;
|
|
8057
8249
|
}
|
|
8058
8250
|
function readFileContent(filePath) {
|
|
8059
|
-
const fd =
|
|
8251
|
+
const fd = fs11.openSync(filePath, "r");
|
|
8060
8252
|
const bom = Buffer.alloc(2);
|
|
8061
|
-
|
|
8062
|
-
|
|
8253
|
+
fs11.readSync(fd, bom, 0, 2, 0);
|
|
8254
|
+
fs11.closeSync(fd);
|
|
8063
8255
|
let encoding = "utf8";
|
|
8064
8256
|
if (bom[0] === 255 && bom[1] === 254) {
|
|
8065
8257
|
encoding = "utf16le";
|
|
8066
8258
|
}
|
|
8067
|
-
const stat4 =
|
|
8259
|
+
const stat4 = fs11.statSync(filePath);
|
|
8068
8260
|
if (stat4.size > MAX_FILE_SIZE) {
|
|
8069
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`);
|
|
8070
8262
|
}
|
|
8071
|
-
const raw =
|
|
8263
|
+
const raw = fs11.readFileSync(filePath, encoding);
|
|
8072
8264
|
const content = raw.toString().replaceAll("\r\n", "\n");
|
|
8073
8265
|
return { content, encoding };
|
|
8074
8266
|
}
|
|
@@ -8210,11 +8402,11 @@ Usage:
|
|
|
8210
8402
|
} catch (e) {
|
|
8211
8403
|
return { content: e.message, isError: true };
|
|
8212
8404
|
}
|
|
8213
|
-
if (!
|
|
8405
|
+
if (!fs11.existsSync(filePath)) {
|
|
8214
8406
|
return { content: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`, isError: true };
|
|
8215
8407
|
}
|
|
8216
|
-
const stat4 =
|
|
8217
|
-
const baseName =
|
|
8408
|
+
const stat4 = fs11.statSync(filePath);
|
|
8409
|
+
const baseName = path12.basename(filePath).toUpperCase();
|
|
8218
8410
|
if (BLOCKED_BASENAMES.has(baseName)) {
|
|
8219
8411
|
return { content: `\u8BBE\u5907\u6587\u4EF6\u4E0D\u652F\u6301\u8BFB\u53D6: ${filePath}`, isError: true };
|
|
8220
8412
|
}
|
|
@@ -8222,11 +8414,11 @@ Usage:
|
|
|
8222
8414
|
return { content: `\u8BBE\u5907\u6587\u4EF6\u4F1A\u963B\u585E\u6216\u4EA7\u751F\u65E0\u9650\u8F93\u51FA: ${filePath}`, isError: true };
|
|
8223
8415
|
}
|
|
8224
8416
|
if (stat4.isDirectory()) {
|
|
8225
|
-
const entries2 =
|
|
8417
|
+
const entries2 = fs11.readdirSync(filePath);
|
|
8226
8418
|
const items = entries2.map((e) => {
|
|
8227
|
-
const full =
|
|
8419
|
+
const full = path12.join(filePath, e);
|
|
8228
8420
|
try {
|
|
8229
|
-
const s =
|
|
8421
|
+
const s = fs11.statSync(full);
|
|
8230
8422
|
return s.isDirectory() ? `${e}/` : e;
|
|
8231
8423
|
} catch {
|
|
8232
8424
|
return e;
|
|
@@ -8235,7 +8427,7 @@ Usage:
|
|
|
8235
8427
|
return { content: `\u76EE\u5F55 (${entries2.length} \u9879):
|
|
8236
8428
|
${items.join("\n")}` };
|
|
8237
8429
|
}
|
|
8238
|
-
const ext =
|
|
8430
|
+
const ext = path12.extname(filePath).toLowerCase();
|
|
8239
8431
|
if (BINARY_EXTENSIONS.has(ext)) {
|
|
8240
8432
|
return { content: `\u4E8C\u8FDB\u5236\u6587\u4EF6\u4E0D\u652F\u6301\u8BFB\u53D6 (${ext}): ${filePath}`, isError: true };
|
|
8241
8433
|
}
|
|
@@ -8282,22 +8474,22 @@ ${result2}` : result2 };
|
|
|
8282
8474
|
});
|
|
8283
8475
|
|
|
8284
8476
|
// src/tools/write.ts
|
|
8285
|
-
import * as
|
|
8286
|
-
import * as
|
|
8477
|
+
import * as fs12 from "node:fs";
|
|
8478
|
+
import * as path13 from "node:path";
|
|
8287
8479
|
function isBlockedPath(filePath) {
|
|
8288
8480
|
return BLOCKED_PATTERNS.some((p) => p.test(filePath));
|
|
8289
8481
|
}
|
|
8290
8482
|
function atomicWrite(filePath, content) {
|
|
8291
8483
|
const tmpPath = filePath + ".tmp." + Date.now() + ".write";
|
|
8292
|
-
|
|
8484
|
+
fs12.writeFileSync(tmpPath, content, "utf-8");
|
|
8293
8485
|
try {
|
|
8294
|
-
|
|
8486
|
+
fs12.renameSync(tmpPath, filePath);
|
|
8295
8487
|
} catch (e) {
|
|
8296
8488
|
try {
|
|
8297
|
-
|
|
8489
|
+
fs12.unlinkSync(tmpPath);
|
|
8298
8490
|
} catch {
|
|
8299
8491
|
}
|
|
8300
|
-
|
|
8492
|
+
fs12.writeFileSync(filePath, content, "utf-8");
|
|
8301
8493
|
}
|
|
8302
8494
|
}
|
|
8303
8495
|
function simpleDiff(oldContent, newContent) {
|
|
@@ -8391,15 +8583,15 @@ Usage:
|
|
|
8391
8583
|
}
|
|
8392
8584
|
const rawContent = args.content;
|
|
8393
8585
|
const content = rawContent.replaceAll("\r\n", "\n");
|
|
8394
|
-
if (
|
|
8586
|
+
if (fs12.existsSync(filePath) && fs12.statSync(filePath).isDirectory()) {
|
|
8395
8587
|
return { content: `\u8DEF\u5F84\u662F\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6: ${filePath}`, isError: true };
|
|
8396
8588
|
}
|
|
8397
8589
|
let oldContent = null;
|
|
8398
8590
|
let isCreate = true;
|
|
8399
|
-
if (
|
|
8591
|
+
if (fs12.existsSync(filePath)) {
|
|
8400
8592
|
isCreate = false;
|
|
8401
8593
|
try {
|
|
8402
|
-
oldContent =
|
|
8594
|
+
oldContent = fs12.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
|
|
8403
8595
|
} catch {
|
|
8404
8596
|
isCreate = true;
|
|
8405
8597
|
}
|
|
@@ -8415,10 +8607,10 @@ Usage:
|
|
|
8415
8607
|
isError: true
|
|
8416
8608
|
};
|
|
8417
8609
|
}
|
|
8418
|
-
const currentStat =
|
|
8610
|
+
const currentStat = fs12.statSync(filePath);
|
|
8419
8611
|
const lastWriteTime = Math.floor(currentStat.mtimeMs);
|
|
8420
8612
|
if (lastWriteTime > readState.timestamp) {
|
|
8421
|
-
const currentContent =
|
|
8613
|
+
const currentContent = fs12.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
|
|
8422
8614
|
if (currentContent !== oldContent) {
|
|
8423
8615
|
return {
|
|
8424
8616
|
content: `\u6587\u4EF6\u5728\u8BFB\u53D6\u540E\u88AB\u4FEE\u6539\u3002\u8BF7\u5148\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\u518D\u5199\u5165: ${filePath}`,
|
|
@@ -8427,9 +8619,9 @@ Usage:
|
|
|
8427
8619
|
}
|
|
8428
8620
|
}
|
|
8429
8621
|
}
|
|
8430
|
-
const dir =
|
|
8622
|
+
const dir = path13.dirname(filePath);
|
|
8431
8623
|
try {
|
|
8432
|
-
|
|
8624
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
8433
8625
|
} catch (e) {
|
|
8434
8626
|
return { content: `\u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55: ${dir} \u2014 ${e.message}`, isError: true };
|
|
8435
8627
|
}
|
|
@@ -8438,11 +8630,11 @@ Usage:
|
|
|
8438
8630
|
} catch (e) {
|
|
8439
8631
|
return { content: `\u5199\u5165\u5931\u8D25: ${e.message}`, isError: true };
|
|
8440
8632
|
}
|
|
8441
|
-
readFileState.set(filePath, { timestamp:
|
|
8633
|
+
readFileState.set(filePath, { timestamp: fs12.statSync(filePath).mtimeMs });
|
|
8442
8634
|
const action = isCreate ? "\u521B\u5EFA" : "\u66F4\u65B0";
|
|
8443
8635
|
const lines = content.split("\n").length;
|
|
8444
8636
|
const chars = content.length;
|
|
8445
|
-
const stat4 =
|
|
8637
|
+
const stat4 = fs12.statSync(filePath);
|
|
8446
8638
|
let diff = "";
|
|
8447
8639
|
if (!isCreate && oldContent !== null) {
|
|
8448
8640
|
diff = `
|
|
@@ -8461,8 +8653,8 @@ ${simpleDiff(oldContent, content)}`;
|
|
|
8461
8653
|
});
|
|
8462
8654
|
|
|
8463
8655
|
// src/tools/edit.ts
|
|
8464
|
-
import * as
|
|
8465
|
-
import * as
|
|
8656
|
+
import * as fs13 from "node:fs";
|
|
8657
|
+
import * as path14 from "node:path";
|
|
8466
8658
|
function normalizeQuotes(str) {
|
|
8467
8659
|
return str.replaceAll(LEFT_SINGLE_CURLY, "'").replaceAll(RIGHT_SINGLE_CURLY, "'").replaceAll(LEFT_DOUBLE_CURLY, '"').replaceAll(RIGHT_DOUBLE_CURLY, '"');
|
|
8468
8660
|
}
|
|
@@ -8615,7 +8807,7 @@ Usage:
|
|
|
8615
8807
|
}
|
|
8616
8808
|
let fileContent = null;
|
|
8617
8809
|
try {
|
|
8618
|
-
const stat4 =
|
|
8810
|
+
const stat4 = fs13.statSync(filePath);
|
|
8619
8811
|
if (stat4.isDirectory()) {
|
|
8620
8812
|
return { content: `\u8DEF\u5F84\u662F\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6: ${filePath}`, isError: true };
|
|
8621
8813
|
}
|
|
@@ -8625,21 +8817,21 @@ Usage:
|
|
|
8625
8817
|
} catch (e) {
|
|
8626
8818
|
if (e.code === "ENOENT") {
|
|
8627
8819
|
if (oldString === "") {
|
|
8628
|
-
const dir =
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
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 });
|
|
8632
8824
|
return { content: `\u521B\u5EFA\u6587\u4EF6: ${filePath} (${newString.split("\n").length} \u884C)` };
|
|
8633
8825
|
}
|
|
8634
8826
|
return { content: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`, isError: true };
|
|
8635
8827
|
}
|
|
8636
8828
|
throw e;
|
|
8637
8829
|
}
|
|
8638
|
-
const rawContent =
|
|
8830
|
+
const rawContent = fs13.readFileSync(filePath, "utf-8");
|
|
8639
8831
|
fileContent = rawContent.replaceAll("\r\n", "\n");
|
|
8640
8832
|
if (oldString === "" && fileContent.trim() === "") {
|
|
8641
|
-
|
|
8642
|
-
readFileState.set(filePath, { timestamp:
|
|
8833
|
+
fs13.writeFileSync(filePath, newString, "utf-8");
|
|
8834
|
+
readFileState.set(filePath, { timestamp: fs13.statSync(filePath).mtimeMs });
|
|
8643
8835
|
return { content: `\u5199\u5165\u7A7A\u6587\u4EF6: ${filePath} (${newString.split("\n").length} \u884C)` };
|
|
8644
8836
|
}
|
|
8645
8837
|
const readState = readFileState.get(filePath);
|
|
@@ -8649,11 +8841,11 @@ Usage:
|
|
|
8649
8841
|
isError: true
|
|
8650
8842
|
};
|
|
8651
8843
|
}
|
|
8652
|
-
const currentStat =
|
|
8844
|
+
const currentStat = fs13.statSync(filePath);
|
|
8653
8845
|
const lastWriteTime = Math.floor(currentStat.mtimeMs);
|
|
8654
8846
|
if (lastWriteTime > readState.timestamp) {
|
|
8655
8847
|
if (fileContent !== rawContent.replaceAll("\r\n", "\n")) {
|
|
8656
|
-
if (fileContent !==
|
|
8848
|
+
if (fileContent !== fs13.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n")) {
|
|
8657
8849
|
return {
|
|
8658
8850
|
content: `\u6587\u4EF6\u5728\u8BFB\u53D6\u540E\u88AB\u4FEE\u6539\u3002\u8BF7\u5148\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\u518D\u7F16\u8F91: ${filePath}`,
|
|
8659
8851
|
isError: true
|
|
@@ -8685,8 +8877,8 @@ ${preview}
|
|
|
8685
8877
|
const actualNewString = preserveQuoteStyle(oldString, actualOldString, newString);
|
|
8686
8878
|
const diffView = generateEditDiff(fileContent, actualOldString, actualNewString);
|
|
8687
8879
|
const newContent = applyEditToFile(fileContent, actualOldString, actualNewString, replaceAll);
|
|
8688
|
-
|
|
8689
|
-
readFileState.set(filePath, { timestamp:
|
|
8880
|
+
fs13.writeFileSync(filePath, newContent, "utf-8");
|
|
8881
|
+
readFileState.set(filePath, { timestamp: fs13.statSync(filePath).mtimeMs });
|
|
8690
8882
|
const strategy = actualOldString === oldString ? "\u7CBE\u786E\u5339\u914D" : "\u5F15\u53F7\u89C4\u8303\u5316\u5339\u914D";
|
|
8691
8883
|
const count = replaceAll ? matchCount : 1;
|
|
8692
8884
|
const diff = `${oldString.length}\u2192${newString.length}\u5B57\u7B26`;
|
|
@@ -8703,8 +8895,8 @@ ${diffView}`
|
|
|
8703
8895
|
});
|
|
8704
8896
|
|
|
8705
8897
|
// src/tools/glob.ts
|
|
8706
|
-
import * as
|
|
8707
|
-
import * as
|
|
8898
|
+
import * as fs14 from "node:fs";
|
|
8899
|
+
import * as path15 from "node:path";
|
|
8708
8900
|
function globMatch(pattern, filename) {
|
|
8709
8901
|
const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
8710
8902
|
try {
|
|
@@ -8724,18 +8916,18 @@ function findFiles(dir, pattern, limit, baseDir) {
|
|
|
8724
8916
|
}
|
|
8725
8917
|
let entries2;
|
|
8726
8918
|
try {
|
|
8727
|
-
entries2 =
|
|
8919
|
+
entries2 = fs14.readdirSync(currentDir, { withFileTypes: true });
|
|
8728
8920
|
} catch {
|
|
8729
8921
|
return;
|
|
8730
8922
|
}
|
|
8731
8923
|
for (const entry of entries2) {
|
|
8732
8924
|
if (truncated) return;
|
|
8733
|
-
const fullPath =
|
|
8925
|
+
const fullPath = path15.join(currentDir, entry.name);
|
|
8734
8926
|
if (entry.isDirectory()) {
|
|
8735
8927
|
if (VCS_DIRS.has(entry.name)) continue;
|
|
8736
8928
|
walk(fullPath);
|
|
8737
8929
|
} else if (entry.isFile()) {
|
|
8738
|
-
const relativePath =
|
|
8930
|
+
const relativePath = path15.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
8739
8931
|
const patternsToTry = [pattern];
|
|
8740
8932
|
if (pattern.startsWith("**/")) {
|
|
8741
8933
|
patternsToTry.push(pattern.slice(3));
|
|
@@ -8745,7 +8937,7 @@ function findFiles(dir, pattern, limit, baseDir) {
|
|
|
8745
8937
|
);
|
|
8746
8938
|
if (matched) {
|
|
8747
8939
|
try {
|
|
8748
|
-
const stat4 =
|
|
8940
|
+
const stat4 = fs14.statSync(fullPath);
|
|
8749
8941
|
results.push({ path: fullPath, mtimeMs: stat4.mtimeMs });
|
|
8750
8942
|
} catch {
|
|
8751
8943
|
}
|
|
@@ -8762,7 +8954,7 @@ function findFiles(dir, pattern, limit, baseDir) {
|
|
|
8762
8954
|
};
|
|
8763
8955
|
}
|
|
8764
8956
|
function toRelativePath(absolutePath, cwd) {
|
|
8765
|
-
if (absolutePath.startsWith(cwd +
|
|
8957
|
+
if (absolutePath.startsWith(cwd + path15.sep)) {
|
|
8766
8958
|
return absolutePath.slice(cwd.length + 1);
|
|
8767
8959
|
}
|
|
8768
8960
|
return absolutePath;
|
|
@@ -8795,10 +8987,10 @@ var init_glob = __esm({
|
|
|
8795
8987
|
const searchPath = args.path ? resolvePath(args.path, ctx.workspace) : ctx.workspace;
|
|
8796
8988
|
const pattern = args.pattern;
|
|
8797
8989
|
const limit = args.limit || DEFAULT_LIMIT;
|
|
8798
|
-
if (!
|
|
8990
|
+
if (!fs14.existsSync(searchPath)) {
|
|
8799
8991
|
return { content: `\u76EE\u5F55\u4E0D\u5B58\u5728: ${searchPath}`, isError: true };
|
|
8800
8992
|
}
|
|
8801
|
-
if (!
|
|
8993
|
+
if (!fs14.statSync(searchPath).isDirectory()) {
|
|
8802
8994
|
return { content: `\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${searchPath}`, isError: true };
|
|
8803
8995
|
}
|
|
8804
8996
|
const start = Date.now();
|
|
@@ -8822,7 +9014,7 @@ ${filenames.join("\n")}${truncatedNote}`
|
|
|
8822
9014
|
|
|
8823
9015
|
// src/tools/grep.ts
|
|
8824
9016
|
import { execFile } from "node:child_process";
|
|
8825
|
-
import * as
|
|
9017
|
+
import * as path16 from "node:path";
|
|
8826
9018
|
function ripGrep(args, searchPath, signal) {
|
|
8827
9019
|
return new Promise((resolve11) => {
|
|
8828
9020
|
const fullArgs = [...args, searchPath];
|
|
@@ -8854,7 +9046,7 @@ function applyHeadLimit(items, limit, offset = 0) {
|
|
|
8854
9046
|
};
|
|
8855
9047
|
}
|
|
8856
9048
|
function toRelativePath2(absolutePath, cwd) {
|
|
8857
|
-
if (absolutePath.startsWith(cwd +
|
|
9049
|
+
if (absolutePath.startsWith(cwd + path16.sep)) {
|
|
8858
9050
|
return absolutePath.slice(cwd.length + 1);
|
|
8859
9051
|
}
|
|
8860
9052
|
if (absolutePath.startsWith(cwd)) {
|
|
@@ -9024,12 +9216,14 @@ ${filenames.join("\n")}${truncatedNote}`
|
|
|
9024
9216
|
// src/tools/task-manager.ts
|
|
9025
9217
|
var task_manager_exports = {};
|
|
9026
9218
|
__export(task_manager_exports, {
|
|
9219
|
+
ackPendingNotification: () => ackPendingNotification,
|
|
9027
9220
|
buildCalendarNotification: () => buildCalendarNotification,
|
|
9028
9221
|
buildNudgeNotification: () => buildNudgeNotification,
|
|
9029
9222
|
clearNotificationCallback: () => clearNotificationCallback,
|
|
9030
9223
|
drainPendingNotifications: () => drainPendingNotifications,
|
|
9031
9224
|
enqueueNotification: () => enqueueNotification,
|
|
9032
9225
|
generateTaskId: () => generateTaskId,
|
|
9226
|
+
getPendingNotificationRecords: () => getPendingNotificationRecords,
|
|
9033
9227
|
getPendingNotifications: () => getPendingNotifications,
|
|
9034
9228
|
getTask: () => getTask,
|
|
9035
9229
|
getTaskOutput: () => getTaskOutput,
|
|
@@ -9038,14 +9232,16 @@ __export(task_manager_exports, {
|
|
|
9038
9232
|
getTaskOutputPath: () => getTaskOutputPath,
|
|
9039
9233
|
getTaskOutputSize: () => getTaskOutputSize,
|
|
9040
9234
|
killTask: () => killTask,
|
|
9235
|
+
listLiveTasks: () => listLiveTasks,
|
|
9041
9236
|
listTasks: () => listTasks,
|
|
9237
|
+
loadPersistedTasks: () => loadPersistedTasks,
|
|
9042
9238
|
setNotificationCallback: () => setNotificationCallback,
|
|
9043
9239
|
spawnBackgroundTask: () => spawnBackgroundTask
|
|
9044
9240
|
});
|
|
9045
9241
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
9046
9242
|
import { spawn as spawn2 } from "node:child_process";
|
|
9047
|
-
import * as
|
|
9048
|
-
import * as
|
|
9243
|
+
import * as fs15 from "node:fs";
|
|
9244
|
+
import * as path17 from "node:path";
|
|
9049
9245
|
function generateTaskId(type2 = "local_bash") {
|
|
9050
9246
|
const prefix = TASK_ID_PREFIXES[type2] ?? "x";
|
|
9051
9247
|
const bytes = randomBytes3(8);
|
|
@@ -9058,60 +9254,182 @@ function generateTaskId(type2 = "local_bash") {
|
|
|
9058
9254
|
function getTaskOutputDir() {
|
|
9059
9255
|
if (_taskOutputDir === void 0) {
|
|
9060
9256
|
const stateDir = process.env.ENGINE_STATE_DIR || process.cwd();
|
|
9061
|
-
_taskOutputDir =
|
|
9257
|
+
_taskOutputDir = path17.join(stateDir, "tasks");
|
|
9062
9258
|
}
|
|
9063
9259
|
return _taskOutputDir;
|
|
9064
9260
|
}
|
|
9065
9261
|
function getTaskOutputPath(taskId) {
|
|
9066
|
-
return
|
|
9262
|
+
return path17.join(getTaskOutputDir(), `${taskId}.output`);
|
|
9067
9263
|
}
|
|
9068
9264
|
function ensureOutputDir() {
|
|
9069
9265
|
const dir = getTaskOutputDir();
|
|
9070
|
-
if (!
|
|
9071
|
-
|
|
9266
|
+
if (!fs15.existsSync(dir)) {
|
|
9267
|
+
fs15.mkdirSync(dir, { recursive: true });
|
|
9072
9268
|
}
|
|
9073
9269
|
}
|
|
9074
9270
|
function initTaskOutput(taskId) {
|
|
9075
9271
|
ensureOutputDir();
|
|
9076
9272
|
const outputPath = getTaskOutputPath(taskId);
|
|
9077
|
-
|
|
9273
|
+
fs15.writeFileSync(outputPath, "", "utf-8");
|
|
9078
9274
|
return outputPath;
|
|
9079
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
|
+
}
|
|
9080
9361
|
function setNotificationCallback(cb) {
|
|
9081
9362
|
notificationCallback = cb;
|
|
9363
|
+
loadNotificationQueue();
|
|
9364
|
+
if (pendingNotifications.length === 0) return;
|
|
9365
|
+
attemptDueNotifications();
|
|
9082
9366
|
}
|
|
9083
9367
|
function clearNotificationCallback() {
|
|
9084
9368
|
notificationCallback = null;
|
|
9369
|
+
if (notificationRetryTimer) {
|
|
9370
|
+
clearTimeout(notificationRetryTimer);
|
|
9371
|
+
notificationRetryTimer = void 0;
|
|
9372
|
+
}
|
|
9085
9373
|
}
|
|
9086
|
-
function enqueueNotification(notification, route) {
|
|
9374
|
+
function enqueueNotification(notification, route, idempotencyKey) {
|
|
9375
|
+
loadNotificationQueue();
|
|
9376
|
+
if (idempotencyKey && pendingNotifications.some((item) => item.idempotencyKey === idempotencyKey)) return;
|
|
9087
9377
|
if (notificationCallback) {
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
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
|
+
}
|
|
9091
9389
|
}
|
|
9092
|
-
pendingNotifications.push(notification);
|
|
9390
|
+
pendingNotifications.push({ id: `n-${Date.now()}-${randomBytes3(4).toString("hex")}`, notification, route, createdAt: (/* @__PURE__ */ new Date()).toISOString(), idempotencyKey });
|
|
9391
|
+
persistNotificationQueue();
|
|
9093
9392
|
console.log(`[task-manager] Notification queued (${pendingNotifications.length} pending, no callback)`);
|
|
9094
9393
|
}
|
|
9095
9394
|
function getPendingNotifications() {
|
|
9096
|
-
|
|
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;
|
|
9097
9410
|
}
|
|
9098
9411
|
function drainPendingNotifications() {
|
|
9099
|
-
|
|
9412
|
+
loadNotificationQueue();
|
|
9413
|
+
const due = pendingNotifications.filter((item) => notificationDue(item));
|
|
9414
|
+
if (due.length === 0) return [];
|
|
9415
|
+
const kept = pendingNotifications.filter((item) => !notificationDue(item));
|
|
9100
9416
|
pendingNotifications.length = 0;
|
|
9101
|
-
|
|
9417
|
+
pendingNotifications.push(...kept);
|
|
9418
|
+
persistNotificationQueue();
|
|
9419
|
+
return due.map((item) => item.notification);
|
|
9102
9420
|
}
|
|
9103
9421
|
function spawnBackgroundTask(opts) {
|
|
9104
9422
|
const taskId = generateTaskId("local_bash");
|
|
9105
9423
|
const outputPath = initTaskOutput(taskId);
|
|
9106
9424
|
const { shell, args: shellArgs } = findShell();
|
|
9107
|
-
const outputFd =
|
|
9425
|
+
const outputFd = fs15.openSync(outputPath, "w");
|
|
9108
9426
|
const child = spawn2(shell, [...shellArgs, opts.command], {
|
|
9109
9427
|
cwd: opts.cwd,
|
|
9110
9428
|
env: opts.env || process.env,
|
|
9111
9429
|
stdio: ["ignore", outputFd, outputFd]
|
|
9112
9430
|
});
|
|
9113
9431
|
try {
|
|
9114
|
-
|
|
9432
|
+
fs15.closeSync(outputFd);
|
|
9115
9433
|
} catch {
|
|
9116
9434
|
}
|
|
9117
9435
|
processes.set(taskId, child);
|
|
@@ -9129,6 +9447,7 @@ function spawnBackgroundTask(opts) {
|
|
|
9129
9447
|
channelTarget: opts.channelTarget
|
|
9130
9448
|
};
|
|
9131
9449
|
tasks.set(taskId, taskState);
|
|
9450
|
+
persistTask(taskState);
|
|
9132
9451
|
let timer;
|
|
9133
9452
|
if (opts.timeout && opts.timeout > 0) {
|
|
9134
9453
|
timer = setTimeout(() => {
|
|
@@ -9142,12 +9461,12 @@ function spawnBackgroundTask(opts) {
|
|
|
9142
9461
|
let killedForSize = false;
|
|
9143
9462
|
sizeWatchdog = setInterval(() => {
|
|
9144
9463
|
if (tasks.get(taskId)?.status !== "running") return;
|
|
9145
|
-
|
|
9464
|
+
fs15.stat(outputPath, (err, st) => {
|
|
9146
9465
|
if (err || st.size <= MAX_TASK_OUTPUT_BYTES) return;
|
|
9147
9466
|
killedForSize = true;
|
|
9148
9467
|
if (sizeWatchdog) clearInterval(sizeWatchdog);
|
|
9149
9468
|
try {
|
|
9150
|
-
|
|
9469
|
+
fs15.appendFileSync(outputPath, "\n[output truncated: exceeded 5GB disk cap]\n");
|
|
9151
9470
|
} catch {
|
|
9152
9471
|
}
|
|
9153
9472
|
killChild(child);
|
|
@@ -9165,8 +9484,15 @@ function spawnBackgroundTask(opts) {
|
|
|
9165
9484
|
state2.status = status;
|
|
9166
9485
|
state2.exitCode = exitCode;
|
|
9167
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
|
+
}
|
|
9168
9493
|
if (!state2.notified) {
|
|
9169
9494
|
state2.notified = true;
|
|
9495
|
+
persistTask(state2);
|
|
9170
9496
|
const summary = buildSummary(state2);
|
|
9171
9497
|
const notification = buildTaskNotification(taskId, outputPath, status, summary);
|
|
9172
9498
|
enqueueNotification(notification, { sessionId: state2.sessionId, channel: state2.channel, channelTarget: state2.channelTarget });
|
|
@@ -9221,6 +9547,12 @@ function getTask(taskId) {
|
|
|
9221
9547
|
return tasks.get(taskId);
|
|
9222
9548
|
}
|
|
9223
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() {
|
|
9224
9556
|
return [...tasks.values()];
|
|
9225
9557
|
}
|
|
9226
9558
|
function getTaskOutput(taskId, maxBytes = 8 * 1024 * 1024) {
|
|
@@ -9228,16 +9560,16 @@ function getTaskOutput(taskId, maxBytes = 8 * 1024 * 1024) {
|
|
|
9228
9560
|
if (!state2) return "";
|
|
9229
9561
|
try {
|
|
9230
9562
|
const outputPath = state2.outputFile;
|
|
9231
|
-
if (!
|
|
9232
|
-
const stat4 =
|
|
9563
|
+
if (!fs15.existsSync(outputPath)) return "";
|
|
9564
|
+
const stat4 = fs15.statSync(outputPath);
|
|
9233
9565
|
if (stat4.size <= maxBytes) {
|
|
9234
|
-
return
|
|
9566
|
+
return fs15.readFileSync(outputPath, "utf-8");
|
|
9235
9567
|
}
|
|
9236
|
-
const fd =
|
|
9568
|
+
const fd = fs15.openSync(outputPath, "r");
|
|
9237
9569
|
const start = stat4.size - maxBytes;
|
|
9238
9570
|
const buf = Buffer.alloc(maxBytes);
|
|
9239
|
-
|
|
9240
|
-
|
|
9571
|
+
fs15.readSync(fd, buf, 0, maxBytes, start);
|
|
9572
|
+
fs15.closeSync(fd);
|
|
9241
9573
|
const content = buf.toString("utf-8");
|
|
9242
9574
|
const omitted = Math.round((stat4.size - maxBytes) / 1024);
|
|
9243
9575
|
return `[${omitted}KB of earlier output omitted]
|
|
@@ -9251,14 +9583,14 @@ function getTaskOutputDelta(taskId, fromOffset, maxBytes = 8 * 1024 * 1024) {
|
|
|
9251
9583
|
if (!state2) return { content: "", newOffset: fromOffset };
|
|
9252
9584
|
try {
|
|
9253
9585
|
const outputPath = state2.outputFile;
|
|
9254
|
-
if (!
|
|
9255
|
-
const stat4 =
|
|
9586
|
+
if (!fs15.existsSync(outputPath)) return { content: "", newOffset: fromOffset };
|
|
9587
|
+
const stat4 = fs15.statSync(outputPath);
|
|
9256
9588
|
if (fromOffset >= stat4.size) return { content: "", newOffset: stat4.size };
|
|
9257
9589
|
const readLen = Math.min(maxBytes, stat4.size - fromOffset);
|
|
9258
9590
|
const buf = Buffer.alloc(readLen);
|
|
9259
|
-
const fd =
|
|
9260
|
-
|
|
9261
|
-
|
|
9591
|
+
const fd = fs15.openSync(outputPath, "r");
|
|
9592
|
+
fs15.readSync(fd, buf, 0, readLen, fromOffset);
|
|
9593
|
+
fs15.closeSync(fd);
|
|
9262
9594
|
return { content: buf.toString("utf-8"), newOffset: fromOffset + readLen };
|
|
9263
9595
|
} catch {
|
|
9264
9596
|
return { content: "", newOffset: fromOffset };
|
|
@@ -9268,8 +9600,8 @@ function getTaskOutputSize(taskId) {
|
|
|
9268
9600
|
const state2 = tasks.get(taskId);
|
|
9269
9601
|
if (!state2) return 0;
|
|
9270
9602
|
try {
|
|
9271
|
-
if (!
|
|
9272
|
-
return
|
|
9603
|
+
if (!fs15.existsSync(state2.outputFile)) return 0;
|
|
9604
|
+
return fs15.statSync(state2.outputFile).size;
|
|
9273
9605
|
} catch {
|
|
9274
9606
|
return 0;
|
|
9275
9607
|
}
|
|
@@ -9293,7 +9625,7 @@ function killTask(taskId) {
|
|
|
9293
9625
|
}
|
|
9294
9626
|
return true;
|
|
9295
9627
|
}
|
|
9296
|
-
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;
|
|
9297
9629
|
var init_task_manager = __esm({
|
|
9298
9630
|
"src/tools/task-manager.ts"() {
|
|
9299
9631
|
"use strict";
|
|
@@ -9307,8 +9639,13 @@ var init_task_manager = __esm({
|
|
|
9307
9639
|
MAX_TASK_OUTPUT_BYTES = 5 * 1024 * 1024 * 1024;
|
|
9308
9640
|
tasks = /* @__PURE__ */ new Map();
|
|
9309
9641
|
processes = /* @__PURE__ */ new Map();
|
|
9642
|
+
taskIndexPath = () => path17.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "index.json");
|
|
9310
9643
|
pendingNotifications = [];
|
|
9644
|
+
notificationsLoaded = false;
|
|
9645
|
+
notificationQueuePath = () => path17.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "notifications.json");
|
|
9311
9646
|
notificationCallback = null;
|
|
9647
|
+
RETRY_BASE_MS = 1e3;
|
|
9648
|
+
RETRY_MAX_MS = 6e4;
|
|
9312
9649
|
TASK_NOTIFICATION_TAG = "task-notification";
|
|
9313
9650
|
TASK_ID_TAG = "task-id";
|
|
9314
9651
|
TASK_TYPE_TAG = "task-type";
|
|
@@ -9547,8 +9884,8 @@ __export(BashTool_exports, {
|
|
|
9547
9884
|
killChild: () => killChild
|
|
9548
9885
|
});
|
|
9549
9886
|
import { spawn as spawn3, execSync } from "node:child_process";
|
|
9550
|
-
import * as
|
|
9551
|
-
import * as
|
|
9887
|
+
import * as fs16 from "node:fs";
|
|
9888
|
+
import * as path18 from "node:path";
|
|
9552
9889
|
function isWslBash(p) {
|
|
9553
9890
|
const normalized = p.replace(/\//g, "\\").toLowerCase();
|
|
9554
9891
|
return WSL_PATH_MARKERS.some((m) => normalized.includes(m.toLowerCase()));
|
|
@@ -9567,7 +9904,7 @@ function findShell() {
|
|
|
9567
9904
|
});
|
|
9568
9905
|
const candidates = result2.trim().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
9569
9906
|
const nonWsl = candidates.find((p) => !isWslBash(p));
|
|
9570
|
-
if (nonWsl &&
|
|
9907
|
+
if (nonWsl && fs16.existsSync(nonWsl)) {
|
|
9571
9908
|
cachedShell = { shell: nonWsl, args: ["-c"] };
|
|
9572
9909
|
return cachedShell;
|
|
9573
9910
|
}
|
|
@@ -9577,10 +9914,10 @@ function findShell() {
|
|
|
9577
9914
|
"C:\\Program Files\\Git\\bin\\bash.exe",
|
|
9578
9915
|
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
9579
9916
|
"C:\\Program Files\\Git\\usr\\bin\\bash.exe",
|
|
9580
|
-
|
|
9917
|
+
path18.join(process.env.LOCALAPPDATA || "", "Programs", "Git", "bin", "bash.exe")
|
|
9581
9918
|
];
|
|
9582
9919
|
for (const p of knownPaths) {
|
|
9583
|
-
if (p &&
|
|
9920
|
+
if (p && fs16.existsSync(p)) {
|
|
9584
9921
|
cachedShell = { shell: p, args: ["-c"] };
|
|
9585
9922
|
return cachedShell;
|
|
9586
9923
|
}
|
|
@@ -9683,8 +10020,8 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
|
|
|
9683
10020
|
}
|
|
9684
10021
|
const MAX_OUTPUT = 100 * 1024;
|
|
9685
10022
|
const osMod = await import("node:os");
|
|
9686
|
-
const outputFile =
|
|
9687
|
-
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");
|
|
9688
10025
|
return new Promise((resolve11) => {
|
|
9689
10026
|
const { shell, args: shellArgs } = findShell();
|
|
9690
10027
|
const child = spawn3(shell, [...shellArgs, command], {
|
|
@@ -9703,21 +10040,21 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
|
|
|
9703
10040
|
let fileOutput = "";
|
|
9704
10041
|
let truncated = false;
|
|
9705
10042
|
try {
|
|
9706
|
-
const st = await
|
|
10043
|
+
const st = await fs16.promises.stat(outputFile);
|
|
9707
10044
|
if (st.size > MAX_OUTPUT) {
|
|
9708
|
-
const rfd = await
|
|
10045
|
+
const rfd = await fs16.promises.open(outputFile, "r");
|
|
9709
10046
|
const buf = Buffer.alloc(MAX_OUTPUT);
|
|
9710
10047
|
await rfd.read(buf, 0, MAX_OUTPUT, 0);
|
|
9711
10048
|
await rfd.close();
|
|
9712
10049
|
fileOutput = buf.toString("utf-8");
|
|
9713
10050
|
truncated = true;
|
|
9714
10051
|
} else {
|
|
9715
|
-
fileOutput = await
|
|
10052
|
+
fileOutput = await fs16.promises.readFile(outputFile, "utf-8");
|
|
9716
10053
|
}
|
|
9717
10054
|
} catch {
|
|
9718
10055
|
}
|
|
9719
10056
|
try {
|
|
9720
|
-
await
|
|
10057
|
+
await fs16.promises.unlink(outputFile);
|
|
9721
10058
|
} catch {
|
|
9722
10059
|
}
|
|
9723
10060
|
const processedStdout = fileOutput.replace(/^(\s*\n)+/, "").trimEnd();
|
|
@@ -10522,23 +10859,23 @@ var init_agentSwarmsEnabled = __esm({
|
|
|
10522
10859
|
});
|
|
10523
10860
|
|
|
10524
10861
|
// src/swarm/teamHelpers.ts
|
|
10525
|
-
import { mkdirSync as
|
|
10862
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
10526
10863
|
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
10527
|
-
import { join as
|
|
10864
|
+
import { join as join16 } from "node:path";
|
|
10528
10865
|
function getTeamsDir() {
|
|
10529
|
-
return
|
|
10866
|
+
return join16(_stateDir, "teams");
|
|
10530
10867
|
}
|
|
10531
10868
|
function getTasksDir() {
|
|
10532
|
-
return
|
|
10869
|
+
return join16(_stateDir, "tasks");
|
|
10533
10870
|
}
|
|
10534
10871
|
function sanitizeName(name) {
|
|
10535
10872
|
return name.replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
|
|
10536
10873
|
}
|
|
10537
10874
|
function getTeamDir(teamName) {
|
|
10538
|
-
return
|
|
10875
|
+
return join16(getTeamsDir(), sanitizeName(teamName));
|
|
10539
10876
|
}
|
|
10540
10877
|
function getTeamFilePath(teamName) {
|
|
10541
|
-
return
|
|
10878
|
+
return join16(getTeamDir(teamName), "config.json");
|
|
10542
10879
|
}
|
|
10543
10880
|
function readTeamFile(teamName) {
|
|
10544
10881
|
try {
|
|
@@ -10605,7 +10942,7 @@ async function cleanupTeamDirectories(teamName) {
|
|
|
10605
10942
|
} catch (error) {
|
|
10606
10943
|
console.warn(`[teamHelpers] Failed to clean up team directory ${teamDir}: ${error.message}`);
|
|
10607
10944
|
}
|
|
10608
|
-
const tasksDir =
|
|
10945
|
+
const tasksDir = join16(getTasksDir(), sanitizedName);
|
|
10609
10946
|
try {
|
|
10610
10947
|
await rm(tasksDir, { recursive: true, force: true });
|
|
10611
10948
|
console.log(`[teamHelpers] Cleaned up tasks directory: ${tasksDir}`);
|
|
@@ -10614,8 +10951,8 @@ async function cleanupTeamDirectories(teamName) {
|
|
|
10614
10951
|
}
|
|
10615
10952
|
}
|
|
10616
10953
|
function ensureTasksDir(taskListId) {
|
|
10617
|
-
const dir =
|
|
10618
|
-
|
|
10954
|
+
const dir = join16(getTasksDir(), taskListId);
|
|
10955
|
+
mkdirSync8(dir, { recursive: true });
|
|
10619
10956
|
}
|
|
10620
10957
|
function setLeaderTeamName(name) {
|
|
10621
10958
|
_leaderTeamName = name;
|
|
@@ -10795,9 +11132,9 @@ The user interacts primarily with the team lead. Your work is coordinated throug
|
|
|
10795
11132
|
|
|
10796
11133
|
// src/swarm/teammateMailbox.ts
|
|
10797
11134
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
10798
|
-
import { join as
|
|
11135
|
+
import { join as join17 } from "node:path";
|
|
10799
11136
|
function getTeamsDir2() {
|
|
10800
|
-
return
|
|
11137
|
+
return join17(process.env.ENGINE_STATE_DIR || ".", "teams");
|
|
10801
11138
|
}
|
|
10802
11139
|
function sanitizePathComponent(s) {
|
|
10803
11140
|
return s.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
@@ -10806,12 +11143,12 @@ function getInboxPath(agentName, teamName) {
|
|
|
10806
11143
|
const team = teamName || "default";
|
|
10807
11144
|
const safeTeam = sanitizePathComponent(team);
|
|
10808
11145
|
const safeAgentName = sanitizePathComponent(agentName);
|
|
10809
|
-
return
|
|
11146
|
+
return join17(getTeamsDir2(), safeTeam, "inboxes", `${safeAgentName}.json`);
|
|
10810
11147
|
}
|
|
10811
11148
|
async function ensureInboxDir(teamName) {
|
|
10812
11149
|
const team = teamName || "default";
|
|
10813
11150
|
const safeTeam = sanitizePathComponent(team);
|
|
10814
|
-
const inboxDir =
|
|
11151
|
+
const inboxDir = join17(getTeamsDir2(), safeTeam, "inboxes");
|
|
10815
11152
|
await mkdir2(inboxDir, { recursive: true });
|
|
10816
11153
|
}
|
|
10817
11154
|
async function sleep4(ms) {
|
|
@@ -10848,7 +11185,7 @@ async function acquireLock(inboxPath) {
|
|
|
10848
11185
|
for (let i = 0; i < LOCK_RETRIES; i++) {
|
|
10849
11186
|
if (await isLockStale(lockPath2)) {
|
|
10850
11187
|
try {
|
|
10851
|
-
await import("node:fs/promises").then((
|
|
11188
|
+
await import("node:fs/promises").then((fs29) => fs29.rm(lockPath2, { force: true }));
|
|
10852
11189
|
} catch {
|
|
10853
11190
|
}
|
|
10854
11191
|
}
|
|
@@ -10856,7 +11193,7 @@ async function acquireLock(inboxPath) {
|
|
|
10856
11193
|
await writeFile2(lockPath2, `${process.pid}-${Date.now()}`, { encoding: "utf-8", flag: "wx" });
|
|
10857
11194
|
return async () => {
|
|
10858
11195
|
try {
|
|
10859
|
-
await import("node:fs/promises").then((
|
|
11196
|
+
await import("node:fs/promises").then((fs29) => fs29.rm(lockPath2, { force: true }));
|
|
10860
11197
|
} catch {
|
|
10861
11198
|
}
|
|
10862
11199
|
};
|
|
@@ -12026,12 +12363,12 @@ Examples:
|
|
|
12026
12363
|
});
|
|
12027
12364
|
|
|
12028
12365
|
// src/tools/msg-husband.ts
|
|
12029
|
-
import
|
|
12030
|
-
import
|
|
12366
|
+
import fs17 from "node:fs";
|
|
12367
|
+
import path19 from "node:path";
|
|
12031
12368
|
function getHusbandFeishuId(workspace) {
|
|
12032
|
-
const contactsPath =
|
|
12369
|
+
const contactsPath = path19.join(workspace, "prompts", "contacts.md");
|
|
12033
12370
|
try {
|
|
12034
|
-
const text =
|
|
12371
|
+
const text = fs17.readFileSync(contactsPath, "utf-8");
|
|
12035
12372
|
const m = text.match(/\|\s*翀哥\s*\|\s*(ou_[a-f0-9]+)\s*\|/);
|
|
12036
12373
|
return m ? m[1] : null;
|
|
12037
12374
|
} catch {
|
|
@@ -12184,8 +12521,8 @@ Examples:
|
|
|
12184
12521
|
if (!to && !resolvedChannelId) {
|
|
12185
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 };
|
|
12186
12523
|
}
|
|
12187
|
-
const
|
|
12188
|
-
if (!
|
|
12524
|
+
const fs29 = await import("node:fs");
|
|
12525
|
+
if (!fs29.existsSync(filePath)) {
|
|
12189
12526
|
return { content: `\u53D1\u9001\u5931\u8D25: \u6587\u4EF6\u4E0D\u5B58\u5728 ${filePath}`, isError: true };
|
|
12190
12527
|
}
|
|
12191
12528
|
const toIds = to ? to.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
@@ -12213,7 +12550,7 @@ Examples:
|
|
|
12213
12550
|
md: "text/markdown"
|
|
12214
12551
|
};
|
|
12215
12552
|
const mimeType = mimeTypeMap[ext] || "application/octet-stream";
|
|
12216
|
-
const stat4 =
|
|
12553
|
+
const stat4 = fs29.statSync(filePath);
|
|
12217
12554
|
const sizeMB = stat4.size / 1024 / 1024;
|
|
12218
12555
|
if (sizeMB > 25) {
|
|
12219
12556
|
return { content: `\u53D1\u9001\u5931\u8D25: \u6587\u4EF6 ${sizeMB.toFixed(1)}MB \u8D85\u8FC7 Discord 25MB \u9650\u5236`, isError: true };
|
|
@@ -12242,12 +12579,12 @@ Examples:
|
|
|
12242
12579
|
});
|
|
12243
12580
|
|
|
12244
12581
|
// src/tools/my-eyes.ts
|
|
12245
|
-
import * as
|
|
12246
|
-
import * as
|
|
12582
|
+
import * as fs18 from "node:fs";
|
|
12583
|
+
import * as path20 from "node:path";
|
|
12247
12584
|
function resolveLatestImage(specifiedPath, mediaDir) {
|
|
12248
|
-
if (specifiedPath &&
|
|
12249
|
-
if (!
|
|
12250
|
-
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);
|
|
12251
12588
|
return files[0]?.p || null;
|
|
12252
12589
|
}
|
|
12253
12590
|
var MIME_MAP;
|
|
@@ -12292,15 +12629,15 @@ var init_my_eyes = __esm({
|
|
|
12292
12629
|
if (!provider?.streamChat) {
|
|
12293
12630
|
return { content: "Error: provider \u4E0D\u53EF\u7528\u3002", isError: true };
|
|
12294
12631
|
}
|
|
12295
|
-
const mediaDir =
|
|
12632
|
+
const mediaDir = path20.join(ctx.stateDir, "media", "inbound");
|
|
12296
12633
|
const imagePath = resolveLatestImage(args.image_path, mediaDir);
|
|
12297
12634
|
if (!imagePath) {
|
|
12298
12635
|
return { content: "Error: no image found. Provide image_path or ensure media/inbound has images.", isError: true };
|
|
12299
12636
|
}
|
|
12300
12637
|
const rawPrompt = args.prompt?.trim() || "\u63CF\u8FF0\u8FD9\u5F20\u56FE\u7247\u7684\u5185\u5BB9";
|
|
12301
|
-
const ext =
|
|
12638
|
+
const ext = path20.extname(imagePath).toLowerCase();
|
|
12302
12639
|
const mime = MIME_MAP[ext] || "jpeg";
|
|
12303
|
-
const imgB64 =
|
|
12640
|
+
const imgB64 = fs18.readFileSync(imagePath).toString("base64");
|
|
12304
12641
|
const userMsg = {
|
|
12305
12642
|
role: "user",
|
|
12306
12643
|
content: [
|
|
@@ -12335,7 +12672,7 @@ var init_my_eyes = __esm({
|
|
|
12335
12672
|
});
|
|
12336
12673
|
|
|
12337
12674
|
// src/tools/opus-encoder.ts
|
|
12338
|
-
import * as
|
|
12675
|
+
import * as fs19 from "node:fs";
|
|
12339
12676
|
function oggCrc32(buf) {
|
|
12340
12677
|
let crc = 0;
|
|
12341
12678
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -12395,7 +12732,7 @@ async function wavToOggOpusNative(wavPath) {
|
|
|
12395
12732
|
const mod = await import("@discordjs/opus");
|
|
12396
12733
|
const OpusEncoder = mod.OpusEncoder ?? mod.default?.OpusEncoder;
|
|
12397
12734
|
if (!OpusEncoder) throw new Error("@discordjs/opus export shape unexpected");
|
|
12398
|
-
const wav = parseWav(
|
|
12735
|
+
const wav = parseWav(fs19.readFileSync(wavPath));
|
|
12399
12736
|
if (wav.channels !== 1) throw new Error(`unsupported ${wav.channels}ch (need mono)`);
|
|
12400
12737
|
if (!NATIVE_RATES.includes(wav.sampleRate)) throw new Error(`unsupported rate ${wav.sampleRate}`);
|
|
12401
12738
|
if (wav.pcm.length === 0) throw new Error("empty pcm data");
|
|
@@ -12431,7 +12768,7 @@ async function wavToOggOpusNative(wavPath) {
|
|
|
12431
12768
|
}
|
|
12432
12769
|
ogg.page(cur, pageGranule, false, true);
|
|
12433
12770
|
const oggPath = wavPath.replace(/\.wav$/, ".ogg");
|
|
12434
|
-
|
|
12771
|
+
fs19.writeFileSync(oggPath, ogg.finish());
|
|
12435
12772
|
return oggPath;
|
|
12436
12773
|
}
|
|
12437
12774
|
var FRAME_MS, PRESKIP_48K, OPUS_RATE, NATIVE_RATES, BITRATE, CRC_TABLE, OggWriter;
|
|
@@ -12511,8 +12848,8 @@ var init_voice_chat_tts_daemon = __esm({
|
|
|
12511
12848
|
import { execFile as execFile2 } from "node:child_process";
|
|
12512
12849
|
import { createInterface as createInterface2 } from "node:readline";
|
|
12513
12850
|
import { promisify } from "node:util";
|
|
12514
|
-
import * as
|
|
12515
|
-
import * as
|
|
12851
|
+
import * as fs20 from "node:fs";
|
|
12852
|
+
import * as path21 from "node:path";
|
|
12516
12853
|
import * as os3 from "node:os";
|
|
12517
12854
|
function resolvePython(configuredPath) {
|
|
12518
12855
|
if (configuredPath) {
|
|
@@ -12548,8 +12885,8 @@ async function ttsCosyvoice(text, apiKey, model, voice, workspaceId, instruction
|
|
|
12548
12885
|
}
|
|
12549
12886
|
async function ttsCosyvoiceStream(text, cfg, onChunk) {
|
|
12550
12887
|
const { apiKey, model, voice, workspaceId, instruction } = cfg;
|
|
12551
|
-
|
|
12552
|
-
const output =
|
|
12888
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
12889
|
+
const output = path21.join(VOICE_DIR, `tts_${Date.now()}.wav`);
|
|
12553
12890
|
const script = `
|
|
12554
12891
|
import sys, json, base64, threading
|
|
12555
12892
|
import dashscope
|
|
@@ -12634,7 +12971,7 @@ print('EOS')
|
|
|
12634
12971
|
header.writeUInt16LE(16, 34);
|
|
12635
12972
|
header.write("data", 36);
|
|
12636
12973
|
header.writeUInt32LE(pcm.length, 40);
|
|
12637
|
-
|
|
12974
|
+
fs20.writeFileSync(output, Buffer.concat([header, pcm]));
|
|
12638
12975
|
return output;
|
|
12639
12976
|
}
|
|
12640
12977
|
async function ttsQwen3Local(text, cfg, onChunk) {
|
|
@@ -12686,14 +13023,14 @@ async function ttsQwen3Opus(text, cfg) {
|
|
|
12686
13023
|
const ogg = Buffer.from(await res.arrayBuffer());
|
|
12687
13024
|
if (ogg.length < 20) throw new Error("qwen3-3060 opus: empty output");
|
|
12688
13025
|
const durationMs = parseInt(res.headers.get("x-duration-ms") || "0", 10);
|
|
12689
|
-
|
|
12690
|
-
const oggPath =
|
|
12691
|
-
|
|
13026
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13027
|
+
const oggPath = path21.join(VOICE_DIR, `tts_${Date.now()}.ogg`);
|
|
13028
|
+
fs20.writeFileSync(oggPath, ogg);
|
|
12692
13029
|
return { oggPath, durationMs };
|
|
12693
13030
|
}
|
|
12694
13031
|
async function ttsGptsovits(text) {
|
|
12695
|
-
|
|
12696
|
-
const output =
|
|
13032
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13033
|
+
const output = path21.join(VOICE_DIR, `tts_${Date.now()}.wav`);
|
|
12697
13034
|
const params = new URLSearchParams({
|
|
12698
13035
|
text,
|
|
12699
13036
|
text_language: "zh",
|
|
@@ -12704,12 +13041,12 @@ async function ttsGptsovits(text) {
|
|
|
12704
13041
|
const res = await fetch(`${GPTSOVITS_API}/?${params}`);
|
|
12705
13042
|
if (!res.ok) throw new Error(`GPT-SoVITS API ${res.status}`);
|
|
12706
13043
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
12707
|
-
|
|
13044
|
+
fs20.writeFileSync(output, buf);
|
|
12708
13045
|
return output;
|
|
12709
13046
|
}
|
|
12710
13047
|
async function ttsEdge(text) {
|
|
12711
|
-
|
|
12712
|
-
const output =
|
|
13048
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13049
|
+
const output = path21.join(VOICE_DIR, `tts_${Date.now()}.mp3`);
|
|
12713
13050
|
const script = `
|
|
12714
13051
|
import asyncio, edge_tts, sys
|
|
12715
13052
|
async def main():
|
|
@@ -12736,11 +13073,11 @@ async function toWav24kWithDuration(audioPath) {
|
|
|
12736
13073
|
"pcm_s16le",
|
|
12737
13074
|
wavPath
|
|
12738
13075
|
], { timeout: 3e4 });
|
|
12739
|
-
if (!
|
|
13076
|
+
if (!fs20.existsSync(wavPath) || fs20.statSync(wavPath).size < 44) {
|
|
12740
13077
|
throw new Error("toWav24k produced empty output");
|
|
12741
13078
|
}
|
|
12742
13079
|
try {
|
|
12743
|
-
|
|
13080
|
+
fs20.unlinkSync(audioPath);
|
|
12744
13081
|
} catch {
|
|
12745
13082
|
}
|
|
12746
13083
|
}
|
|
@@ -12771,7 +13108,7 @@ async function compressWav(wavPath) {
|
|
|
12771
13108
|
"+faststart",
|
|
12772
13109
|
m4aPath
|
|
12773
13110
|
], { timeout: 3e4 });
|
|
12774
|
-
|
|
13111
|
+
fs20.unlinkSync(wavPath);
|
|
12775
13112
|
return m4aPath;
|
|
12776
13113
|
} catch {
|
|
12777
13114
|
return wavPath;
|
|
@@ -12798,10 +13135,10 @@ async function wavToOggOpus(wavPath) {
|
|
|
12798
13135
|
oggPath
|
|
12799
13136
|
], { timeout: 3e4 });
|
|
12800
13137
|
}
|
|
12801
|
-
if (!
|
|
13138
|
+
if (!fs20.existsSync(oggPath) || fs20.statSync(oggPath).size < 20) {
|
|
12802
13139
|
throw new Error("ogg/opus encode produced empty output");
|
|
12803
13140
|
}
|
|
12804
|
-
|
|
13141
|
+
fs20.unlinkSync(wavPath);
|
|
12805
13142
|
return oggPath;
|
|
12806
13143
|
}
|
|
12807
13144
|
async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
@@ -12818,8 +13155,8 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12818
13155
|
const pcmChunks = [];
|
|
12819
13156
|
await ttsQwen3Local(text, { url: vc.url, voice: vc.voice, lang: vc.lang }, (pcm2) => pcmChunks.push(pcm2));
|
|
12820
13157
|
const pcm = Buffer.concat(pcmChunks);
|
|
12821
|
-
|
|
12822
|
-
const wavPath =
|
|
13158
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13159
|
+
const wavPath = path21.join(VOICE_DIR, `tts_mc_${Date.now()}.wav`);
|
|
12823
13160
|
const header = Buffer.alloc(44);
|
|
12824
13161
|
header.write("RIFF", 0);
|
|
12825
13162
|
header.writeUInt32LE(36 + pcm.length, 4);
|
|
@@ -12834,7 +13171,7 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12834
13171
|
header.writeUInt16LE(16, 34);
|
|
12835
13172
|
header.write("data", 36);
|
|
12836
13173
|
header.writeUInt32LE(pcm.length, 40);
|
|
12837
|
-
|
|
13174
|
+
fs20.writeFileSync(wavPath, Buffer.concat([header, pcm]));
|
|
12838
13175
|
audioPath = wavPath;
|
|
12839
13176
|
}
|
|
12840
13177
|
} else if (actualEngine === "cosyvoice" && vc?.apiKey) {
|
|
@@ -12848,7 +13185,7 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12848
13185
|
} catch (e) {
|
|
12849
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 };
|
|
12850
13187
|
}
|
|
12851
|
-
if (!audioPath || !
|
|
13188
|
+
if (!audioPath || !fs20.existsSync(audioPath)) {
|
|
12852
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 };
|
|
12853
13190
|
}
|
|
12854
13191
|
if (audioPath.endsWith(".wav")) {
|
|
@@ -12858,21 +13195,21 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12858
13195
|
console.warn(`[my-voice:multaca] opus encode failed (${e.message}), attaching wav`);
|
|
12859
13196
|
}
|
|
12860
13197
|
}
|
|
12861
|
-
const ext =
|
|
12862
|
-
const sizeKB =
|
|
13198
|
+
const ext = path21.extname(audioPath).toLowerCase();
|
|
13199
|
+
const sizeKB = fs20.statSync(audioPath).size / 1024;
|
|
12863
13200
|
const voiceFile = `voice_${Date.now()}${ext}`;
|
|
12864
|
-
const cwdCopy =
|
|
13201
|
+
const cwdCopy = path21.join(process.cwd(), voiceFile);
|
|
12865
13202
|
try {
|
|
12866
|
-
|
|
13203
|
+
fs20.copyFileSync(audioPath, cwdCopy);
|
|
12867
13204
|
} catch (e) {
|
|
12868
13205
|
try {
|
|
12869
|
-
|
|
13206
|
+
fs20.unlinkSync(audioPath);
|
|
12870
13207
|
} catch {
|
|
12871
13208
|
}
|
|
12872
13209
|
return { content: `\u8BED\u97F3\u6302\u8F7D\u5931\u8D25\uFF08\u62F7\u8D1D\u5230\u5DE5\u4F5C\u76EE\u5F55\uFF09\uFF1A${e.message}`, isError: true };
|
|
12873
13210
|
}
|
|
12874
13211
|
try {
|
|
12875
|
-
|
|
13212
|
+
fs20.unlinkSync(audioPath);
|
|
12876
13213
|
} catch {
|
|
12877
13214
|
}
|
|
12878
13215
|
const content = opts.caption || `\u{1F399}\uFE0F \u8BED\u97F3\u6D88\u606F\uFF08${text.length} \u5B57\uFF09`;
|
|
@@ -12901,13 +13238,13 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
|
|
|
12901
13238
|
}
|
|
12902
13239
|
if (!ok) throw new Error(`unexpected CLI output: ${String(stdout).slice(0, 200)}`);
|
|
12903
13240
|
try {
|
|
12904
|
-
|
|
13241
|
+
fs20.unlinkSync(cwdCopy);
|
|
12905
13242
|
} catch {
|
|
12906
13243
|
}
|
|
12907
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)` };
|
|
12908
13245
|
} catch (e) {
|
|
12909
13246
|
try {
|
|
12910
|
-
|
|
13247
|
+
fs20.unlinkSync(cwdCopy);
|
|
12911
13248
|
} catch {
|
|
12912
13249
|
}
|
|
12913
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 };
|
|
@@ -12922,7 +13259,7 @@ var init_my_voice = __esm({
|
|
|
12922
13259
|
init_opus_encoder();
|
|
12923
13260
|
init_voice_chat_tts_daemon();
|
|
12924
13261
|
execFileAsync = promisify(execFile2);
|
|
12925
|
-
VOICE_DIR =
|
|
13262
|
+
VOICE_DIR = path21.join(os3.tmpdir(), "engine-voice");
|
|
12926
13263
|
_pyCache = null;
|
|
12927
13264
|
GPTSOVITS_API = "http://127.0.0.1:9880";
|
|
12928
13265
|
GPTSOVITS_REF_WAV = "/home/chong/voice/ref/shanshan_ref_v2.wav";
|
|
@@ -13021,8 +13358,8 @@ var init_my_voice = __esm({
|
|
|
13021
13358
|
const pcmChunks = [];
|
|
13022
13359
|
await ttsQwen3Local(text, { url: vc.url, voice: vc.voice, lang: vc.lang }, (pcm2) => pcmChunks.push(pcm2));
|
|
13023
13360
|
const pcm = Buffer.concat(pcmChunks);
|
|
13024
|
-
|
|
13025
|
-
const wavPath =
|
|
13361
|
+
fs20.mkdirSync(VOICE_DIR, { recursive: true });
|
|
13362
|
+
const wavPath = path21.join(VOICE_DIR, `tts_${Date.now()}.wav`);
|
|
13026
13363
|
const header = Buffer.alloc(44);
|
|
13027
13364
|
header.write("RIFF", 0);
|
|
13028
13365
|
header.writeUInt32LE(36 + pcm.length, 4);
|
|
@@ -13037,7 +13374,7 @@ var init_my_voice = __esm({
|
|
|
13037
13374
|
header.writeUInt16LE(16, 34);
|
|
13038
13375
|
header.write("data", 36);
|
|
13039
13376
|
header.writeUInt32LE(pcm.length, 40);
|
|
13040
|
-
|
|
13377
|
+
fs20.writeFileSync(wavPath, Buffer.concat([header, pcm]));
|
|
13041
13378
|
audioPath = wavPath;
|
|
13042
13379
|
}
|
|
13043
13380
|
} catch (e) {
|
|
@@ -13068,10 +13405,10 @@ var init_my_voice = __esm({
|
|
|
13068
13405
|
audioPath = await compressWav(audioPath);
|
|
13069
13406
|
}
|
|
13070
13407
|
}
|
|
13071
|
-
const ext =
|
|
13408
|
+
const ext = path21.extname(audioPath).toLowerCase();
|
|
13072
13409
|
const mimeMap = { ".mp3": "audio/mpeg", ".wav": "audio/wav", ".m4a": "audio/mp4", ".ogg": "audio/ogg", ".silk": "audio/silk" };
|
|
13073
13410
|
const mimeType = mimeMap[ext] || "audio/mpeg";
|
|
13074
|
-
const sizeKB =
|
|
13411
|
+
const sizeKB = fs20.statSync(audioPath).size / 1024;
|
|
13075
13412
|
try {
|
|
13076
13413
|
await mgr.sendFile(resolvedChannel, target, caption, {
|
|
13077
13414
|
path: audioPath,
|
|
@@ -13080,7 +13417,7 @@ var init_my_voice = __esm({
|
|
|
13080
13417
|
...voiceDurationSec !== void 0 ? { voiceDurationSec } : {}
|
|
13081
13418
|
});
|
|
13082
13419
|
try {
|
|
13083
|
-
|
|
13420
|
+
fs20.unlinkSync(audioPath);
|
|
13084
13421
|
} catch {
|
|
13085
13422
|
}
|
|
13086
13423
|
return { content: `Voice sent! (${actualEngine}, ${sizeKB.toFixed(0)}KB, ${resolvedChannel})` };
|
|
@@ -13097,8 +13434,8 @@ var init_my_voice = __esm({
|
|
|
13097
13434
|
});
|
|
13098
13435
|
|
|
13099
13436
|
// src/tools/my-selfie.ts
|
|
13100
|
-
import * as
|
|
13101
|
-
import * as
|
|
13437
|
+
import * as fs21 from "node:fs";
|
|
13438
|
+
import * as path22 from "node:path";
|
|
13102
13439
|
function getProxyDispatcher2() {
|
|
13103
13440
|
const cfg = liveConfig.all();
|
|
13104
13441
|
const proxy = cfg.providers?.xai?.proxy;
|
|
@@ -13414,12 +13751,12 @@ var init_my_selfie = __esm({
|
|
|
13414
13751
|
const REFERENCES = getReferences(ctx);
|
|
13415
13752
|
const refName = args.reference || "default";
|
|
13416
13753
|
const refEntry = REFERENCES.find((r) => r.name === refName) || REFERENCES[0];
|
|
13417
|
-
const refPath =
|
|
13418
|
-
if (provider !== "autodl" && !
|
|
13754
|
+
const refPath = path22.join(ctx.workspace, refEntry.p);
|
|
13755
|
+
if (provider !== "autodl" && !fs21.existsSync(refPath)) {
|
|
13419
13756
|
return { content: `Error: reference image not found at ${refPath}`, isError: true };
|
|
13420
13757
|
}
|
|
13421
13758
|
const resolution = args.resolution || DEFAULT_RESOLUTION;
|
|
13422
|
-
const refB64 =
|
|
13759
|
+
const refB64 = fs21.existsSync(refPath) ? fs21.readFileSync(refPath).toString("base64") : "";
|
|
13423
13760
|
let imageBuffer;
|
|
13424
13761
|
try {
|
|
13425
13762
|
if (provider === "autodl") {
|
|
@@ -13434,11 +13771,11 @@ var init_my_selfie = __esm({
|
|
|
13434
13771
|
} catch (err) {
|
|
13435
13772
|
return { content: `Selfie generation failed: ${err.message}`, isError: true };
|
|
13436
13773
|
}
|
|
13437
|
-
const imagesDir =
|
|
13438
|
-
if (!
|
|
13774
|
+
const imagesDir = path22.join(ctx.workspace, "images");
|
|
13775
|
+
if (!fs21.existsSync(imagesDir)) fs21.mkdirSync(imagesDir, { recursive: true });
|
|
13439
13776
|
const filename = `selfie_${Date.now()}.jpg`;
|
|
13440
|
-
const outputPath =
|
|
13441
|
-
|
|
13777
|
+
const outputPath = path22.join(imagesDir, filename);
|
|
13778
|
+
fs21.writeFileSync(outputPath, imageBuffer);
|
|
13442
13779
|
const mgr = ctx.channelManager;
|
|
13443
13780
|
if (mgr) {
|
|
13444
13781
|
const resolvedChannel = ctx.channel || "feishu";
|
|
@@ -13449,11 +13786,11 @@ var init_my_selfie = __esm({
|
|
|
13449
13786
|
mimeType: "image/jpeg"
|
|
13450
13787
|
});
|
|
13451
13788
|
} catch (err) {
|
|
13452
|
-
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 };
|
|
13453
13790
|
}
|
|
13454
13791
|
return { content: `Selfie sent! Mode: ${mode}, Provider: ${provider}, Ref: ${refEntry.name}` };
|
|
13455
13792
|
}
|
|
13456
|
-
return { content: `Selfie generated! Mode: ${mode}, Ref: ${refEntry.name}. Image: ${
|
|
13793
|
+
return { content: `Selfie generated! Mode: ${mode}, Ref: ${refEntry.name}. Image: ${path22.resolve(outputPath)}` };
|
|
13457
13794
|
},
|
|
13458
13795
|
isConcurrencySafe: () => false,
|
|
13459
13796
|
interruptBehavior: () => "block",
|
|
@@ -13548,88 +13885,6 @@ var init_body_move = __esm({
|
|
|
13548
13885
|
}
|
|
13549
13886
|
});
|
|
13550
13887
|
|
|
13551
|
-
// src/calendar/db.ts
|
|
13552
|
-
import * as path21 from "node:path";
|
|
13553
|
-
import * as fs20 from "node:fs";
|
|
13554
|
-
import { createRequire as createRequire2 } from "node:module";
|
|
13555
|
-
function getSqlite() {
|
|
13556
|
-
if (!_sqlite) _sqlite = createRequire2(import.meta.url)("node:sqlite");
|
|
13557
|
-
return _sqlite;
|
|
13558
|
-
}
|
|
13559
|
-
function openDb(workspace) {
|
|
13560
|
-
const dir = path21.join(workspace, ".calendar");
|
|
13561
|
-
fs20.mkdirSync(dir, { recursive: true });
|
|
13562
|
-
const dbPath = path21.join(dir, "calendar.db");
|
|
13563
|
-
const db = new DatabaseSync(dbPath);
|
|
13564
|
-
db.exec("PRAGMA journal_mode=WAL");
|
|
13565
|
-
db.exec(`CREATE TABLE IF NOT EXISTS events (
|
|
13566
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
13567
|
-
type TEXT NOT NULL,
|
|
13568
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
13569
|
-
event TEXT NOT NULL,
|
|
13570
|
-
day TEXT,
|
|
13571
|
-
time TEXT,
|
|
13572
|
-
date_str TEXT,
|
|
13573
|
-
created_at TEXT NOT NULL,
|
|
13574
|
-
done_at TEXT,
|
|
13575
|
-
archived_at TEXT
|
|
13576
|
-
)`);
|
|
13577
|
-
migrate(db);
|
|
13578
|
-
return db;
|
|
13579
|
-
}
|
|
13580
|
-
function migrate(db) {
|
|
13581
|
-
const cols = new Set(
|
|
13582
|
-
db.prepare("PRAGMA table_info(events)").all().map((r) => r.name)
|
|
13583
|
-
);
|
|
13584
|
-
if (!cols.has("remind_before_min")) {
|
|
13585
|
-
db.exec("ALTER TABLE events ADD COLUMN remind_before_min INTEGER DEFAULT 60");
|
|
13586
|
-
}
|
|
13587
|
-
if (!cols.has("remind_at")) {
|
|
13588
|
-
db.exec("ALTER TABLE events ADD COLUMN remind_at TEXT");
|
|
13589
|
-
}
|
|
13590
|
-
if (!cols.has("reminded")) {
|
|
13591
|
-
db.exec("ALTER TABLE events ADD COLUMN reminded INTEGER DEFAULT 0");
|
|
13592
|
-
}
|
|
13593
|
-
if (!cols.has("time_exact")) {
|
|
13594
|
-
db.exec("ALTER TABLE events ADD COLUMN time_exact TEXT");
|
|
13595
|
-
}
|
|
13596
|
-
if (!cols.has("start_time")) {
|
|
13597
|
-
db.exec("ALTER TABLE events ADD COLUMN start_time TEXT");
|
|
13598
|
-
}
|
|
13599
|
-
if (!cols.has("duration_min")) {
|
|
13600
|
-
db.exec("ALTER TABLE events ADD COLUMN duration_min INTEGER");
|
|
13601
|
-
}
|
|
13602
|
-
if (!cols.has("created_channel")) {
|
|
13603
|
-
db.exec("ALTER TABLE events ADD COLUMN created_channel TEXT");
|
|
13604
|
-
}
|
|
13605
|
-
if (!cols.has("created_channel_target")) {
|
|
13606
|
-
db.exec("ALTER TABLE events ADD COLUMN created_channel_target TEXT");
|
|
13607
|
-
}
|
|
13608
|
-
if (!cols.has("repeat_type")) {
|
|
13609
|
-
db.exec("ALTER TABLE events ADD COLUMN repeat_type TEXT DEFAULT 'once'");
|
|
13610
|
-
}
|
|
13611
|
-
if (!cols.has("doc_path")) {
|
|
13612
|
-
db.exec("ALTER TABLE events ADD COLUMN doc_path TEXT");
|
|
13613
|
-
}
|
|
13614
|
-
}
|
|
13615
|
-
var _sqlite, DatabaseSync, TZ_OFFSET_MS;
|
|
13616
|
-
var init_db = __esm({
|
|
13617
|
-
"src/calendar/db.ts"() {
|
|
13618
|
-
"use strict";
|
|
13619
|
-
_sqlite = null;
|
|
13620
|
-
DatabaseSync = new Proxy(function() {
|
|
13621
|
-
}, {
|
|
13622
|
-
construct(_t, args) {
|
|
13623
|
-
return new (getSqlite()).DatabaseSync(...args);
|
|
13624
|
-
},
|
|
13625
|
-
get(_t, prop) {
|
|
13626
|
-
return getSqlite().DatabaseSync[prop];
|
|
13627
|
-
}
|
|
13628
|
-
});
|
|
13629
|
-
TZ_OFFSET_MS = 8 * 60 * 60 * 1e3;
|
|
13630
|
-
}
|
|
13631
|
-
});
|
|
13632
|
-
|
|
13633
13888
|
// src/calendar/helpers.ts
|
|
13634
13889
|
function nowIso() {
|
|
13635
13890
|
return new Date(Date.now() + TZ_OFFSET_MS2 - (/* @__PURE__ */ new Date()).getTimezoneOffset() * 6e4).toISOString().replace("Z", "+08:00");
|
|
@@ -13855,14 +14110,14 @@ function fmtEnd(start, durationMin) {
|
|
|
13855
14110
|
const total = hh * 60 + mm + durationMin;
|
|
13856
14111
|
return `${Math.floor(total / 60)}:${String(total % 60).padStart(2, "0")}`;
|
|
13857
14112
|
}
|
|
13858
|
-
function addWeekly(
|
|
14113
|
+
function addWeekly(db2, args) {
|
|
13859
14114
|
const { day, event } = args;
|
|
13860
14115
|
if (!WEEKDAYS2.includes(day)) return `\u9519\u8BEF: \u661F\u671F\u5FC5\u987B\u662F ${WEEKDAYS2.join("/")}`;
|
|
13861
14116
|
if (!args.time) return `\u9519\u8BEF: \u5468\u671F\u65E5\u7A0B\u5FC5\u987B\u586B start_time\uFF08\u5982 time='14:00'\uFF09`;
|
|
13862
14117
|
if (!args.duration) return `\u9519\u8BEF: \u5468\u671F\u65E5\u7A0B\u5FC5\u987B\u586B duration\uFF08\u5982 duration='1h'\uFF09`;
|
|
13863
14118
|
const durationMin = parseDuration(args.duration);
|
|
13864
14119
|
if (!durationMin) return `\u9519\u8BEF: duration \u683C\u5F0F\u4E0D\u5BF9\uFF08\u5982 '30m' / '1h'\uFF09`;
|
|
13865
|
-
const conflictRows =
|
|
14120
|
+
const conflictRows = db2.prepare(
|
|
13866
14121
|
"SELECT * FROM events WHERE status='pending' AND type='weekly' AND day=?"
|
|
13867
14122
|
).all(day);
|
|
13868
14123
|
const conflict = checkScheduleConflict(conflictRows, args.time, durationMin);
|
|
@@ -13877,16 +14132,16 @@ function addWeekly(db, args) {
|
|
|
13877
14132
|
else remindMin = parseInt(v) || 60;
|
|
13878
14133
|
}
|
|
13879
14134
|
const remindAt = computeWeeklyRemindAt(day, args.time, remindMin);
|
|
13880
|
-
const r =
|
|
14135
|
+
const r = db2.prepare(
|
|
13881
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)
|
|
13882
14137
|
VALUES ('weekly','pending',?,?,?,?,?,?,?,?,?,?,?)`
|
|
13883
14138
|
).run(event, day, args.time, args.time, durationMin, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
|
|
13884
14139
|
return `#${r.lastInsertRowid} \u5DF2\u6DFB\u52A0: [\u6BCF\u5468] ${day} ${args.time} (${durationMin}min) ${event} (\u63D0\u524D${remindMin}min\u63D0\u9192)`;
|
|
13885
14140
|
}
|
|
13886
|
-
function addDaily(
|
|
14141
|
+
function addDaily(db2, args) {
|
|
13887
14142
|
const { time, event, repeatType } = args;
|
|
13888
14143
|
if (!time) return `\u9519\u8BEF: \u6BCF\u65E5\u4EFB\u52A1\u5FC5\u987B\u586B time\uFF08\u5982 time='23:00'\uFF09`;
|
|
13889
|
-
const dailyRows =
|
|
14144
|
+
const dailyRows = db2.prepare(
|
|
13890
14145
|
"SELECT * FROM events WHERE status='pending' AND type='daily'"
|
|
13891
14146
|
).all();
|
|
13892
14147
|
const [hh, mm] = time.split(":").map(Number);
|
|
@@ -13908,21 +14163,21 @@ function addDaily(db, args) {
|
|
|
13908
14163
|
}
|
|
13909
14164
|
const remindAt = repeatType === "daily" ? computeDailyRemindAt(time, remindMin) : computeWeekdaysRemindAt(time, remindMin);
|
|
13910
14165
|
if (!remindAt) return `\u9519\u8BEF: \u65E0\u6CD5\u8BA1\u7B97 remind_at`;
|
|
13911
|
-
const r =
|
|
14166
|
+
const r = db2.prepare(
|
|
13912
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)
|
|
13913
14168
|
VALUES ('daily','pending',?,?,?,?,?,?,?,?,?,?)`
|
|
13914
14169
|
).run(event, time, time, repeatType, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
|
|
13915
14170
|
const label = repeatType === "daily" ? "\u6BCF\u5929" : "\u5DE5\u4F5C\u65E5";
|
|
13916
14171
|
return `#${r.lastInsertRowid} \u5DF2\u6DFB\u52A0: [${label}] ${time} ${event} (\u63D0\u524D${remindMin}min\u63D0\u9192)`;
|
|
13917
14172
|
}
|
|
13918
|
-
function addDate(
|
|
14173
|
+
function addDate(db2, args) {
|
|
13919
14174
|
const { dateStr, event } = args;
|
|
13920
14175
|
if (!args.time) return `\u9519\u8BEF: \u4E00\u6B21\u6027\u65E5\u7A0B\u5FC5\u987B\u586B start_time\uFF08\u5982 time='14:00'\uFF09`;
|
|
13921
14176
|
if (!args.duration) return `\u9519\u8BEF: \u4E00\u6B21\u6027\u65E5\u7A0B\u5FC5\u987B\u586B duration\uFF08\u5982 duration='1h'\uFF09`;
|
|
13922
14177
|
const durationMin = parseDuration(args.duration);
|
|
13923
14178
|
if (!durationMin) return `\u9519\u8BEF: duration \u683C\u5F0F\u4E0D\u5BF9\uFF08\u5982 '30m' / '1h'\uFF09`;
|
|
13924
14179
|
const todayWeekday = getTodayWeekday();
|
|
13925
|
-
const dateRows =
|
|
14180
|
+
const dateRows = db2.prepare(
|
|
13926
14181
|
"SELECT * FROM events WHERE status='pending' AND type='date' AND date_str=?"
|
|
13927
14182
|
).all(dateStr);
|
|
13928
14183
|
const parsed = parseDateRange(dateStr);
|
|
@@ -13932,7 +14187,7 @@ function addDate(db, args) {
|
|
|
13932
14187
|
const year = now.getUTCFullYear();
|
|
13933
14188
|
const d = new Date(Date.UTC(year, parsed.month - 1, parsed.dStart));
|
|
13934
14189
|
const weekday = WEEKDAYS2[d.getUTCDay() === 0 ? 6 : d.getUTCDay() - 1];
|
|
13935
|
-
weeklyRows =
|
|
14190
|
+
weeklyRows = db2.prepare(
|
|
13936
14191
|
"SELECT * FROM events WHERE status='pending' AND type='weekly' AND day=?"
|
|
13937
14192
|
).all(weekday);
|
|
13938
14193
|
}
|
|
@@ -13949,13 +14204,13 @@ function addDate(db, args) {
|
|
|
13949
14204
|
else remindMin = parseInt(v) || 60;
|
|
13950
14205
|
}
|
|
13951
14206
|
const remindAt = computeRemindAt(dateStr, args.time, remindMin);
|
|
13952
|
-
const r =
|
|
14207
|
+
const r = db2.prepare(
|
|
13953
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)
|
|
13954
14209
|
VALUES ('date','pending',?,?,?,?,?,?,?,?,?,?,?)`
|
|
13955
14210
|
).run(event, dateStr, args.time, args.time, durationMin, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
|
|
13956
14211
|
return `#${r.lastInsertRowid} \u5DF2\u6DFB\u52A0: [${dateStr} ${args.time} (${durationMin}min)] ${event} (\u63D0\u524D${remindMin}min\u63D0\u9192)`;
|
|
13957
14212
|
}
|
|
13958
|
-
function addBatch(
|
|
14213
|
+
function addBatch(db2, args) {
|
|
13959
14214
|
if (!args.time) return `\u9519\u8BEF: \u6279\u91CF\u6DFB\u52A0\u5FC5\u987B\u586B time\uFF08\u5982 time='14:00'\uFF09`;
|
|
13960
14215
|
if (!args.duration) return `\u9519\u8BEF: \u6279\u91CF\u6DFB\u52A0\u5FC5\u987B\u586B duration\uFF08\u5982 duration='1h'\uFF09`;
|
|
13961
14216
|
const durationMin = parseDuration(args.duration);
|
|
@@ -13972,7 +14227,7 @@ function addBatch(db, args) {
|
|
|
13972
14227
|
const ok = [];
|
|
13973
14228
|
const skipped = [];
|
|
13974
14229
|
for (const dateStr of dates) {
|
|
13975
|
-
const dateRows =
|
|
14230
|
+
const dateRows = db2.prepare(
|
|
13976
14231
|
"SELECT * FROM events WHERE status='pending' AND type='date' AND date_str=?"
|
|
13977
14232
|
).all(dateStr);
|
|
13978
14233
|
const parsed = parseDateRange(dateStr);
|
|
@@ -13982,7 +14237,7 @@ function addBatch(db, args) {
|
|
|
13982
14237
|
const year = now.getUTCFullYear();
|
|
13983
14238
|
const d = new Date(Date.UTC(year, parsed.month - 1, parsed.dStart));
|
|
13984
14239
|
const weekday = WEEKDAYS2[d.getUTCDay() === 0 ? 6 : d.getUTCDay() - 1];
|
|
13985
|
-
weeklyRows =
|
|
14240
|
+
weeklyRows = db2.prepare(
|
|
13986
14241
|
"SELECT * FROM events WHERE status='pending' AND type='weekly' AND day=?"
|
|
13987
14242
|
).all(weekday);
|
|
13988
14243
|
}
|
|
@@ -13993,7 +14248,7 @@ function addBatch(db, args) {
|
|
|
13993
14248
|
continue;
|
|
13994
14249
|
}
|
|
13995
14250
|
const remindAt = computeRemindAt(dateStr, args.time, remindMin);
|
|
13996
|
-
const r =
|
|
14251
|
+
const r = db2.prepare(
|
|
13997
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)
|
|
13998
14253
|
VALUES ('date','pending',?,?,?,?,?,?,?,?,?,?,?)`
|
|
13999
14254
|
).run(args.event, dateStr, args.time, args.time, durationMin, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
|
|
@@ -14010,7 +14265,7 @@ ${skipped.map((s) => ` ${s}`).join("\n")}`;
|
|
|
14010
14265
|
}
|
|
14011
14266
|
return result2;
|
|
14012
14267
|
}
|
|
14013
|
-
function addTask(
|
|
14268
|
+
function addTask(db2, args) {
|
|
14014
14269
|
const { dateStr, timeExact, event, docPath } = args;
|
|
14015
14270
|
if (!docPath || !docPath.trim()) {
|
|
14016
14271
|
return `\u274C \u521B\u5EFA\u5931\u8D25\uFF1Aadd-task \u5FC5\u987B\u4F20 doc_path\u3002
|
|
@@ -14041,12 +14296,12 @@ function addTask(db, args) {
|
|
|
14041
14296
|
else if (v.endsWith("h")) remindMin = parseInt(v.slice(0, -1)) * 60;
|
|
14042
14297
|
else remindMin = parseInt(v) || 60;
|
|
14043
14298
|
}
|
|
14044
|
-
const taskRows =
|
|
14299
|
+
const taskRows = db2.prepare(
|
|
14045
14300
|
"SELECT * FROM events WHERE status='pending' AND type='task' AND date_str=?"
|
|
14046
14301
|
).all(dateStr);
|
|
14047
14302
|
const prox = checkTaskProximity(taskRows, timeExact);
|
|
14048
14303
|
const remindAt = computeRemindAt(dateStr, timeExact, remindMin);
|
|
14049
|
-
const r =
|
|
14304
|
+
const r = db2.prepare(
|
|
14050
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)
|
|
14051
14306
|
VALUES ('task','pending',?,?,?,?,?,?,?,?,?,?)`
|
|
14052
14307
|
).run(event, dateStr, timeExact, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null, docPath);
|
|
@@ -14058,9 +14313,9 @@ function addTask(db, args) {
|
|
|
14058
14313
|
}
|
|
14059
14314
|
return msg2;
|
|
14060
14315
|
}
|
|
14061
|
-
function reschedule(
|
|
14316
|
+
function reschedule(db2, args) {
|
|
14062
14317
|
const { id, dateStr, timeExact } = args;
|
|
14063
|
-
const row =
|
|
14318
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=?").get(id);
|
|
14064
14319
|
if (!row) return `\u672A\u627E\u5230\u4E8B\u4EF6 #${id}`;
|
|
14065
14320
|
if (row.type !== "task") return `#${id} \u4E0D\u662F task \u7C7B\u578B\uFF08${row.type}\uFF09\uFF0Creschedule \u4EC5\u652F\u6301 task`;
|
|
14066
14321
|
let remindMin = row.remind_before_min || 60;
|
|
@@ -14071,12 +14326,12 @@ function reschedule(db, args) {
|
|
|
14071
14326
|
else remindMin = parseInt(v) || remindMin;
|
|
14072
14327
|
}
|
|
14073
14328
|
const remindAt = computeRemindAt(dateStr, timeExact, remindMin);
|
|
14074
|
-
|
|
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);
|
|
14075
14330
|
return `#${id} \u5DF2\u6539\u671F: [${dateStr} ${timeExact}] ${row.event} (\u63D0\u524D${remindMin}min\u63D0\u9192)`;
|
|
14076
14331
|
}
|
|
14077
|
-
function list(
|
|
14332
|
+
function list(db2, opts = {}) {
|
|
14078
14333
|
if (opts.all) {
|
|
14079
|
-
const rows =
|
|
14334
|
+
const rows = db2.prepare("SELECT * FROM events WHERE status NOT IN ('archived', 'deleted') ORDER BY type, id").all();
|
|
14080
14335
|
const out2 = ["## \u6BCF\u5468\u56FA\u5B9A"];
|
|
14081
14336
|
for (const r of rows) if (r.type === "weekly") out2.push(fmtRow(r));
|
|
14082
14337
|
out2.push("\n## \u6BCF\u65E5\u56FA\u5B9A");
|
|
@@ -14090,17 +14345,17 @@ function list(db, opts = {}) {
|
|
|
14090
14345
|
const out = [`\u5F53\u524D\u65F6\u95F4: ${fmtNow()}`];
|
|
14091
14346
|
const todayWeekday = getTodayWeekday();
|
|
14092
14347
|
const events = [];
|
|
14093
|
-
for (const r of
|
|
14348
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='weekly' AND status='pending' AND day=?").all(todayWeekday)) {
|
|
14094
14349
|
events.push(` #${r.id} ${r.time || ""} ${r.event}`);
|
|
14095
14350
|
}
|
|
14096
|
-
for (const r of
|
|
14351
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='daily' AND status='pending'").all()) {
|
|
14097
14352
|
if (r.repeat_type === "weekdays") {
|
|
14098
14353
|
const idx = new Date(Date.now() + 8 * 60 * 60 * 1e3).getUTCDay();
|
|
14099
14354
|
if (idx === 0 || idx === 6) continue;
|
|
14100
14355
|
}
|
|
14101
14356
|
events.push(` #${r.id} ${r.time || ""} ${r.event}`);
|
|
14102
14357
|
}
|
|
14103
|
-
for (const r of
|
|
14358
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='date' AND status='pending'").all()) {
|
|
14104
14359
|
const p = parseDateRange(r.date_str);
|
|
14105
14360
|
if (p && isToday(p.month, p.dStart, p.dEnd)) {
|
|
14106
14361
|
events.push(` #${r.id} ${r.event}`);
|
|
@@ -14114,14 +14369,14 @@ function list(db, opts = {}) {
|
|
|
14114
14369
|
}
|
|
14115
14370
|
return out.join("\n");
|
|
14116
14371
|
}
|
|
14117
|
-
function pending(
|
|
14372
|
+
function pending(db2) {
|
|
14118
14373
|
const out = [`\u5F53\u524D\u65F6\u95F4: ${fmtNow()}`];
|
|
14119
14374
|
const todayWeekday = getTodayWeekday();
|
|
14120
14375
|
const events = [];
|
|
14121
|
-
for (const r of
|
|
14376
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='weekly' AND status='pending' AND day=?").all(todayWeekday)) {
|
|
14122
14377
|
events.push(` #${r.id} [\u6BCF\u5468] ${r.time || ""} ${r.event}`);
|
|
14123
14378
|
}
|
|
14124
|
-
for (const r of
|
|
14379
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='daily' AND status='pending'").all()) {
|
|
14125
14380
|
if (r.repeat_type === "weekdays") {
|
|
14126
14381
|
const idx = new Date(Date.now() + 8 * 60 * 60 * 1e3).getUTCDay();
|
|
14127
14382
|
if (idx === 0 || idx === 6) continue;
|
|
@@ -14129,7 +14384,7 @@ function pending(db) {
|
|
|
14129
14384
|
const label = r.repeat_type === "weekdays" ? "[\u5DE5\u4F5C\u65E5]" : "[\u6BCF\u5929]";
|
|
14130
14385
|
events.push(` #${r.id} ${label} ${r.time || ""} ${r.event}`);
|
|
14131
14386
|
}
|
|
14132
|
-
for (const r of
|
|
14387
|
+
for (const r of db2.prepare("SELECT * FROM events WHERE type='date' AND status='pending'").all()) {
|
|
14133
14388
|
const p = parseDateRange(r.date_str);
|
|
14134
14389
|
if (!p) continue;
|
|
14135
14390
|
if (isToday(p.month, p.dStart, p.dEnd)) {
|
|
@@ -14148,31 +14403,31 @@ function pending(db) {
|
|
|
14148
14403
|
}
|
|
14149
14404
|
return out.join("\n");
|
|
14150
14405
|
}
|
|
14151
|
-
function done(
|
|
14152
|
-
const row =
|
|
14406
|
+
function done(db2, id) {
|
|
14407
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=? AND status=?").get(id, "pending");
|
|
14153
14408
|
if (!row) return `\u672A\u627E\u5230 pending \u4E8B\u4EF6 #${id}`;
|
|
14154
14409
|
if (row.type === "daily" || row.type === "weekly") {
|
|
14155
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}`;
|
|
14156
14411
|
}
|
|
14157
|
-
|
|
14412
|
+
db2.prepare("UPDATE events SET status=?, done_at=?, reminded=1 WHERE id=?").run("done", nowIso(), id);
|
|
14158
14413
|
return `#${id} \u5DF2\u6807\u8BB0\u5B8C\u6210: ${row.event}`;
|
|
14159
14414
|
}
|
|
14160
|
-
function linkDoc(
|
|
14161
|
-
const row =
|
|
14415
|
+
function linkDoc(db2, id, docPath) {
|
|
14416
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=?").get(id);
|
|
14162
14417
|
if (!row) return `\u672A\u627E\u5230\u4E8B\u4EF6 #${id}`;
|
|
14163
|
-
|
|
14418
|
+
db2.prepare("UPDATE events SET doc_path=? WHERE id=?").run(docPath, id);
|
|
14164
14419
|
return `#${id} \u5DF2\u5173\u8054\u6587\u6863: ${docPath}`;
|
|
14165
14420
|
}
|
|
14166
|
-
function findDoc(
|
|
14167
|
-
const row =
|
|
14421
|
+
function findDoc(db2, id) {
|
|
14422
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=?").get(id);
|
|
14168
14423
|
if (!row) return `\u672A\u627E\u5230\u4E8B\u4EF6 #${id}`;
|
|
14169
14424
|
const parts = [`#${id} ${row.event}`];
|
|
14170
14425
|
if (row.doc_path) parts.push(`\u{1F4C4} doc_path: ${row.doc_path}`);
|
|
14171
14426
|
else parts.push(`\u{1F4C4} doc_path: (\u672A\u5173\u8054)`);
|
|
14172
14427
|
return parts.join("\n");
|
|
14173
14428
|
}
|
|
14174
|
-
function search(
|
|
14175
|
-
const rows =
|
|
14429
|
+
function search(db2, keyword) {
|
|
14430
|
+
const rows = db2.prepare("SELECT * FROM events WHERE event LIKE ? ORDER BY id").all(`%${keyword}%`);
|
|
14176
14431
|
if (rows.length > 0) {
|
|
14177
14432
|
const out = [`\u67E5\u8BE2 '${keyword}' (${rows.length} \u6761):`];
|
|
14178
14433
|
rows.forEach((r) => out.push(fmtRow(r)));
|
|
@@ -14180,29 +14435,29 @@ function search(db, keyword) {
|
|
|
14180
14435
|
}
|
|
14181
14436
|
return `\u67E5\u8BE2 '${keyword}' \u65E0\u7ED3\u679C`;
|
|
14182
14437
|
}
|
|
14183
|
-
function archive(
|
|
14184
|
-
const row =
|
|
14438
|
+
function archive(db2, id) {
|
|
14439
|
+
const row = db2.prepare("SELECT * FROM events WHERE id=? AND status!=?").get(id, "archived");
|
|
14185
14440
|
if (!row) return `\u672A\u627E\u5230\u4E8B\u4EF6 #${id}`;
|
|
14186
|
-
|
|
14441
|
+
db2.prepare("UPDATE events SET status=?, archived_at=?, reminded=1 WHERE id=?").run("archived", nowIso(), id);
|
|
14187
14442
|
return `#${id} \u5DF2\u5F52\u6863: ${row.event}`;
|
|
14188
14443
|
}
|
|
14189
|
-
function cleanup(
|
|
14190
|
-
const rows =
|
|
14444
|
+
function cleanup(db2) {
|
|
14445
|
+
const rows = db2.prepare("SELECT * FROM events WHERE type='date' AND status='done'").all();
|
|
14191
14446
|
let archived = 0;
|
|
14192
14447
|
for (const r of rows) {
|
|
14193
14448
|
const p = parseDateRange(r.date_str);
|
|
14194
14449
|
if (p && isOverdue(p.month, p.dStart, p.dEnd)) {
|
|
14195
|
-
|
|
14450
|
+
db2.prepare("UPDATE events SET status=?, archived_at=? WHERE id=?").run("archived", nowIso(), r.id);
|
|
14196
14451
|
archived++;
|
|
14197
14452
|
}
|
|
14198
14453
|
}
|
|
14199
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";
|
|
14200
14455
|
}
|
|
14201
|
-
function stats(
|
|
14202
|
-
const total =
|
|
14203
|
-
const pending2 =
|
|
14204
|
-
const done2 =
|
|
14205
|
-
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;
|
|
14206
14461
|
return `\u65E5\u5386\u7EDF\u8BA1: \u603B\u8BA1 ${total} | pending ${pending2} | done ${done2} | archived ${archived}`;
|
|
14207
14462
|
}
|
|
14208
14463
|
var WEEKDAYS2;
|
|
@@ -14248,7 +14503,7 @@ var init_calendar = __esm({
|
|
|
14248
14503
|
const action = args.action;
|
|
14249
14504
|
if (!action) return { content: "Error: action is required", isError: true };
|
|
14250
14505
|
try {
|
|
14251
|
-
const
|
|
14506
|
+
const db2 = openDb(ctx.workspace);
|
|
14252
14507
|
let result2;
|
|
14253
14508
|
let isAddTask = false;
|
|
14254
14509
|
if (action === "add") {
|
|
@@ -14258,22 +14513,22 @@ var init_calendar = __esm({
|
|
|
14258
14513
|
const repeat = args.repeat || (args.weekly ? "weekly" : "once");
|
|
14259
14514
|
if (repeat === "daily" || repeat === "weekdays") {
|
|
14260
14515
|
if (!args.time) return { content: "Error: add daily/weekdays needs time (e.g. 23:00)", isError: true };
|
|
14261
|
-
result2 = addDaily(
|
|
14516
|
+
result2 = addDaily(db2, { time: args.time, event, repeatType: repeat, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
|
|
14262
14517
|
} else if (repeat === "weekly") {
|
|
14263
14518
|
const day = args.day;
|
|
14264
14519
|
if (!day) return { content: "Error: add weekly needs day", isError: true };
|
|
14265
|
-
result2 = addWeekly(
|
|
14520
|
+
result2 = addWeekly(db2, { day, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
|
|
14266
14521
|
} else {
|
|
14267
14522
|
const date = args.date?.trim();
|
|
14268
14523
|
if (!date) return { content: "Error: add once needs date (e.g. 5/26)", isError: true };
|
|
14269
|
-
result2 = addDate(
|
|
14524
|
+
result2 = addDate(db2, { dateStr: date, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
|
|
14270
14525
|
}
|
|
14271
14526
|
} else if (action === "add-batch") {
|
|
14272
14527
|
const event = args.event?.trim();
|
|
14273
14528
|
const datesInput = args.dates?.trim();
|
|
14274
14529
|
if (!event) return { content: "Error: add-batch needs event", isError: true };
|
|
14275
14530
|
if (!datesInput) return { content: 'Error: add-batch needs dates (e.g. "7/2,7/4,7/6-7/10")', isError: true };
|
|
14276
|
-
result2 = addBatch(
|
|
14531
|
+
result2 = addBatch(db2, { datesInput, event, time: args.time, duration: args.duration, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
|
|
14277
14532
|
} else if (action === "add-task") {
|
|
14278
14533
|
isAddTask = true;
|
|
14279
14534
|
const event = args.event?.trim();
|
|
@@ -14284,47 +14539,47 @@ var init_calendar = __esm({
|
|
|
14284
14539
|
if (!date) return { content: "Error: add-task needs date (e.g. 7/5)", isError: true };
|
|
14285
14540
|
if (!timeExact || !timeExact.includes(":")) return { content: "Error: add-task needs time_exact (HH:MM, e.g. 14:00)", isError: true };
|
|
14286
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 };
|
|
14287
|
-
result2 = addTask(
|
|
14542
|
+
result2 = addTask(db2, { dateStr: date, timeExact, event, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget, docPath });
|
|
14288
14543
|
} else if (action === "reschedule") {
|
|
14289
14544
|
if (args.id == null) return { content: "Error: reschedule needs id", isError: true };
|
|
14290
14545
|
const date = args.date?.trim();
|
|
14291
14546
|
const timeExact = args.time_exact?.trim();
|
|
14292
14547
|
if (!date) return { content: "Error: reschedule needs date (e.g. 7/10)", isError: true };
|
|
14293
14548
|
if (!timeExact || !timeExact.includes(":")) return { content: "Error: reschedule needs time_exact (HH:MM)", isError: true };
|
|
14294
|
-
result2 = reschedule(
|
|
14549
|
+
result2 = reschedule(db2, { id: args.id, dateStr: date, timeExact, remind: args.remind });
|
|
14295
14550
|
} else if (action === "link-doc") {
|
|
14296
14551
|
if (args.id == null) return { content: "Error: link-doc needs id", isError: true };
|
|
14297
14552
|
const docPath = args.doc_path?.trim();
|
|
14298
14553
|
if (!docPath) return { content: "Error: link-doc needs doc_path", isError: true };
|
|
14299
|
-
result2 = linkDoc(
|
|
14554
|
+
result2 = linkDoc(db2, args.id, docPath);
|
|
14300
14555
|
} else if (action === "find-doc") {
|
|
14301
14556
|
if (args.id == null) return { content: "Error: find-doc needs id", isError: true };
|
|
14302
|
-
result2 = findDoc(
|
|
14557
|
+
result2 = findDoc(db2, args.id);
|
|
14303
14558
|
} else if (action === "list") {
|
|
14304
|
-
result2 = list(
|
|
14559
|
+
result2 = list(db2, { all: !!args.all });
|
|
14305
14560
|
} else if (action === "done") {
|
|
14306
14561
|
if (args.id == null) return { content: "Error: done needs id", isError: true };
|
|
14307
|
-
result2 = done(
|
|
14562
|
+
result2 = done(db2, args.id);
|
|
14308
14563
|
} else if (action === "pending") {
|
|
14309
|
-
result2 = pending(
|
|
14564
|
+
result2 = pending(db2);
|
|
14310
14565
|
} else if (action === "search") {
|
|
14311
14566
|
const kw = args.event?.trim();
|
|
14312
14567
|
if (!kw) return { content: "Error: search needs keyword (event field)", isError: true };
|
|
14313
|
-
result2 = search(
|
|
14568
|
+
result2 = search(db2, kw);
|
|
14314
14569
|
} else if (action === "archive") {
|
|
14315
14570
|
if (args.id == null) return { content: "Error: archive needs id", isError: true };
|
|
14316
|
-
result2 = archive(
|
|
14571
|
+
result2 = archive(db2, args.id);
|
|
14317
14572
|
} else if (action === "delete") {
|
|
14318
14573
|
if (args.id == null) return { content: "Error: delete needs id", isError: true };
|
|
14319
|
-
result2 = archive(
|
|
14574
|
+
result2 = archive(db2, args.id);
|
|
14320
14575
|
} else if (action === "cleanup") {
|
|
14321
|
-
result2 = cleanup(
|
|
14576
|
+
result2 = cleanup(db2);
|
|
14322
14577
|
} else if (action === "stats") {
|
|
14323
|
-
result2 = stats(
|
|
14578
|
+
result2 = stats(db2);
|
|
14324
14579
|
} else {
|
|
14325
14580
|
return { content: `Error: unknown action '${action}'`, isError: true };
|
|
14326
14581
|
}
|
|
14327
|
-
|
|
14582
|
+
db2.close();
|
|
14328
14583
|
const isFailed = result2.startsWith("\u274C") || result2.includes("Error") || result2.includes("\u7528\u6CD5");
|
|
14329
14584
|
if (isAddTask && !isFailed) {
|
|
14330
14585
|
const { enqueueNotification: enqueueNotification2, buildCalendarNotification: buildCalendarNotification2 } = await Promise.resolve().then(() => (init_task_manager(), task_manager_exports));
|
|
@@ -14568,24 +14823,24 @@ var init_constants5 = __esm({
|
|
|
14568
14823
|
});
|
|
14569
14824
|
|
|
14570
14825
|
// src/tools/TodoWriteTool/TodoWriteTool.ts
|
|
14571
|
-
import
|
|
14572
|
-
import
|
|
14826
|
+
import fs22 from "node:fs";
|
|
14827
|
+
import path23 from "node:path";
|
|
14573
14828
|
function todoFilePath(sessionId) {
|
|
14574
|
-
return
|
|
14829
|
+
return path23.join(todosDir, `${sessionId}.json`);
|
|
14575
14830
|
}
|
|
14576
14831
|
function loadTodos(sessionId) {
|
|
14577
14832
|
if (!todosDir) return [];
|
|
14578
14833
|
try {
|
|
14579
14834
|
const filePath = todoFilePath(sessionId);
|
|
14580
|
-
if (!
|
|
14581
|
-
return JSON.parse(
|
|
14835
|
+
if (!fs22.existsSync(filePath)) return [];
|
|
14836
|
+
return JSON.parse(fs22.readFileSync(filePath, "utf-8"));
|
|
14582
14837
|
} catch {
|
|
14583
14838
|
return [];
|
|
14584
14839
|
}
|
|
14585
14840
|
}
|
|
14586
14841
|
function saveTodos(sessionId, todos) {
|
|
14587
14842
|
if (!todosDir) return;
|
|
14588
|
-
|
|
14843
|
+
fs22.writeFileSync(todoFilePath(sessionId), JSON.stringify(todos, null, 2), "utf-8");
|
|
14589
14844
|
}
|
|
14590
14845
|
var todosDir;
|
|
14591
14846
|
var init_TodoWriteTool = __esm({
|
|
@@ -14842,15 +15097,15 @@ var init_constants7 = __esm({
|
|
|
14842
15097
|
});
|
|
14843
15098
|
|
|
14844
15099
|
// src/utils/plans.ts
|
|
14845
|
-
import * as
|
|
14846
|
-
import * as
|
|
15100
|
+
import * as fs23 from "node:fs";
|
|
15101
|
+
import * as path24 from "node:path";
|
|
14847
15102
|
import * as crypto4 from "node:crypto";
|
|
14848
15103
|
function generateSlug() {
|
|
14849
15104
|
return crypto4.randomBytes(4).toString("hex");
|
|
14850
15105
|
}
|
|
14851
15106
|
function getPlansDirectory(stateDir) {
|
|
14852
|
-
const plansDir =
|
|
14853
|
-
|
|
15107
|
+
const plansDir = path24.join(stateDir, "plans");
|
|
15108
|
+
fs23.mkdirSync(plansDir, { recursive: true });
|
|
14854
15109
|
return plansDir;
|
|
14855
15110
|
}
|
|
14856
15111
|
function getPlanSlug(sessionId, stateDir) {
|
|
@@ -14859,8 +15114,8 @@ function getPlanSlug(sessionId, stateDir) {
|
|
|
14859
15114
|
const plansDir = getPlansDirectory(stateDir);
|
|
14860
15115
|
for (let i = 0; i < MAX_SLUG_RETRIES; i++) {
|
|
14861
15116
|
slug = generateSlug();
|
|
14862
|
-
const filePath =
|
|
14863
|
-
if (!
|
|
15117
|
+
const filePath = path24.join(plansDir, `${slug}.md`);
|
|
15118
|
+
if (!fs23.existsSync(filePath)) {
|
|
14864
15119
|
break;
|
|
14865
15120
|
}
|
|
14866
15121
|
}
|
|
@@ -14871,21 +15126,21 @@ function getPlanSlug(sessionId, stateDir) {
|
|
|
14871
15126
|
function getPlanFilePath(sessionId, stateDir, agentId) {
|
|
14872
15127
|
const slug = getPlanSlug(sessionId, stateDir);
|
|
14873
15128
|
if (!agentId) {
|
|
14874
|
-
return
|
|
15129
|
+
return path24.join(getPlansDirectory(stateDir), `${slug}.md`);
|
|
14875
15130
|
}
|
|
14876
|
-
return
|
|
15131
|
+
return path24.join(getPlansDirectory(stateDir), `${slug}-agent-${agentId}.md`);
|
|
14877
15132
|
}
|
|
14878
15133
|
function getPlan(sessionId, stateDir, agentId) {
|
|
14879
15134
|
const filePath = getPlanFilePath(sessionId, stateDir, agentId);
|
|
14880
15135
|
try {
|
|
14881
|
-
return
|
|
15136
|
+
return fs23.readFileSync(filePath, "utf-8");
|
|
14882
15137
|
} catch {
|
|
14883
15138
|
return null;
|
|
14884
15139
|
}
|
|
14885
15140
|
}
|
|
14886
15141
|
function writePlan(sessionId, stateDir, content, agentId) {
|
|
14887
15142
|
const filePath = getPlanFilePath(sessionId, stateDir, agentId);
|
|
14888
|
-
|
|
15143
|
+
fs23.writeFileSync(filePath, content, "utf-8");
|
|
14889
15144
|
return filePath;
|
|
14890
15145
|
}
|
|
14891
15146
|
var MAX_SLUG_RETRIES, planSlugCache;
|
|
@@ -15033,28 +15288,28 @@ var init_constants8 = __esm({
|
|
|
15033
15288
|
});
|
|
15034
15289
|
|
|
15035
15290
|
// src/utils/tasks.ts
|
|
15036
|
-
import * as
|
|
15037
|
-
import * as
|
|
15291
|
+
import * as fs24 from "node:fs";
|
|
15292
|
+
import * as path25 from "node:path";
|
|
15038
15293
|
function sanitizePathComponent2(input) {
|
|
15039
15294
|
return input.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
15040
15295
|
}
|
|
15041
15296
|
function getTasksDir2(stateDir, listId) {
|
|
15042
|
-
return
|
|
15297
|
+
return path25.join(stateDir, "tasks", sanitizePathComponent2(listId));
|
|
15043
15298
|
}
|
|
15044
15299
|
function getTaskPath(stateDir, listId, taskId) {
|
|
15045
|
-
return
|
|
15300
|
+
return path25.join(getTasksDir2(stateDir, listId), `${sanitizePathComponent2(taskId)}.json`);
|
|
15046
15301
|
}
|
|
15047
15302
|
function ensureTasksDir2(stateDir, listId) {
|
|
15048
15303
|
const dir = getTasksDir2(stateDir, listId);
|
|
15049
|
-
|
|
15304
|
+
fs24.mkdirSync(dir, { recursive: true });
|
|
15050
15305
|
return dir;
|
|
15051
15306
|
}
|
|
15052
15307
|
function getHighWaterMarkPath(stateDir, listId) {
|
|
15053
|
-
return
|
|
15308
|
+
return path25.join(getTasksDir2(stateDir, listId), HIGH_WATER_MARK_FILE);
|
|
15054
15309
|
}
|
|
15055
15310
|
function readHighWaterMark(stateDir, listId) {
|
|
15056
15311
|
try {
|
|
15057
|
-
const content =
|
|
15312
|
+
const content = fs24.readFileSync(getHighWaterMarkPath(stateDir, listId), "utf-8").trim();
|
|
15058
15313
|
const value = parseInt(content, 10);
|
|
15059
15314
|
return isNaN(value) ? 0 : value;
|
|
15060
15315
|
} catch {
|
|
@@ -15062,20 +15317,20 @@ function readHighWaterMark(stateDir, listId) {
|
|
|
15062
15317
|
}
|
|
15063
15318
|
}
|
|
15064
15319
|
function writeHighWaterMark(stateDir, listId, value) {
|
|
15065
|
-
|
|
15320
|
+
fs24.writeFileSync(getHighWaterMarkPath(stateDir, listId), String(value));
|
|
15066
15321
|
}
|
|
15067
15322
|
function findHighestTaskIdFromFiles(stateDir, listId) {
|
|
15068
15323
|
const dir = getTasksDir2(stateDir, listId);
|
|
15069
15324
|
let files;
|
|
15070
15325
|
try {
|
|
15071
|
-
files =
|
|
15326
|
+
files = fs24.readdirSync(dir);
|
|
15072
15327
|
} catch {
|
|
15073
15328
|
return 0;
|
|
15074
15329
|
}
|
|
15075
15330
|
let highest = 0;
|
|
15076
|
-
for (const
|
|
15077
|
-
if (!
|
|
15078
|
-
const taskId = parseInt(
|
|
15331
|
+
for (const file2 of files) {
|
|
15332
|
+
if (!file2.endsWith(".json")) continue;
|
|
15333
|
+
const taskId = parseInt(file2.replace(".json", ""), 10);
|
|
15079
15334
|
if (!isNaN(taskId) && taskId > highest) {
|
|
15080
15335
|
highest = taskId;
|
|
15081
15336
|
}
|
|
@@ -15094,14 +15349,14 @@ function createTask(stateDir, listId, taskData) {
|
|
|
15094
15349
|
const id = String(highestId + 1);
|
|
15095
15350
|
const task = { id, ...taskData };
|
|
15096
15351
|
const filePath = getTaskPath(stateDir, listId, id);
|
|
15097
|
-
|
|
15352
|
+
fs24.writeFileSync(filePath, JSON.stringify(task, null, 2));
|
|
15098
15353
|
return id;
|
|
15099
15354
|
});
|
|
15100
15355
|
}
|
|
15101
15356
|
function getTask2(stateDir, listId, taskId) {
|
|
15102
15357
|
const filePath = getTaskPath(stateDir, listId, taskId);
|
|
15103
15358
|
try {
|
|
15104
|
-
const content =
|
|
15359
|
+
const content = fs24.readFileSync(filePath, "utf-8");
|
|
15105
15360
|
return JSON.parse(content);
|
|
15106
15361
|
} catch {
|
|
15107
15362
|
return null;
|
|
@@ -15111,7 +15366,7 @@ function listTasks2(stateDir, listId) {
|
|
|
15111
15366
|
const dir = getTasksDir2(stateDir, listId);
|
|
15112
15367
|
let files;
|
|
15113
15368
|
try {
|
|
15114
|
-
files =
|
|
15369
|
+
files = fs24.readdirSync(dir);
|
|
15115
15370
|
} catch {
|
|
15116
15371
|
return [];
|
|
15117
15372
|
}
|
|
@@ -15123,7 +15378,7 @@ function updateTask(stateDir, listId, taskId, updates) {
|
|
|
15123
15378
|
if (!existing) return null;
|
|
15124
15379
|
const updated = { ...existing, ...updates, id: taskId };
|
|
15125
15380
|
const filePath = getTaskPath(stateDir, listId, taskId);
|
|
15126
|
-
|
|
15381
|
+
fs24.writeFileSync(filePath, JSON.stringify(updated, null, 2));
|
|
15127
15382
|
return updated;
|
|
15128
15383
|
}
|
|
15129
15384
|
function deleteTask(stateDir, listId, taskId) {
|
|
@@ -15137,7 +15392,7 @@ function deleteTask(stateDir, listId, taskId) {
|
|
|
15137
15392
|
}
|
|
15138
15393
|
}
|
|
15139
15394
|
try {
|
|
15140
|
-
|
|
15395
|
+
fs24.unlinkSync(filePath);
|
|
15141
15396
|
} catch {
|
|
15142
15397
|
return false;
|
|
15143
15398
|
}
|
|
@@ -16570,10 +16825,10 @@ function ensureLoaded(workspace, configIds) {
|
|
|
16570
16825
|
if (!state.blockedUserIds.includes(id)) state.blockedUserIds.push(id);
|
|
16571
16826
|
}
|
|
16572
16827
|
}
|
|
16573
|
-
const
|
|
16828
|
+
const path31 = join23(workspace, ".reply-blocklist.json");
|
|
16574
16829
|
try {
|
|
16575
|
-
if (existsSync18(
|
|
16576
|
-
const raw = readFileSync18(
|
|
16830
|
+
if (existsSync18(path31)) {
|
|
16831
|
+
const raw = readFileSync18(path31, "utf-8");
|
|
16577
16832
|
const parsed = JSON.parse(raw);
|
|
16578
16833
|
if (parsed.blockedUserIds) {
|
|
16579
16834
|
for (const id of parsed.blockedUserIds) {
|
|
@@ -16589,9 +16844,9 @@ function ensureLoaded(workspace, configIds) {
|
|
|
16589
16844
|
loaded = true;
|
|
16590
16845
|
}
|
|
16591
16846
|
function save(workspace) {
|
|
16592
|
-
const
|
|
16847
|
+
const path31 = join23(workspace, ".reply-blocklist.json");
|
|
16593
16848
|
try {
|
|
16594
|
-
writeFileSync14(
|
|
16849
|
+
writeFileSync14(path31, JSON.stringify(state, null, 2), "utf-8");
|
|
16595
16850
|
} catch (err) {
|
|
16596
16851
|
console.warn(`[reply-blocklist] Failed to save: ${err.message}`);
|
|
16597
16852
|
}
|
|
@@ -17108,9 +17363,9 @@ function cosineSim(a, b) {
|
|
|
17108
17363
|
}
|
|
17109
17364
|
function readDbEmbeddings(dbPath) {
|
|
17110
17365
|
const { DatabaseSync: DatabaseSync2 } = require3("node:sqlite");
|
|
17111
|
-
const
|
|
17366
|
+
const db2 = new DatabaseSync2(dbPath, { readOnly: true });
|
|
17112
17367
|
try {
|
|
17113
|
-
const stmt =
|
|
17368
|
+
const stmt = db2.prepare(`
|
|
17114
17369
|
SELECT file_path, name, description, mtime, embedding
|
|
17115
17370
|
FROM files
|
|
17116
17371
|
WHERE embedding IS NOT NULL AND deprecated_by IS NULL
|
|
@@ -17127,7 +17382,7 @@ function readDbEmbeddings(dbPath) {
|
|
|
17127
17382
|
}
|
|
17128
17383
|
return rows;
|
|
17129
17384
|
} finally {
|
|
17130
|
-
|
|
17385
|
+
db2.close();
|
|
17131
17386
|
}
|
|
17132
17387
|
}
|
|
17133
17388
|
async function llmRerank(query, candidates, topK, ollamaChatUrl, model) {
|
|
@@ -17504,6 +17759,69 @@ var init_light_mode = __esm({
|
|
|
17504
17759
|
}
|
|
17505
17760
|
});
|
|
17506
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
|
+
|
|
17507
17825
|
// src/sender-context.ts
|
|
17508
17826
|
import { readFileSync as readFileSync21, existsSync as existsSync20 } from "node:fs";
|
|
17509
17827
|
import { join as join28 } from "node:path";
|
|
@@ -17671,8 +17989,8 @@ var extractMemories_exports = {};
|
|
|
17671
17989
|
__export(extractMemories_exports, {
|
|
17672
17990
|
createMemoryExtractor: () => createMemoryExtractor
|
|
17673
17991
|
});
|
|
17674
|
-
import * as
|
|
17675
|
-
import * as
|
|
17992
|
+
import * as fs25 from "fs";
|
|
17993
|
+
import * as path26 from "path";
|
|
17676
17994
|
function isModelVisibleMessage(message) {
|
|
17677
17995
|
return message.role === "user" || message.role === "assistant";
|
|
17678
17996
|
}
|
|
@@ -17695,13 +18013,13 @@ function getMemoryTools() {
|
|
|
17695
18013
|
return allDefs.filter((d) => MEMORY_TOOL_NAMES.includes(d.function.name));
|
|
17696
18014
|
}
|
|
17697
18015
|
function getStatePath(workspace) {
|
|
17698
|
-
return
|
|
18016
|
+
return path26.join(workspace, STATE_FILE);
|
|
17699
18017
|
}
|
|
17700
18018
|
function loadPersistedState(workspace) {
|
|
17701
18019
|
try {
|
|
17702
18020
|
const p = getStatePath(workspace);
|
|
17703
|
-
if (
|
|
17704
|
-
const data = JSON.parse(
|
|
18021
|
+
if (fs25.existsSync(p)) {
|
|
18022
|
+
const data = JSON.parse(fs25.readFileSync(p, "utf-8"));
|
|
17705
18023
|
for (const [sid, ts] of Object.entries(data.lastTs ?? {})) {
|
|
17706
18024
|
lastTsMap.set(sid, ts);
|
|
17707
18025
|
}
|
|
@@ -17721,7 +18039,7 @@ function persistState(workspace) {
|
|
|
17721
18039
|
for (const [sid, ts] of lastTsMap.entries()) lastTs[sid] = ts;
|
|
17722
18040
|
for (const [sid, ts] of lastExtractTimeMap.entries()) timestamps[sid] = ts;
|
|
17723
18041
|
const data = JSON.stringify({ lastTs, timestamps }, null, 2);
|
|
17724
|
-
|
|
18042
|
+
fs25.writeFileSync(getStatePath(workspace), data, "utf-8");
|
|
17725
18043
|
} catch (e) {
|
|
17726
18044
|
console.warn(`[memory] failed to persist extract state: ${e?.message ?? e}`);
|
|
17727
18045
|
}
|
|
@@ -17762,11 +18080,11 @@ function createMemoryExtractor(workspace, enabled) {
|
|
|
17762
18080
|
const existingMemories = formatMemoryManifest(
|
|
17763
18081
|
await scanMemoryFiles2(memoryDir, new AbortController().signal)
|
|
17764
18082
|
);
|
|
17765
|
-
const extractOverridePath =
|
|
18083
|
+
const extractOverridePath = path26.join(workspace, "prompts", "extract.md");
|
|
17766
18084
|
let systemPrompt;
|
|
17767
18085
|
try {
|
|
17768
|
-
if (
|
|
17769
|
-
systemPrompt =
|
|
18086
|
+
if (fs25.existsSync(extractOverridePath)) {
|
|
18087
|
+
systemPrompt = fs25.readFileSync(extractOverridePath, { encoding: "utf-8" });
|
|
17770
18088
|
if (existingMemories.length > 0) {
|
|
17771
18089
|
systemPrompt += `
|
|
17772
18090
|
|
|
@@ -17867,8 +18185,8 @@ var ingest_exports = {};
|
|
|
17867
18185
|
__export(ingest_exports, {
|
|
17868
18186
|
pushConversation: () => pushConversation
|
|
17869
18187
|
});
|
|
17870
|
-
import
|
|
17871
|
-
import
|
|
18188
|
+
import fs26 from "node:fs";
|
|
18189
|
+
import path27 from "node:path";
|
|
17872
18190
|
function parseMeta(text) {
|
|
17873
18191
|
const m = text.match(/^\[meta:\s*(.+?)\s*\((.+?)\)\s*@(\S+)\s*[^\]]*\]/);
|
|
17874
18192
|
if (!m) return null;
|
|
@@ -17901,9 +18219,9 @@ async function readConfig() {
|
|
|
17901
18219
|
}
|
|
17902
18220
|
function loadPushTs(workspace, sessionId) {
|
|
17903
18221
|
try {
|
|
17904
|
-
const p =
|
|
17905
|
-
if (
|
|
17906
|
-
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"));
|
|
17907
18225
|
return typeof data[sessionId] === "number" ? data[sessionId] : 0;
|
|
17908
18226
|
}
|
|
17909
18227
|
} catch (e) {
|
|
@@ -17913,14 +18231,14 @@ function loadPushTs(workspace, sessionId) {
|
|
|
17913
18231
|
}
|
|
17914
18232
|
function savePushTs(workspace, sessionId, ts) {
|
|
17915
18233
|
try {
|
|
17916
|
-
const p =
|
|
18234
|
+
const p = path27.join(workspace, PUSH_STATE_FILE);
|
|
17917
18235
|
let data = {};
|
|
17918
18236
|
try {
|
|
17919
|
-
if (
|
|
18237
|
+
if (fs26.existsSync(p)) data = JSON.parse(fs26.readFileSync(p, "utf-8"));
|
|
17920
18238
|
} catch {
|
|
17921
18239
|
}
|
|
17922
18240
|
data[sessionId] = ts;
|
|
17923
|
-
|
|
18241
|
+
fs26.writeFileSync(p, JSON.stringify(data, null, 2), "utf-8");
|
|
17924
18242
|
} catch (e) {
|
|
17925
18243
|
console.warn(`[everos-ingest] save pushTs failed: ${e?.message ?? e}`);
|
|
17926
18244
|
}
|
|
@@ -18569,11 +18887,11 @@ async function readLastConsolidatedAt(memoryDir) {
|
|
|
18569
18887
|
}
|
|
18570
18888
|
}
|
|
18571
18889
|
async function tryAcquireConsolidationLock(memoryDir) {
|
|
18572
|
-
const
|
|
18890
|
+
const path31 = lockPath(memoryDir);
|
|
18573
18891
|
let mtimeMs;
|
|
18574
18892
|
let holderPid;
|
|
18575
18893
|
try {
|
|
18576
|
-
const [s, raw] = await Promise.all([stat3(
|
|
18894
|
+
const [s, raw] = await Promise.all([stat3(path31), readFile5(path31, "utf8")]);
|
|
18577
18895
|
mtimeMs = s.mtimeMs;
|
|
18578
18896
|
const parsed = parseInt(raw.trim(), 10);
|
|
18579
18897
|
holderPid = Number.isFinite(parsed) ? parsed : void 0;
|
|
@@ -18586,10 +18904,10 @@ async function tryAcquireConsolidationLock(memoryDir) {
|
|
|
18586
18904
|
}
|
|
18587
18905
|
}
|
|
18588
18906
|
await mkdir3(memoryDir, { recursive: true });
|
|
18589
|
-
await writeFile4(
|
|
18907
|
+
await writeFile4(path31, String(process.pid));
|
|
18590
18908
|
let verify;
|
|
18591
18909
|
try {
|
|
18592
|
-
verify = await readFile5(
|
|
18910
|
+
verify = await readFile5(path31, "utf8");
|
|
18593
18911
|
} catch {
|
|
18594
18912
|
return null;
|
|
18595
18913
|
}
|
|
@@ -18597,15 +18915,15 @@ async function tryAcquireConsolidationLock(memoryDir) {
|
|
|
18597
18915
|
return mtimeMs ?? 0;
|
|
18598
18916
|
}
|
|
18599
18917
|
async function rollbackConsolidationLock(memoryDir, priorMtime) {
|
|
18600
|
-
const
|
|
18918
|
+
const path31 = lockPath(memoryDir);
|
|
18601
18919
|
try {
|
|
18602
18920
|
if (priorMtime === 0) {
|
|
18603
|
-
await unlink(
|
|
18921
|
+
await unlink(path31);
|
|
18604
18922
|
return;
|
|
18605
18923
|
}
|
|
18606
|
-
await writeFile4(
|
|
18924
|
+
await writeFile4(path31, "");
|
|
18607
18925
|
const t = priorMtime / 1e3;
|
|
18608
|
-
await utimes(
|
|
18926
|
+
await utimes(path31, t, t);
|
|
18609
18927
|
} catch (e) {
|
|
18610
18928
|
console.log(`[autoDream] rollback failed: ${e.message} \u2014 next trigger delayed to minHours`);
|
|
18611
18929
|
}
|
|
@@ -18888,34 +19206,30 @@ var handle_query_exports = {};
|
|
|
18888
19206
|
__export(handle_query_exports, {
|
|
18889
19207
|
handleQuery: () => handleQuery,
|
|
18890
19208
|
resetSessionStartInjection: () => resetSessionStartInjection,
|
|
18891
|
-
resetWorkModeInjection: () => resetWorkModeInjection,
|
|
18892
19209
|
resolveSystemPrompt: () => resolveSystemPrompt
|
|
18893
19210
|
});
|
|
18894
19211
|
import { readFileSync as readFileSync25, existsSync as existsSync22 } from "node:fs";
|
|
18895
19212
|
import { join as join33, resolve as resolve8 } from "node:path";
|
|
18896
|
-
import * as
|
|
19213
|
+
import * as path28 from "node:path";
|
|
18897
19214
|
function resolveSystemPrompt(v) {
|
|
18898
19215
|
return typeof v === "function" ? v() : v || "";
|
|
18899
19216
|
}
|
|
18900
19217
|
function resetSessionStartInjection(sessionId) {
|
|
18901
19218
|
sessionStartDone.delete(sessionId);
|
|
18902
19219
|
}
|
|
18903
|
-
function resetWorkModeInjection(sessionId) {
|
|
18904
|
-
workModeInjected.delete(sessionId);
|
|
18905
|
-
}
|
|
18906
19220
|
function loadExternalChanRules(workspace) {
|
|
18907
|
-
const
|
|
18908
|
-
if (externalChanRulesCache && externalChanRulesCache.path ===
|
|
19221
|
+
const path31 = join33(workspace, "prompts", "external-chan-rules.md");
|
|
19222
|
+
if (externalChanRulesCache && externalChanRulesCache.path === path31) return externalChanRulesCache;
|
|
18909
19223
|
let content = "";
|
|
18910
|
-
if (existsSync22(
|
|
19224
|
+
if (existsSync22(path31)) {
|
|
18911
19225
|
try {
|
|
18912
|
-
content = readFileSync25(
|
|
19226
|
+
content = readFileSync25(path31, "utf-8").trim();
|
|
18913
19227
|
} catch (e) {
|
|
18914
19228
|
console.warn(`[external-chan-rules] Failed to load: ${e}`);
|
|
18915
19229
|
}
|
|
18916
19230
|
}
|
|
18917
|
-
externalChanRulesCache = { path:
|
|
18918
|
-
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}`);
|
|
18919
19233
|
return externalChanRulesCache;
|
|
18920
19234
|
}
|
|
18921
19235
|
function getExternalChanRulesBlock(inboundMeta, workspace) {
|
|
@@ -19123,7 +19437,13 @@ ${text}` : text });
|
|
|
19123
19437
|
const isLight = isLightMode(chatMode, channelName) && chatMode !== "emotion";
|
|
19124
19438
|
const lightN = resolveLightN(channelName);
|
|
19125
19439
|
const lightHistory = buildLightHistory(history, { isLight, lightN, channelName, chatMode, recallFull: emotionStripped });
|
|
19126
|
-
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)];
|
|
19127
19447
|
if (deps.mcpManager && !deps.mcpManager.isMcpDeltaSent(sessionId)) {
|
|
19128
19448
|
const delta = deps.mcpManager.getMcpDelta();
|
|
19129
19449
|
if (delta && delta.addedBlocks.length > 0) {
|
|
@@ -19177,30 +19497,6 @@ ${text}` : text });
|
|
|
19177
19497
|
}
|
|
19178
19498
|
}
|
|
19179
19499
|
}
|
|
19180
|
-
if (chatMode === "emotion") {
|
|
19181
|
-
if (workModeInjected.has(sessionId)) workModeInjected.delete(sessionId);
|
|
19182
|
-
} else if (!workModeInjected.has(sessionId)) {
|
|
19183
|
-
workModeInjected.add(sessionId);
|
|
19184
|
-
try {
|
|
19185
|
-
const sr = await executeSessionStartHooks(channelName === "cli" ? "cli" : "channel", {
|
|
19186
|
-
sessionId,
|
|
19187
|
-
workspace,
|
|
19188
|
-
cwd: workspace,
|
|
19189
|
-
channel: channelName === "cli" ? "console" : channelName,
|
|
19190
|
-
senderId: inboundMeta?.from || "",
|
|
19191
|
-
channelType: inboundMeta?.channelType || "",
|
|
19192
|
-
source
|
|
19193
|
-
});
|
|
19194
|
-
if (sr.additionalContexts && sr.additionalContexts.length > 0) {
|
|
19195
|
-
const att = createAttachmentMessage({ type: "session_start", text: sr.additionalContexts.join("\n\n") });
|
|
19196
|
-
history.push(att);
|
|
19197
|
-
messages.push(att);
|
|
19198
|
-
console.log(`[hooks] work-mode injection: ${sr.additionalContexts.length} additionalContext(s) at END of messages (session ${sessionId}, cache-safe, persisted)`);
|
|
19199
|
-
}
|
|
19200
|
-
} catch (err) {
|
|
19201
|
-
console.warn(`[hooks] work-mode injection error: ${err.message}`);
|
|
19202
|
-
}
|
|
19203
|
-
}
|
|
19204
19500
|
const pendingNotifications2 = drainPendingNotifications();
|
|
19205
19501
|
if (pendingNotifications2.length > 0) {
|
|
19206
19502
|
messages.push(createAttachmentMessage({
|
|
@@ -19221,7 +19517,7 @@ ${text}` : text });
|
|
|
19221
19517
|
}));
|
|
19222
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(" | ")}`);
|
|
19223
19519
|
}
|
|
19224
|
-
if (channelName !== "heartbeat" && channelName !== "cron" && channelName !== "inner-voice" && channelName !== "
|
|
19520
|
+
if (channelName !== "heartbeat" && channelName !== "cron" && channelName !== "inner-voice" && channelName !== "proactive") {
|
|
19225
19521
|
sessions.touch(sessionId);
|
|
19226
19522
|
}
|
|
19227
19523
|
const toolContext = {
|
|
@@ -19665,7 +19961,7 @@ stack: ${err.stack ?? "(none)"}`);
|
|
|
19665
19961
|
}
|
|
19666
19962
|
} catch (err) {
|
|
19667
19963
|
try {
|
|
19668
|
-
(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}
|
|
19669
19965
|
stack: ${err.stack ?? "(none)"}
|
|
19670
19966
|
`);
|
|
19671
19967
|
} catch {
|
|
@@ -19683,7 +19979,7 @@ function roughTokenCount(messages) {
|
|
|
19683
19979
|
}
|
|
19684
19980
|
return total;
|
|
19685
19981
|
}
|
|
19686
|
-
var sessionStartDone,
|
|
19982
|
+
var sessionStartDone, externalChanRulesCache;
|
|
19687
19983
|
var init_handle_query = __esm({
|
|
19688
19984
|
"src/handle-query.ts"() {
|
|
19689
19985
|
"use strict";
|
|
@@ -19703,9 +19999,9 @@ var init_handle_query = __esm({
|
|
|
19703
19999
|
init_findRelevantMemoriesEveros();
|
|
19704
20000
|
init_paths();
|
|
19705
20001
|
init_light_mode();
|
|
20002
|
+
init_voiceFastView();
|
|
19706
20003
|
init_sender_context();
|
|
19707
20004
|
sessionStartDone = /* @__PURE__ */ new Set();
|
|
19708
|
-
workModeInjected = /* @__PURE__ */ new Set();
|
|
19709
20005
|
externalChanRulesCache = null;
|
|
19710
20006
|
}
|
|
19711
20007
|
});
|
|
@@ -20211,20 +20507,20 @@ __export(cli_travel_exports, {
|
|
|
20211
20507
|
loadTravelConfig: () => loadTravelConfig,
|
|
20212
20508
|
saveTravelConfig: () => saveTravelConfig
|
|
20213
20509
|
});
|
|
20214
|
-
import * as
|
|
20215
|
-
import * as
|
|
20510
|
+
import * as path29 from "node:path";
|
|
20511
|
+
import * as fs27 from "node:fs";
|
|
20216
20512
|
import * as os4 from "node:os";
|
|
20217
20513
|
import { execSync as execSync2 } from "node:child_process";
|
|
20218
20514
|
function loadTravelConfig() {
|
|
20219
20515
|
try {
|
|
20220
|
-
if (!
|
|
20221
|
-
return JSON.parse(
|
|
20516
|
+
if (!fs27.existsSync(CONFIG_PATH)) return null;
|
|
20517
|
+
return JSON.parse(fs27.readFileSync(CONFIG_PATH, "utf-8"));
|
|
20222
20518
|
} catch {
|
|
20223
20519
|
return null;
|
|
20224
20520
|
}
|
|
20225
20521
|
}
|
|
20226
20522
|
function saveTravelConfig(cfg) {
|
|
20227
|
-
|
|
20523
|
+
fs27.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
|
|
20228
20524
|
}
|
|
20229
20525
|
function sanitizeContent(content, dirs) {
|
|
20230
20526
|
let result2 = content;
|
|
@@ -20249,7 +20545,7 @@ function restoreContent(content, dirs) {
|
|
|
20249
20545
|
return result2;
|
|
20250
20546
|
}
|
|
20251
20547
|
function isTextFile(filePath) {
|
|
20252
|
-
const ext =
|
|
20548
|
+
const ext = path29.extname(filePath).toLowerCase();
|
|
20253
20549
|
return TEXT_EXTENSIONS.has(ext);
|
|
20254
20550
|
}
|
|
20255
20551
|
function shouldExclude(name) {
|
|
@@ -20264,14 +20560,14 @@ function shouldExclude(name) {
|
|
|
20264
20560
|
}
|
|
20265
20561
|
function collectFiles(rootDir, includeSet, optionalSet) {
|
|
20266
20562
|
const files = [];
|
|
20267
|
-
const entries2 =
|
|
20563
|
+
const entries2 = fs27.readdirSync(rootDir, { withFileTypes: true });
|
|
20268
20564
|
for (const entry of entries2) {
|
|
20269
20565
|
if (shouldExclude(entry.name)) continue;
|
|
20270
|
-
const fullPath =
|
|
20271
|
-
const realPath =
|
|
20566
|
+
const fullPath = path29.join(rootDir, entry.name);
|
|
20567
|
+
const realPath = fs27.realpathSync(fullPath);
|
|
20272
20568
|
if (realPath !== fullPath) {
|
|
20273
20569
|
try {
|
|
20274
|
-
const lstat =
|
|
20570
|
+
const lstat = fs27.lstatSync(fullPath);
|
|
20275
20571
|
if (lstat.isSymbolicLink()) {
|
|
20276
20572
|
continue;
|
|
20277
20573
|
}
|
|
@@ -20292,12 +20588,12 @@ function collectFiles(rootDir, includeSet, optionalSet) {
|
|
|
20292
20588
|
function collectAllFiles(dir) {
|
|
20293
20589
|
const files = [];
|
|
20294
20590
|
try {
|
|
20295
|
-
const entries2 =
|
|
20591
|
+
const entries2 = fs27.readdirSync(dir, { withFileTypes: true });
|
|
20296
20592
|
for (const entry of entries2) {
|
|
20297
20593
|
if (shouldExclude(entry.name)) continue;
|
|
20298
|
-
const fullPath =
|
|
20594
|
+
const fullPath = path29.join(dir, entry.name);
|
|
20299
20595
|
try {
|
|
20300
|
-
if (
|
|
20596
|
+
if (fs27.lstatSync(fullPath).isSymbolicLink()) continue;
|
|
20301
20597
|
} catch {
|
|
20302
20598
|
}
|
|
20303
20599
|
if (entry.isDirectory()) {
|
|
@@ -20312,16 +20608,16 @@ function collectAllFiles(dir) {
|
|
|
20312
20608
|
}
|
|
20313
20609
|
function readMainEngineUuid(agentsDir) {
|
|
20314
20610
|
try {
|
|
20315
|
-
const platformMapPath =
|
|
20316
|
-
const indexMapPath =
|
|
20317
|
-
if (!
|
|
20318
|
-
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"));
|
|
20319
20615
|
const mainPlatformId = platformMap["scope:main"] || platformMap["main"];
|
|
20320
20616
|
if (!mainPlatformId) return null;
|
|
20321
|
-
const indexMap = JSON.parse(
|
|
20617
|
+
const indexMap = JSON.parse(fs27.readFileSync(indexMapPath, "utf-8"));
|
|
20322
20618
|
const entry = indexMap[mainPlatformId];
|
|
20323
20619
|
if (!entry || !entry.file) return null;
|
|
20324
|
-
const basename8 =
|
|
20620
|
+
const basename8 = path29.basename(entry.file).replace(/\.jsonl$/, "");
|
|
20325
20621
|
return basename8;
|
|
20326
20622
|
} catch {
|
|
20327
20623
|
return null;
|
|
@@ -20329,13 +20625,13 @@ function readMainEngineUuid(agentsDir) {
|
|
|
20329
20625
|
}
|
|
20330
20626
|
function collectRecentSessions(agentsDir, _days = 7) {
|
|
20331
20627
|
const files = [];
|
|
20332
|
-
if (!
|
|
20628
|
+
if (!fs27.existsSync(agentsDir)) return files;
|
|
20333
20629
|
const sessionGroups = /* @__PURE__ */ new Map();
|
|
20334
20630
|
function scanSessionsDir(dir) {
|
|
20335
20631
|
try {
|
|
20336
|
-
const entries2 =
|
|
20632
|
+
const entries2 = fs27.readdirSync(dir, { withFileTypes: true });
|
|
20337
20633
|
for (const entry of entries2) {
|
|
20338
|
-
const fullPath =
|
|
20634
|
+
const fullPath = path29.join(dir, entry.name);
|
|
20339
20635
|
if (entry.isDirectory()) {
|
|
20340
20636
|
scanSessionsDir(fullPath);
|
|
20341
20637
|
continue;
|
|
@@ -20359,7 +20655,7 @@ function collectRecentSessions(agentsDir, _days = 7) {
|
|
|
20359
20655
|
if (entry.name.endsWith(".jsonl")) {
|
|
20360
20656
|
group.jsonl = fullPath;
|
|
20361
20657
|
} else {
|
|
20362
|
-
const stat4 =
|
|
20658
|
+
const stat4 = fs27.statSync(fullPath);
|
|
20363
20659
|
group.archived.push({ file: fullPath, mtime: stat4.mtimeMs });
|
|
20364
20660
|
}
|
|
20365
20661
|
}
|
|
@@ -20378,37 +20674,37 @@ function collectRecentSessions(agentsDir, _days = 7) {
|
|
|
20378
20674
|
}
|
|
20379
20675
|
async function doExport(opts) {
|
|
20380
20676
|
const { agentName, stateDir, note, dryRun: dryRun2 } = opts;
|
|
20381
|
-
const workspace = (opts.workspace ||
|
|
20382
|
-
const engineHome =
|
|
20677
|
+
const workspace = (opts.workspace || path29.join(stateDir, "workspace")).replace(/[/\\]+$/, "");
|
|
20678
|
+
const engineHome = path29.join(os4.homedir(), ".engine7").replace(/[/\\]+$/, "");
|
|
20383
20679
|
console.log(`\u{1F4E6} engine7 export`);
|
|
20384
20680
|
console.log(` agent: ${agentName}`);
|
|
20385
20681
|
console.log(` state: ${stateDir}`);
|
|
20386
20682
|
console.log(` workspace: ${workspace}`);
|
|
20387
|
-
if (!
|
|
20683
|
+
if (!fs27.existsSync(workspace)) {
|
|
20388
20684
|
console.error(`\u274C workspace \u4E0D\u5B58\u5728: ${workspace}`);
|
|
20389
20685
|
process.exit(1);
|
|
20390
20686
|
}
|
|
20391
20687
|
const dirs = { workspace, stateDir, engineHome };
|
|
20392
20688
|
const wsFiles = collectFiles(workspace, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL);
|
|
20393
|
-
const sessionFiles = collectRecentSessions(
|
|
20394
|
-
const configsDir =
|
|
20689
|
+
const sessionFiles = collectRecentSessions(path29.join(stateDir, "agents"), 7);
|
|
20690
|
+
const configsDir = path29.join(stateDir, "configs");
|
|
20395
20691
|
const configFiles = [];
|
|
20396
|
-
if (
|
|
20692
|
+
if (fs27.existsSync(configsDir)) {
|
|
20397
20693
|
for (const f of collectAllFiles(configsDir)) {
|
|
20398
|
-
if (shouldExclude(
|
|
20694
|
+
if (shouldExclude(path29.basename(f))) continue;
|
|
20399
20695
|
configFiles.push(f);
|
|
20400
20696
|
}
|
|
20401
20697
|
}
|
|
20402
20698
|
const EVEROS_SKIP = /* @__PURE__ */ new Set([".tmp", ".lock", "import.log", "import_progress.json"]);
|
|
20403
|
-
const everosDir =
|
|
20699
|
+
const everosDir = path29.join(stateDir, ".everos");
|
|
20404
20700
|
const everosFiles = [];
|
|
20405
|
-
if (
|
|
20701
|
+
if (fs27.existsSync(everosDir)) {
|
|
20406
20702
|
for (const f of collectAllFiles(everosDir)) {
|
|
20407
|
-
if (EVEROS_SKIP.has(
|
|
20703
|
+
if (EVEROS_SKIP.has(path29.basename(f))) continue;
|
|
20408
20704
|
everosFiles.push(f);
|
|
20409
20705
|
}
|
|
20410
|
-
const walFile =
|
|
20411
|
-
if (
|
|
20706
|
+
const walFile = path29.join(everosDir, ".index", "sqlite", "system.db-wal");
|
|
20707
|
+
if (fs27.existsSync(walFile) && fs27.statSync(walFile).size > 0) {
|
|
20412
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`);
|
|
20413
20709
|
console.warn(` \u5EFA\u8BAE: \u5148\u505C everos \u670D\u52A1\u518D export\uFF0C\u6216 import \u540E\u91CD\u5EFA\u7D22\u5F15`);
|
|
20414
20710
|
}
|
|
@@ -20416,16 +20712,16 @@ async function doExport(opts) {
|
|
|
20416
20712
|
console.log(` workspace \u6587\u4EF6: ${wsFiles.length}`);
|
|
20417
20713
|
console.log(` session jsonl: ${sessionFiles.length} (\u6700\u8FD17\u5929)`);
|
|
20418
20714
|
console.log(` configs: ${configFiles.length}`);
|
|
20419
|
-
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)`);
|
|
20420
20716
|
if (dryRun2) {
|
|
20421
20717
|
console.log(`
|
|
20422
20718
|
[DRY RUN] \u4F1A\u6253\u5305\u4EE5\u4E0B\u6587\u4EF6:`);
|
|
20423
|
-
wsFiles.slice(0, 20).forEach((f) => console.log(` ${
|
|
20719
|
+
wsFiles.slice(0, 20).forEach((f) => console.log(` ${path29.relative(workspace, f)}`));
|
|
20424
20720
|
if (wsFiles.length > 20) console.log(` ... \u8FD8\u6709 ${wsFiles.length - 20} \u4E2A\u6587\u4EF6`);
|
|
20425
20721
|
if (everosFiles.length > 0) {
|
|
20426
20722
|
console.log(`
|
|
20427
20723
|
[DRY RUN] everos (${everosFiles.length} \u6587\u4EF6):`);
|
|
20428
|
-
everosFiles.slice(0, 10).forEach((f) => console.log(` ${
|
|
20724
|
+
everosFiles.slice(0, 10).forEach((f) => console.log(` ${path29.relative(stateDir, f)}`));
|
|
20429
20725
|
if (everosFiles.length > 10) console.log(` ... \u8FD8\u6709 ${everosFiles.length - 10} \u4E2A\u6587\u4EF6`);
|
|
20430
20726
|
}
|
|
20431
20727
|
console.log(`
|
|
@@ -20434,46 +20730,46 @@ async function doExport(opts) {
|
|
|
20434
20730
|
}
|
|
20435
20731
|
const now = /* @__PURE__ */ new Date();
|
|
20436
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")}`;
|
|
20437
|
-
const tmpDir =
|
|
20438
|
-
|
|
20439
|
-
const stagingDir =
|
|
20440
|
-
|
|
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 });
|
|
20441
20737
|
let fileCount = 0;
|
|
20442
20738
|
let totalSize = 0;
|
|
20443
20739
|
let copyFail = 0;
|
|
20444
20740
|
const copyOne = (srcFile, relRoot, destRoot) => {
|
|
20445
|
-
const relPath =
|
|
20446
|
-
const destFile =
|
|
20447
|
-
|
|
20741
|
+
const relPath = path29.relative(relRoot, srcFile);
|
|
20742
|
+
const destFile = path29.join(destRoot, relPath);
|
|
20743
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20448
20744
|
try {
|
|
20449
20745
|
if (isTextFile(srcFile)) {
|
|
20450
|
-
const content =
|
|
20451
|
-
|
|
20746
|
+
const content = fs27.readFileSync(srcFile, "utf-8");
|
|
20747
|
+
fs27.writeFileSync(destFile, sanitizeContent(content, dirs));
|
|
20452
20748
|
} else {
|
|
20453
|
-
|
|
20749
|
+
fs27.copyFileSync(srcFile, destFile);
|
|
20454
20750
|
}
|
|
20455
20751
|
fileCount++;
|
|
20456
|
-
totalSize +=
|
|
20752
|
+
totalSize += fs27.statSync(srcFile).size;
|
|
20457
20753
|
} catch (e) {
|
|
20458
20754
|
copyFail++;
|
|
20459
20755
|
console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
|
|
20460
20756
|
}
|
|
20461
20757
|
};
|
|
20462
|
-
for (const srcFile of wsFiles) copyOne(srcFile, workspace,
|
|
20758
|
+
for (const srcFile of wsFiles) copyOne(srcFile, workspace, path29.join(stagingDir, "workspace"));
|
|
20463
20759
|
for (const srcFile of sessionFiles) {
|
|
20464
|
-
const relPath =
|
|
20465
|
-
const destFile =
|
|
20466
|
-
|
|
20760
|
+
const relPath = path29.relative(stateDir, srcFile);
|
|
20761
|
+
const destFile = path29.join(stagingDir, relPath);
|
|
20762
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20467
20763
|
try {
|
|
20468
|
-
let content =
|
|
20764
|
+
let content = fs27.readFileSync(srcFile, "utf-8");
|
|
20469
20765
|
content = sanitizeContent(content, dirs);
|
|
20470
|
-
const baseName =
|
|
20766
|
+
const baseName = path29.basename(srcFile);
|
|
20471
20767
|
if (baseName === "session-index.json" || baseName === "platform-map.json") {
|
|
20472
20768
|
content = content.split("\\\\").join("/");
|
|
20473
20769
|
}
|
|
20474
|
-
|
|
20770
|
+
fs27.writeFileSync(destFile, content);
|
|
20475
20771
|
fileCount++;
|
|
20476
|
-
totalSize +=
|
|
20772
|
+
totalSize += fs27.statSync(srcFile).size;
|
|
20477
20773
|
} catch (e) {
|
|
20478
20774
|
copyFail++;
|
|
20479
20775
|
console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
|
|
@@ -20495,13 +20791,13 @@ async function doExport(opts) {
|
|
|
20495
20791
|
totalSize,
|
|
20496
20792
|
note
|
|
20497
20793
|
};
|
|
20498
|
-
|
|
20499
|
-
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`);
|
|
20500
20796
|
console.log(`
|
|
20501
20797
|
\u{1F5DC}\uFE0F \u6253\u5305\u4E2D...`);
|
|
20502
20798
|
const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
|
|
20503
20799
|
execSync2(`"${tarExe}" -czf "${archiveFile}" -C "${tmpDir}" ${agentName}`, { stdio: "pipe" });
|
|
20504
|
-
const archiveSize =
|
|
20800
|
+
const archiveSize = fs27.statSync(archiveFile).size;
|
|
20505
20801
|
console.log(`\u2705 \u6253\u5305\u5B8C\u6210: ${archiveFile} (${(archiveSize / 1024 / 1024).toFixed(1)} MB, ${fileCount} \u6587\u4EF6${copyFail ? `, \u5931\u8D25 ${copyFail}` : ""})`);
|
|
20506
20802
|
const cfg = loadTravelConfig();
|
|
20507
20803
|
if (!cfg || !cfg.githubToken) {
|
|
@@ -20524,8 +20820,8 @@ async function doImport(opts) {
|
|
|
20524
20820
|
console.error(` \u914D\u7F6E: \u7F16\u8F91 ${CONFIG_PATH}`);
|
|
20525
20821
|
process.exit(1);
|
|
20526
20822
|
}
|
|
20527
|
-
const tmpDir =
|
|
20528
|
-
|
|
20823
|
+
const tmpDir = path29.join(os4.tmpdir(), `engine7-import-${agentName}-${Date.now()}`);
|
|
20824
|
+
fs27.mkdirSync(tmpDir, { recursive: true });
|
|
20529
20825
|
const archiveFile = await downloadFromGitHub(cfg, agentName, version, tmpDir);
|
|
20530
20826
|
console.log(`\u2705 \u4E0B\u8F7D\u5B8C\u6210: ${archiveFile}`);
|
|
20531
20827
|
if (dryRun2) {
|
|
@@ -20536,99 +20832,99 @@ async function doImport(opts) {
|
|
|
20536
20832
|
console.log(`\u{1F4C2} \u89E3\u5305\u4E2D...`);
|
|
20537
20833
|
const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
|
|
20538
20834
|
execSync2(`"${tarExe}" -xzf "${archiveFile}" -C "${tmpDir}"`, { stdio: "pipe" });
|
|
20539
|
-
const stagingDir =
|
|
20540
|
-
const manifestPath =
|
|
20541
|
-
if (!
|
|
20835
|
+
const stagingDir = path29.join(tmpDir, agentName);
|
|
20836
|
+
const manifestPath = path29.join(stagingDir, "manifest.json");
|
|
20837
|
+
if (!fs27.existsSync(manifestPath)) {
|
|
20542
20838
|
console.error(`\u274C manifest.json \u4E0D\u5B58\u5728\uFF0C\u6587\u4EF6\u53EF\u80FD\u635F\u574F`);
|
|
20543
20839
|
process.exit(1);
|
|
20544
20840
|
}
|
|
20545
|
-
const manifest = JSON.parse(
|
|
20546
|
-
const workspace =
|
|
20547
|
-
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(/[/\\]+$/, "");
|
|
20548
20844
|
const dirs = { workspace, stateDir: stateDir.replace(/\\/g, "/").replace(/[/\\]+$/, ""), engineHome };
|
|
20549
20845
|
console.log(` \u7248\u672C: ${manifest.version}`);
|
|
20550
20846
|
console.log(` \u521B\u5EFA: ${manifest.createdAt}`);
|
|
20551
20847
|
console.log(` \u6587\u4EF6\u6570: ${manifest.fileCount}`);
|
|
20552
|
-
const wsStaging =
|
|
20848
|
+
const wsStaging = path29.join(stagingDir, "workspace");
|
|
20553
20849
|
let restoredCount = 0;
|
|
20554
20850
|
let skipCount = 0;
|
|
20555
|
-
if (
|
|
20851
|
+
if (fs27.existsSync(wsStaging)) {
|
|
20556
20852
|
const allFiles = collectAllFiles(wsStaging);
|
|
20557
20853
|
for (const srcFile of allFiles) {
|
|
20558
|
-
const relPath =
|
|
20559
|
-
const destFile =
|
|
20560
|
-
|
|
20854
|
+
const relPath = path29.relative(wsStaging, srcFile);
|
|
20855
|
+
const destFile = path29.join(workspace, relPath);
|
|
20856
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20561
20857
|
try {
|
|
20562
20858
|
if (isTextFile(srcFile)) {
|
|
20563
|
-
const content =
|
|
20564
|
-
|
|
20859
|
+
const content = fs27.readFileSync(srcFile, "utf-8");
|
|
20860
|
+
fs27.writeFileSync(destFile, restoreContent(content, dirs));
|
|
20565
20861
|
} else {
|
|
20566
|
-
|
|
20862
|
+
fs27.copyFileSync(srcFile, destFile);
|
|
20567
20863
|
}
|
|
20568
20864
|
restoredCount++;
|
|
20569
20865
|
} catch (e) {
|
|
20570
20866
|
skipCount++;
|
|
20571
|
-
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${
|
|
20867
|
+
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path29.relative(wsStaging, srcFile)} (${e.code || e.message})`);
|
|
20572
20868
|
}
|
|
20573
20869
|
}
|
|
20574
20870
|
}
|
|
20575
|
-
const agentsStaging =
|
|
20576
|
-
if (
|
|
20871
|
+
const agentsStaging = path29.join(stagingDir, "agents");
|
|
20872
|
+
if (fs27.existsSync(agentsStaging)) {
|
|
20577
20873
|
const sessionFiles = collectAllFiles(agentsStaging);
|
|
20578
20874
|
for (const srcFile of sessionFiles) {
|
|
20579
|
-
const relPath =
|
|
20580
|
-
const destFile =
|
|
20581
|
-
|
|
20582
|
-
const content =
|
|
20583
|
-
|
|
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));
|
|
20584
20880
|
restoredCount++;
|
|
20585
20881
|
}
|
|
20586
20882
|
}
|
|
20587
|
-
const configsStaging =
|
|
20588
|
-
if (
|
|
20883
|
+
const configsStaging = path29.join(stagingDir, "configs");
|
|
20884
|
+
if (fs27.existsSync(configsStaging)) {
|
|
20589
20885
|
const cfgFiles = collectAllFiles(configsStaging);
|
|
20590
20886
|
for (const srcFile of cfgFiles) {
|
|
20591
|
-
const relPath =
|
|
20592
|
-
const destFile =
|
|
20593
|
-
|
|
20887
|
+
const relPath = path29.relative(stagingDir, srcFile);
|
|
20888
|
+
const destFile = path29.join(stateDir, relPath);
|
|
20889
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20594
20890
|
if (isTextFile(srcFile)) {
|
|
20595
|
-
const content =
|
|
20596
|
-
|
|
20891
|
+
const content = fs27.readFileSync(srcFile, "utf-8");
|
|
20892
|
+
fs27.writeFileSync(destFile, restoreContent(content, dirs));
|
|
20597
20893
|
} else {
|
|
20598
|
-
|
|
20894
|
+
fs27.copyFileSync(srcFile, destFile);
|
|
20599
20895
|
}
|
|
20600
20896
|
restoredCount++;
|
|
20601
20897
|
}
|
|
20602
20898
|
}
|
|
20603
|
-
const everosStaging =
|
|
20604
|
-
if (
|
|
20899
|
+
const everosStaging = path29.join(stagingDir, ".everos");
|
|
20900
|
+
if (fs27.existsSync(everosStaging)) {
|
|
20605
20901
|
const everosFiles = collectAllFiles(everosStaging);
|
|
20606
20902
|
for (const srcFile of everosFiles) {
|
|
20607
|
-
const relPath =
|
|
20608
|
-
const destFile =
|
|
20609
|
-
|
|
20903
|
+
const relPath = path29.relative(stagingDir, srcFile);
|
|
20904
|
+
const destFile = path29.join(stateDir, relPath);
|
|
20905
|
+
fs27.mkdirSync(path29.dirname(destFile), { recursive: true });
|
|
20610
20906
|
try {
|
|
20611
20907
|
if (isTextFile(srcFile)) {
|
|
20612
|
-
const content =
|
|
20613
|
-
|
|
20908
|
+
const content = fs27.readFileSync(srcFile, "utf-8");
|
|
20909
|
+
fs27.writeFileSync(destFile, restoreContent(content, dirs));
|
|
20614
20910
|
} else {
|
|
20615
|
-
|
|
20911
|
+
fs27.copyFileSync(srcFile, destFile);
|
|
20616
20912
|
}
|
|
20617
20913
|
restoredCount++;
|
|
20618
20914
|
} catch (e) {
|
|
20619
20915
|
skipCount++;
|
|
20620
|
-
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${
|
|
20916
|
+
console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path29.relative(everosStaging, srcFile)} (${e.code || e.message})`);
|
|
20621
20917
|
}
|
|
20622
20918
|
}
|
|
20623
20919
|
console.log(` everos: ${everosFiles.length} \u6587\u4EF6\u5DF2\u6062\u590D`);
|
|
20624
20920
|
}
|
|
20625
20921
|
console.log(`\u2705 \u6062\u590D\u5B8C\u6210: ${restoredCount} \u6587\u4EF6 \u2192 ${stateDir}${skipCount ? ` (\u8DF3\u8FC7 ${skipCount})` : ""}`);
|
|
20626
20922
|
const platformConfigName = process.platform === "darwin" ? "xiaoke-mac.json" : "xiaoke-win.json";
|
|
20627
|
-
const restoredConfigPath =
|
|
20628
|
-
const configToUse =
|
|
20923
|
+
const restoredConfigPath = path29.join(stateDir, "configs", platformConfigName);
|
|
20924
|
+
const configToUse = fs27.existsSync(restoredConfigPath) ? restoredConfigPath : path29.join(stateDir, "configs", "xiaoke.json");
|
|
20629
20925
|
console.log(`
|
|
20630
20926
|
\u{1F4A1} \u4E0B\u4E00\u6B65: engine7 start --config "${configToUse}"`);
|
|
20631
|
-
|
|
20927
|
+
fs27.rmSync(tmpDir, { recursive: true, force: true });
|
|
20632
20928
|
}
|
|
20633
20929
|
async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
|
|
20634
20930
|
const repo = `${cfg.githubOwner}/${cfg.repoName}`;
|
|
@@ -20658,8 +20954,8 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
|
|
|
20658
20954
|
}
|
|
20659
20955
|
const release2 = await createRes.json();
|
|
20660
20956
|
const uploadUrl = release2.upload_url.replace("{?name,label}", "");
|
|
20661
|
-
const fileBuffer =
|
|
20662
|
-
const fileName =
|
|
20957
|
+
const fileBuffer = fs27.readFileSync(archiveFile);
|
|
20958
|
+
const fileName = path29.basename(archiveFile);
|
|
20663
20959
|
const uploadRes = await fetch(`${uploadUrl}?name=${fileName}`, {
|
|
20664
20960
|
method: "POST",
|
|
20665
20961
|
headers: {
|
|
@@ -20682,7 +20978,7 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
|
|
|
20682
20978
|
throw e;
|
|
20683
20979
|
}
|
|
20684
20980
|
try {
|
|
20685
|
-
|
|
20981
|
+
fs27.rmSync(path29.dirname(archiveFile), { recursive: true, force: true });
|
|
20686
20982
|
} catch {
|
|
20687
20983
|
}
|
|
20688
20984
|
}
|
|
@@ -20714,8 +21010,8 @@ async function downloadFromGitHub(cfg, agentName, version, destDir) {
|
|
|
20714
21010
|
throw new Error(`\u4E0B\u8F7D asset \u5931\u8D25: ${downloadRes.status}`);
|
|
20715
21011
|
}
|
|
20716
21012
|
const buffer = Buffer.from(await downloadRes.arrayBuffer());
|
|
20717
|
-
const archiveFile =
|
|
20718
|
-
|
|
21013
|
+
const archiveFile = path29.join(destDir, asset.name);
|
|
21014
|
+
fs27.writeFileSync(archiveFile, buffer);
|
|
20719
21015
|
return archiveFile;
|
|
20720
21016
|
}
|
|
20721
21017
|
async function getLatestReleaseTag(cfg, agentName) {
|
|
@@ -20740,7 +21036,7 @@ var CONFIG_PATH, PATH_PLACEHOLDERS, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL, WORKS
|
|
|
20740
21036
|
var init_cli_travel = __esm({
|
|
20741
21037
|
"src/cli-travel.ts"() {
|
|
20742
21038
|
"use strict";
|
|
20743
|
-
CONFIG_PATH =
|
|
21039
|
+
CONFIG_PATH = path29.join(os4.homedir(), ".engine7-travel.json");
|
|
20744
21040
|
PATH_PLACEHOLDERS = [
|
|
20745
21041
|
{ placeholder: "{{WORKSPACE}}", getOriginal: (d) => d.workspace },
|
|
20746
21042
|
{ placeholder: "{{ENGINE_HOME}}", getOriginal: (d) => d.engineHome },
|
|
@@ -20816,8 +21112,8 @@ var init_cli_travel = __esm({
|
|
|
20816
21112
|
init_feishu_quick_register();
|
|
20817
21113
|
init_wechat();
|
|
20818
21114
|
init_qr_render();
|
|
20819
|
-
import * as
|
|
20820
|
-
import * as
|
|
21115
|
+
import * as path30 from "node:path";
|
|
21116
|
+
import * as fs28 from "node:fs";
|
|
20821
21117
|
import * as readline3 from "node:readline";
|
|
20822
21118
|
import { fileURLToPath } from "node:url";
|
|
20823
21119
|
var origEmitWarning = process.emitWarning.bind(process);
|
|
@@ -20828,7 +21124,7 @@ process.emitWarning = (warning, ...rest) => {
|
|
|
20828
21124
|
return origEmitWarning(warning, ...rest);
|
|
20829
21125
|
};
|
|
20830
21126
|
var __filename = fileURLToPath(import.meta.url);
|
|
20831
|
-
var __dirname =
|
|
21127
|
+
var __dirname = path30.dirname(__filename);
|
|
20832
21128
|
var SCHEMA_VERSION = 1;
|
|
20833
21129
|
function parseArgs() {
|
|
20834
21130
|
const args = process.argv.slice(2);
|
|
@@ -20853,10 +21149,10 @@ function parseArgs() {
|
|
|
20853
21149
|
}
|
|
20854
21150
|
}
|
|
20855
21151
|
if (!stateDir) {
|
|
20856
|
-
stateDir =
|
|
21152
|
+
stateDir = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
20857
21153
|
console.log(` \u4F7F\u7528\u9ED8\u8BA4\u76EE\u5F55: ${stateDir}`);
|
|
20858
21154
|
}
|
|
20859
|
-
stateDir =
|
|
21155
|
+
stateDir = path30.resolve(stateDir);
|
|
20860
21156
|
return { stateDir, quick, dryRun: dryRun2, force };
|
|
20861
21157
|
}
|
|
20862
21158
|
function printHelp() {
|
|
@@ -20957,10 +21253,10 @@ function getDefaultValues(stateDir) {
|
|
|
20957
21253
|
};
|
|
20958
21254
|
}
|
|
20959
21255
|
function loadExistingValues(stateDir) {
|
|
20960
|
-
const configPath =
|
|
21256
|
+
const configPath = path30.join(stateDir, "configs", "main7.json");
|
|
20961
21257
|
try {
|
|
20962
|
-
if (!
|
|
20963
|
-
const j = JSON.parse(
|
|
21258
|
+
if (!fs28.existsSync(configPath)) return {};
|
|
21259
|
+
const j = JSON.parse(fs28.readFileSync(configPath, "utf8"));
|
|
20964
21260
|
const out = {};
|
|
20965
21261
|
if (j.agents?.defaults?.name) out.agentName = j.agents.defaults.name;
|
|
20966
21262
|
const providers = j.models?.providers || {};
|
|
@@ -21015,15 +21311,15 @@ function loadExistingValues(stateDir) {
|
|
|
21015
21311
|
}
|
|
21016
21312
|
function readSecretsValue(stateDir, envName) {
|
|
21017
21313
|
try {
|
|
21018
|
-
const secretsDir =
|
|
21019
|
-
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);
|
|
21020
21316
|
const candidates = [
|
|
21021
|
-
|
|
21022
|
-
|
|
21317
|
+
path30.join(secretsDir, `${cfgBase}.env`),
|
|
21318
|
+
path30.join(stateDir, "configs", `.env.${cfgBase}`)
|
|
21023
21319
|
];
|
|
21024
21320
|
for (const p of candidates) {
|
|
21025
|
-
if (
|
|
21026
|
-
for (const line of
|
|
21321
|
+
if (fs28.existsSync(p)) {
|
|
21322
|
+
for (const line of fs28.readFileSync(p, "utf8").split("\n")) {
|
|
21027
21323
|
const eq = line.indexOf("=");
|
|
21028
21324
|
if (eq > 0 && line.slice(0, eq).trim() === envName) {
|
|
21029
21325
|
return line.slice(eq + 1).trim();
|
|
@@ -21249,7 +21545,7 @@ async function configureWechat(rl, v) {
|
|
|
21249
21545
|
}
|
|
21250
21546
|
}
|
|
21251
21547
|
function generateConfig(v) {
|
|
21252
|
-
const workspace =
|
|
21548
|
+
const workspace = path30.join(v.stateDir, "workspace").replace(/\\/g, "/");
|
|
21253
21549
|
const config = {
|
|
21254
21550
|
schemaVersion: SCHEMA_VERSION,
|
|
21255
21551
|
stateDir: v.stateDir.replace(/\\/g, "/"),
|
|
@@ -21399,45 +21695,45 @@ function generateConfig(v) {
|
|
|
21399
21695
|
}
|
|
21400
21696
|
function buildDirTree(v) {
|
|
21401
21697
|
const d = v.stateDir;
|
|
21402
|
-
const w =
|
|
21698
|
+
const w = path30.join(d, "workspace");
|
|
21403
21699
|
const now = (/* @__PURE__ */ new Date()).toLocaleString("sv-SE", { timeZone: "Asia/Shanghai", hour12: false });
|
|
21404
21700
|
return [
|
|
21405
21701
|
// 目录
|
|
21406
|
-
{ path:
|
|
21407
|
-
{ path:
|
|
21408
|
-
{ path:
|
|
21409
|
-
{ path:
|
|
21410
|
-
{ path:
|
|
21411
|
-
{ path:
|
|
21412
|
-
{ path:
|
|
21413
|
-
{ path:
|
|
21414
|
-
{ path:
|
|
21415
|
-
{ path:
|
|
21416
|
-
{ 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" },
|
|
21417
21713
|
// workspace 文件
|
|
21418
21714
|
{
|
|
21419
|
-
path:
|
|
21715
|
+
path: path30.join(w, "SESSION-STATE.md"),
|
|
21420
21716
|
type: "file",
|
|
21421
21717
|
content: readTemplate("workspace/SESSION-STATE.md").replace("{{CURRENT_TIME}}", now)
|
|
21422
21718
|
},
|
|
21423
|
-
{ path:
|
|
21719
|
+
{ path: path30.join(w, "HEARTBEAT.md"), type: "file", content: readTemplate("workspace/HEARTBEAT.md") },
|
|
21424
21720
|
{
|
|
21425
|
-
path:
|
|
21721
|
+
path: path30.join(w, "SOUL.md"),
|
|
21426
21722
|
type: "file",
|
|
21427
21723
|
content: readTemplate("workspace/SOUL.md").replace(/\{\{AGENT_NAME\}\}/g, v.agentName)
|
|
21428
21724
|
},
|
|
21429
|
-
{ path:
|
|
21725
|
+
{ path: path30.join(w, "AGENTS.md"), type: "file", content: readTemplate("workspace/AGENTS.md") },
|
|
21430
21726
|
{
|
|
21431
|
-
path:
|
|
21727
|
+
path: path30.join(w, "prompts", "contacts.md"),
|
|
21432
21728
|
type: "file",
|
|
21433
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")
|
|
21434
21730
|
},
|
|
21435
|
-
{ path:
|
|
21436
|
-
{ path:
|
|
21437
|
-
{ 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" },
|
|
21438
21734
|
// package.json — 让 agent 目录成为独立 npm 项目根,防止 npm hoisting
|
|
21439
21735
|
{
|
|
21440
|
-
path:
|
|
21736
|
+
path: path30.join(d, "package.json"),
|
|
21441
21737
|
type: "file",
|
|
21442
21738
|
content: JSON.stringify({
|
|
21443
21739
|
name: v.agentName.toLowerCase().replace(/[^a-z0-9-]/g, "-") || "agent",
|
|
@@ -21448,7 +21744,7 @@ function buildDirTree(v) {
|
|
|
21448
21744
|
},
|
|
21449
21745
|
// 启动脚本(根据 OS 生成)
|
|
21450
21746
|
...process.platform === "win32" ? [{
|
|
21451
|
-
path:
|
|
21747
|
+
path: path30.join(d, "start.cmd"),
|
|
21452
21748
|
type: "file",
|
|
21453
21749
|
content: `@echo off
|
|
21454
21750
|
rem Engine 7 startup script
|
|
@@ -21480,7 +21776,7 @@ if %ERRORLEVEL% NEQ 0 (
|
|
|
21480
21776
|
)
|
|
21481
21777
|
`
|
|
21482
21778
|
}] : [{
|
|
21483
|
-
path:
|
|
21779
|
+
path: path30.join(d, "start.sh"),
|
|
21484
21780
|
type: "file",
|
|
21485
21781
|
content: `#!/bin/bash
|
|
21486
21782
|
# Engine 7 startup script
|
|
@@ -21513,13 +21809,13 @@ node "$ENGINE7_BIN" --engine-config configs/main7.json
|
|
|
21513
21809
|
}
|
|
21514
21810
|
function readTemplate(relativePath) {
|
|
21515
21811
|
const candidates = [
|
|
21516
|
-
|
|
21517
|
-
|
|
21518
|
-
|
|
21812
|
+
path30.join(__dirname, "..", "templates", relativePath),
|
|
21813
|
+
path30.join(__dirname, "..", "..", "templates", relativePath),
|
|
21814
|
+
path30.join(process.cwd(), "templates", relativePath)
|
|
21519
21815
|
];
|
|
21520
21816
|
for (const p of candidates) {
|
|
21521
|
-
if (
|
|
21522
|
-
return
|
|
21817
|
+
if (fs28.existsSync(p)) {
|
|
21818
|
+
return fs28.readFileSync(p, "utf-8");
|
|
21523
21819
|
}
|
|
21524
21820
|
}
|
|
21525
21821
|
throw new Error(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${relativePath}\uFF08\u627E\u4E86: ${candidates.join(", ")}\uFF09`);
|
|
@@ -21534,11 +21830,11 @@ function dryRun(entries2) {
|
|
|
21534
21830
|
function execute(entries2) {
|
|
21535
21831
|
for (const e of entries2) {
|
|
21536
21832
|
if (e.type === "dir") {
|
|
21537
|
-
|
|
21833
|
+
fs28.mkdirSync(e.path, { recursive: true });
|
|
21538
21834
|
console.log(` \u{1F4C1} ${e.path}`);
|
|
21539
21835
|
} else {
|
|
21540
|
-
|
|
21541
|
-
|
|
21836
|
+
fs28.mkdirSync(path30.dirname(e.path), { recursive: true });
|
|
21837
|
+
fs28.writeFileSync(e.path, e.content || "", "utf-8");
|
|
21542
21838
|
console.log(` \u{1F4C4} ${e.path}`);
|
|
21543
21839
|
}
|
|
21544
21840
|
}
|
|
@@ -21572,8 +21868,8 @@ async function main() {
|
|
|
21572
21868
|
if (subcommand === "--version" || subcommand === "-v") {
|
|
21573
21869
|
let ver = "unknown";
|
|
21574
21870
|
try {
|
|
21575
|
-
const pkgPath =
|
|
21576
|
-
ver = JSON.parse(
|
|
21871
|
+
const pkgPath = path30.join(path30.dirname(__filename), "..", "package.json");
|
|
21872
|
+
ver = JSON.parse(fs28.readFileSync(pkgPath, "utf8")).version || "unknown";
|
|
21577
21873
|
} catch {
|
|
21578
21874
|
}
|
|
21579
21875
|
console.log(`engine7 ${ver}`);
|
|
@@ -21591,18 +21887,18 @@ async function main() {
|
|
|
21591
21887
|
else if (args[i] === "--config" && args[i + 1]) configName = args[++i].trim();
|
|
21592
21888
|
}
|
|
21593
21889
|
if (!stateDir) {
|
|
21594
|
-
const cwd =
|
|
21595
|
-
if (
|
|
21890
|
+
const cwd = path30.resolve(process.cwd());
|
|
21891
|
+
if (fs28.existsSync(path30.join(cwd, "configs"))) {
|
|
21596
21892
|
stateDir = cwd;
|
|
21597
21893
|
} else {
|
|
21598
|
-
const pointer =
|
|
21599
|
-
if (
|
|
21894
|
+
const pointer = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
|
|
21895
|
+
if (fs28.existsSync(pointer)) {
|
|
21600
21896
|
try {
|
|
21601
|
-
stateDir = JSON.parse(
|
|
21897
|
+
stateDir = JSON.parse(fs28.readFileSync(pointer, "utf8")).stateDir || "";
|
|
21602
21898
|
} catch {
|
|
21603
21899
|
}
|
|
21604
21900
|
}
|
|
21605
|
-
if (!stateDir) stateDir =
|
|
21901
|
+
if (!stateDir) stateDir = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
21606
21902
|
}
|
|
21607
21903
|
}
|
|
21608
21904
|
if (!target && !isLegacyAddchannel) {
|
|
@@ -21622,12 +21918,12 @@ async function main() {
|
|
|
21622
21918
|
process.exit(0);
|
|
21623
21919
|
}
|
|
21624
21920
|
if (channel === "channels") {
|
|
21625
|
-
const configsDir =
|
|
21626
|
-
if (
|
|
21627
|
-
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"));
|
|
21628
21924
|
for (const f of files) {
|
|
21629
21925
|
try {
|
|
21630
|
-
const j = JSON.parse(
|
|
21926
|
+
const j = JSON.parse(fs28.readFileSync(path30.join(configsDir, f), "utf8"));
|
|
21631
21927
|
if (!j.channels) continue;
|
|
21632
21928
|
console.log(`
|
|
21633
21929
|
\u{1F4C4} ${f}:`);
|
|
@@ -21673,14 +21969,14 @@ async function main() {
|
|
|
21673
21969
|
console.error("\u274C \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25");
|
|
21674
21970
|
process.exit(1);
|
|
21675
21971
|
}
|
|
21676
|
-
const configsDir2 =
|
|
21677
|
-
let configFile2 = configName ?
|
|
21678
|
-
if (!configFile2 || !
|
|
21679
|
-
if (
|
|
21680
|
-
for (const f of
|
|
21681
|
-
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);
|
|
21682
21978
|
try {
|
|
21683
|
-
if (JSON.parse(
|
|
21979
|
+
if (JSON.parse(fs28.readFileSync(full, "utf8")).channels) {
|
|
21684
21980
|
configFile2 = full;
|
|
21685
21981
|
break;
|
|
21686
21982
|
}
|
|
@@ -21689,11 +21985,11 @@ async function main() {
|
|
|
21689
21985
|
}
|
|
21690
21986
|
}
|
|
21691
21987
|
}
|
|
21692
|
-
if (configFile2 &&
|
|
21693
|
-
const j = JSON.parse(
|
|
21988
|
+
if (configFile2 && fs28.existsSync(configFile2)) {
|
|
21989
|
+
const j = JSON.parse(fs28.readFileSync(configFile2, "utf8"));
|
|
21694
21990
|
j.channels = j.channels || {};
|
|
21695
21991
|
j.channels.feishu = { enabled: true, appId: result2.appId, appSecret: result2.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" };
|
|
21696
|
-
|
|
21992
|
+
fs28.writeFileSync(configFile2, JSON.stringify(j, null, 2), "utf8");
|
|
21697
21993
|
console.log("\u2705 \u98DE\u4E66\u901A\u9053\u5DF2\u5199\u5165: " + configFile2);
|
|
21698
21994
|
console.log("\u91CD\u542F\u751F\u6548: engine7 restart");
|
|
21699
21995
|
} else {
|
|
@@ -21711,16 +22007,16 @@ async function main() {
|
|
|
21711
22007
|
console.error("\u274C \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25\uFF0C\u672A\u4FEE\u6539\u4EFB\u4F55\u914D\u7F6E");
|
|
21712
22008
|
process.exit(1);
|
|
21713
22009
|
}
|
|
21714
|
-
const configsDir =
|
|
22010
|
+
const configsDir = path30.join(stateDir, "configs");
|
|
21715
22011
|
let configFile = "";
|
|
21716
22012
|
if (configName) {
|
|
21717
|
-
configFile =
|
|
21718
|
-
} else if (
|
|
21719
|
-
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"));
|
|
21720
22016
|
for (const f of candidates) {
|
|
21721
|
-
const full =
|
|
22017
|
+
const full = path30.join(configsDir, f);
|
|
21722
22018
|
try {
|
|
21723
|
-
const j2 = JSON.parse(
|
|
22019
|
+
const j2 = JSON.parse(fs28.readFileSync(full, "utf8"));
|
|
21724
22020
|
if (j2.channels) {
|
|
21725
22021
|
configFile = full;
|
|
21726
22022
|
break;
|
|
@@ -21728,14 +22024,14 @@ async function main() {
|
|
|
21728
22024
|
} catch {
|
|
21729
22025
|
}
|
|
21730
22026
|
}
|
|
21731
|
-
if (!configFile && candidates.length) configFile =
|
|
22027
|
+
if (!configFile && candidates.length) configFile = path30.join(configsDir, candidates[0]);
|
|
21732
22028
|
}
|
|
21733
|
-
if (!configFile || !
|
|
22029
|
+
if (!configFile || !fs28.existsSync(configFile)) {
|
|
21734
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");
|
|
21735
22031
|
console.log(JSON.stringify({ wechat: { enabled: true, token: cred.token, accountId: cred.accountId, dmPolicy: "pairing", group: { policy: "disabled" } } }, null, 2));
|
|
21736
22032
|
process.exit(0);
|
|
21737
22033
|
}
|
|
21738
|
-
const j = JSON.parse(
|
|
22034
|
+
const j = JSON.parse(fs28.readFileSync(configFile, "utf8"));
|
|
21739
22035
|
j.channels = j.channels || {};
|
|
21740
22036
|
j.channels.wechat = {
|
|
21741
22037
|
enabled: true,
|
|
@@ -21744,7 +22040,7 @@ async function main() {
|
|
|
21744
22040
|
dmPolicy: "pairing",
|
|
21745
22041
|
group: { policy: "disabled" }
|
|
21746
22042
|
};
|
|
21747
|
-
|
|
22043
|
+
fs28.writeFileSync(configFile, JSON.stringify(j, null, 2), "utf8");
|
|
21748
22044
|
console.log(`
|
|
21749
22045
|
\u2705 \u5FAE\u4FE1\u901A\u9053\u5DF2\u5199\u5165: ${configFile}`);
|
|
21750
22046
|
console.log(` accountId: ${cred.accountId}`);
|
|
@@ -21772,8 +22068,8 @@ async function main() {
|
|
|
21772
22068
|
else if (args[i] === "--note" && args[i + 1]) note = args[++i];
|
|
21773
22069
|
else if (args[i] === "--dry-run") dryRun2 = true;
|
|
21774
22070
|
}
|
|
21775
|
-
if (!exportStateDir) exportStateDir =
|
|
21776
|
-
if (!agentName) agentName =
|
|
22071
|
+
if (!exportStateDir) exportStateDir = path30.resolve(process.cwd());
|
|
22072
|
+
if (!agentName) agentName = path30.basename(exportStateDir);
|
|
21777
22073
|
await doExport2({ agentName, stateDir: exportStateDir, note, dryRun: dryRun2 });
|
|
21778
22074
|
process.exit(0);
|
|
21779
22075
|
}
|
|
@@ -21793,7 +22089,7 @@ async function main() {
|
|
|
21793
22089
|
console.error("\u274C import \u9700\u8981 --state-dir <path>");
|
|
21794
22090
|
process.exit(1);
|
|
21795
22091
|
}
|
|
21796
|
-
if (!agentName) agentName =
|
|
22092
|
+
if (!agentName) agentName = path30.basename(importStateDir);
|
|
21797
22093
|
await doImport2({ agentName, stateDir: importStateDir, version, dryRun: dryRun2 });
|
|
21798
22094
|
process.exit(0);
|
|
21799
22095
|
}
|
|
@@ -21818,18 +22114,18 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
21818
22114
|
}
|
|
21819
22115
|
}
|
|
21820
22116
|
if (!configPath2) {
|
|
21821
|
-
const defaultCfg =
|
|
21822
|
-
const homeCfg =
|
|
21823
|
-
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)) {
|
|
21824
22120
|
configPath2 = defaultCfg;
|
|
21825
|
-
} else if (
|
|
22121
|
+
} else if (fs28.existsSync(homeCfg)) {
|
|
21826
22122
|
configPath2 = homeCfg;
|
|
21827
22123
|
console.log(` \u4F7F\u7528\u9ED8\u8BA4 config: ${homeCfg}`);
|
|
21828
22124
|
} else {
|
|
21829
22125
|
const ptr = readHomePointer();
|
|
21830
22126
|
if (ptr?.stateDir) {
|
|
21831
|
-
const ptrCfg =
|
|
21832
|
-
if (
|
|
22127
|
+
const ptrCfg = path30.join(ptr.stateDir, "configs", "main7.json");
|
|
22128
|
+
if (fs28.existsSync(ptrCfg)) {
|
|
21833
22129
|
configPath2 = ptrCfg;
|
|
21834
22130
|
console.log(` \u4F7F\u7528 config: ${ptrCfg}`);
|
|
21835
22131
|
}
|
|
@@ -21844,19 +22140,19 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
21844
22140
|
}
|
|
21845
22141
|
const { execSync: execSync3, spawn: spawn5 } = await import("node:child_process");
|
|
21846
22142
|
let enginePath;
|
|
21847
|
-
const localPath =
|
|
21848
|
-
if (
|
|
22143
|
+
const localPath = path30.join("node_modules", "engine7", "dist", "main.mjs");
|
|
22144
|
+
if (fs28.existsSync(localPath)) {
|
|
21849
22145
|
enginePath = localPath;
|
|
21850
22146
|
} else {
|
|
21851
|
-
const cliPath =
|
|
21852
|
-
const distDir =
|
|
21853
|
-
const candidate =
|
|
21854
|
-
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)) {
|
|
21855
22151
|
enginePath = candidate;
|
|
21856
22152
|
} else {
|
|
21857
22153
|
try {
|
|
21858
22154
|
const globalRoot = execSync3("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
21859
|
-
enginePath =
|
|
22155
|
+
enginePath = path30.join(globalRoot, "engine7", "dist", "main.mjs");
|
|
21860
22156
|
} catch {
|
|
21861
22157
|
console.error("\u274C \u627E\u4E0D\u5230 engine7 main.mjs");
|
|
21862
22158
|
process.exit(1);
|
|
@@ -21866,7 +22162,7 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
21866
22162
|
console.log(label);
|
|
21867
22163
|
console.log(` config: ${configPath2}`);
|
|
21868
22164
|
console.log(` engine: ${enginePath}`);
|
|
21869
|
-
const configName =
|
|
22165
|
+
const configName = path30.basename(configPath2);
|
|
21870
22166
|
const myPid = process.pid;
|
|
21871
22167
|
try {
|
|
21872
22168
|
if (process.platform === "win32") {
|
|
@@ -21884,16 +22180,16 @@ engine7 start \u2014 \u542F\u52A8 Engine
|
|
|
21884
22180
|
}
|
|
21885
22181
|
console.log("");
|
|
21886
22182
|
const envForChild = { ...process.env };
|
|
21887
|
-
const secretsDir =
|
|
21888
|
-
const cfgBase =
|
|
22183
|
+
const secretsDir = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7-secrets");
|
|
22184
|
+
const cfgBase = path30.basename(configPath2, ".json");
|
|
21889
22185
|
const secretCandidates = [
|
|
21890
|
-
|
|
21891
|
-
|
|
21892
|
-
|
|
22186
|
+
path30.join(secretsDir, `${cfgBase}.env`),
|
|
22187
|
+
path30.join(path30.dirname(configPath2), `.env.${cfgBase}`),
|
|
22188
|
+
path30.join(path30.dirname(configPath2), ".env")
|
|
21893
22189
|
];
|
|
21894
22190
|
for (const secretPath of secretCandidates) {
|
|
21895
|
-
if (
|
|
21896
|
-
const content =
|
|
22191
|
+
if (fs28.existsSync(secretPath)) {
|
|
22192
|
+
const content = fs28.readFileSync(secretPath, "utf-8");
|
|
21897
22193
|
for (const line of content.split("\n")) {
|
|
21898
22194
|
const trimmed = line.trim();
|
|
21899
22195
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -21968,14 +22264,14 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
21968
22264
|
console.error(`\u274C \u672A\u77E5\u6A21\u5F0F: ${mode}\uFF08\u53EF\u9009: archive / drop-last / strip-images\uFF09`);
|
|
21969
22265
|
process.exit(1);
|
|
21970
22266
|
}
|
|
21971
|
-
const configRaw = JSON.parse(
|
|
22267
|
+
const configRaw = JSON.parse(fs28.readFileSync(configPath2, "utf-8"));
|
|
21972
22268
|
const stateDir = configRaw.stateDir;
|
|
21973
22269
|
if (!stateDir) {
|
|
21974
22270
|
console.error("\u274C config \u91CC\u6CA1\u6709 stateDir");
|
|
21975
22271
|
process.exit(1);
|
|
21976
22272
|
}
|
|
21977
|
-
const sessionsDir =
|
|
21978
|
-
if (!
|
|
22273
|
+
const sessionsDir = path30.join(stateDir, "agents", "main", "sessions");
|
|
22274
|
+
if (!fs28.existsSync(sessionsDir)) {
|
|
21979
22275
|
console.error(`\u274C sessions \u76EE\u5F55\u4E0D\u5B58\u5728: ${sessionsDir}`);
|
|
21980
22276
|
process.exit(1);
|
|
21981
22277
|
}
|
|
@@ -21983,37 +22279,37 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
21983
22279
|
console.log(` config: ${configPath2}`);
|
|
21984
22280
|
console.log(` mode: ${mode}`);
|
|
21985
22281
|
if (mode === "drop-last") console.log(` n: ${dropN}`);
|
|
21986
|
-
const platformMapPath =
|
|
21987
|
-
const indexPath =
|
|
22282
|
+
const platformMapPath = path30.join(sessionsDir, "platform-map.json");
|
|
22283
|
+
const indexPath = path30.join(sessionsDir, "session-index.json");
|
|
21988
22284
|
let sessionFileUUID = null;
|
|
21989
|
-
if (
|
|
21990
|
-
const index = JSON.parse(
|
|
22285
|
+
if (fs28.existsSync(indexPath)) {
|
|
22286
|
+
const index = JSON.parse(fs28.readFileSync(indexPath, "utf-8"));
|
|
21991
22287
|
const entries2 = Object.values(index);
|
|
21992
22288
|
if (entries2.length > 0) {
|
|
21993
22289
|
const fileVal = entries2[0].file || "";
|
|
21994
|
-
sessionFileUUID =
|
|
22290
|
+
sessionFileUUID = path30.isAbsolute(fileVal) ? path30.basename(fileVal, ".jsonl") : fileVal.replace(".jsonl", "");
|
|
21995
22291
|
}
|
|
21996
22292
|
}
|
|
21997
22293
|
if (!sessionFileUUID) {
|
|
21998
|
-
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);
|
|
21999
22295
|
if (jsonlFiles.length === 0) {
|
|
22000
22296
|
console.error("\u274C \u627E\u4E0D\u5230\u6D3B\u8DC3\u7684 session JSONL \u6587\u4EF6");
|
|
22001
22297
|
process.exit(1);
|
|
22002
22298
|
}
|
|
22003
22299
|
sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
|
|
22004
22300
|
}
|
|
22005
|
-
let jsonlPath =
|
|
22006
|
-
if (!
|
|
22007
|
-
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);
|
|
22008
22304
|
if (jsonlFiles.length === 0) {
|
|
22009
22305
|
console.error(`\u274C JSONL \u6587\u4EF6\u4E0D\u5B58\u5728: ${jsonlPath}`);
|
|
22010
22306
|
process.exit(1);
|
|
22011
22307
|
}
|
|
22012
22308
|
sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
|
|
22013
|
-
jsonlPath =
|
|
22309
|
+
jsonlPath = path30.join(sessionsDir, `${sessionFileUUID}.jsonl`);
|
|
22014
22310
|
}
|
|
22015
22311
|
console.log(` file: ${jsonlPath}`);
|
|
22016
|
-
const configName =
|
|
22312
|
+
const configName = path30.basename(configPath2);
|
|
22017
22313
|
if (autoRestart) {
|
|
22018
22314
|
try {
|
|
22019
22315
|
const myPid = process.pid;
|
|
@@ -22029,10 +22325,10 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
22029
22325
|
}
|
|
22030
22326
|
}
|
|
22031
22327
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
22032
|
-
const { readFileSync: readFileSync29, writeFileSync: writeFileSync20, renameSync:
|
|
22328
|
+
const { readFileSync: readFileSync29, writeFileSync: writeFileSync20, renameSync: renameSync5 } = fs28;
|
|
22033
22329
|
if (mode === "archive") {
|
|
22034
22330
|
const archiveName = `${sessionFileUUID}.jsonl.archived.${timestamp}`;
|
|
22035
|
-
|
|
22331
|
+
renameSync5(jsonlPath, path30.join(sessionsDir, archiveName));
|
|
22036
22332
|
console.log(`
|
|
22037
22333
|
\u2705 \u5F52\u6863\u5B8C\u6210: ${archiveName}`);
|
|
22038
22334
|
console.log(` \u91CD\u542F\u540E\u5C06\u4ECE\u7A7A\u767D\u4F1A\u8BDD\u5F00\u59CB`);
|
|
@@ -22107,12 +22403,12 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
|
|
|
22107
22403
|
\u2705 \u6458\u9664 ${stripped} \u884C\u56FE\u7247\u76F8\u5173\u5185\u5BB9`);
|
|
22108
22404
|
}
|
|
22109
22405
|
if (autoRestart) {
|
|
22110
|
-
const realCliPath =
|
|
22111
|
-
const cliDir =
|
|
22112
|
-
const pkgRoot =
|
|
22113
|
-
let enginePath =
|
|
22114
|
-
if (!
|
|
22115
|
-
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");
|
|
22116
22412
|
}
|
|
22117
22413
|
console.log(`
|
|
22118
22414
|
\u{1F680} \u62C9\u8D77 engine...`);
|
|
@@ -22155,18 +22451,18 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
|
|
|
22155
22451
|
else if (args[i] === "--cwd" && args[i + 1]) cwd = args[++i];
|
|
22156
22452
|
}
|
|
22157
22453
|
if (!configPath2) {
|
|
22158
|
-
const defaultCfg =
|
|
22159
|
-
const homeCfg =
|
|
22160
|
-
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)) {
|
|
22161
22457
|
configPath2 = defaultCfg;
|
|
22162
|
-
} else if (
|
|
22458
|
+
} else if (fs28.existsSync(homeCfg)) {
|
|
22163
22459
|
configPath2 = homeCfg;
|
|
22164
|
-
cwd =
|
|
22460
|
+
cwd = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
|
|
22165
22461
|
} else {
|
|
22166
22462
|
const ptr = readHomePointer();
|
|
22167
22463
|
if (ptr?.stateDir) {
|
|
22168
|
-
const ptrCfg =
|
|
22169
|
-
if (
|
|
22464
|
+
const ptrCfg = path30.join(ptr.stateDir, "configs", "main7.json");
|
|
22465
|
+
if (fs28.existsSync(ptrCfg)) {
|
|
22170
22466
|
configPath2 = ptrCfg;
|
|
22171
22467
|
cwd = ptr.stateDir;
|
|
22172
22468
|
}
|
|
@@ -22185,14 +22481,14 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
|
|
|
22185
22481
|
if (process.platform === "win32") {
|
|
22186
22482
|
const taskName = "Engine7";
|
|
22187
22483
|
const nodeExe = process.execPath;
|
|
22188
|
-
const cliMjs =
|
|
22189
|
-
const absConfig =
|
|
22190
|
-
const wrapperPath =
|
|
22484
|
+
const cliMjs = path30.resolve(engine7Bin);
|
|
22485
|
+
const absConfig = path30.resolve(configPath2);
|
|
22486
|
+
const wrapperPath = path30.join(cwd, "engine7-start.cmd");
|
|
22191
22487
|
const wrapperContent = `@echo off\r
|
|
22192
22488
|
cd /d "${cwd}"\r
|
|
22193
22489
|
"${nodeExe}" "${cliMjs}" start --config "${absConfig}"\r
|
|
22194
22490
|
`;
|
|
22195
|
-
|
|
22491
|
+
fs28.writeFileSync(wrapperPath, wrapperContent);
|
|
22196
22492
|
try {
|
|
22197
22493
|
execSync3(`schtasks /create /tn "${taskName}" /tr "${wrapperPath}" /sc onlogon /rl highest /f`, { stdio: "inherit", shell: true });
|
|
22198
22494
|
console.log(`\u2705 Windows \u8BA1\u5212\u4EFB\u52A1 "${taskName}" \u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
|
|
@@ -22203,11 +22499,11 @@ cd /d "${cwd}"\r
|
|
|
22203
22499
|
}
|
|
22204
22500
|
} else if (process.platform === "darwin") {
|
|
22205
22501
|
const label = "com.engine7.agent";
|
|
22206
|
-
const plistDir =
|
|
22207
|
-
|
|
22208
|
-
const plistPath =
|
|
22209
|
-
const localCli =
|
|
22210
|
-
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");
|
|
22211
22507
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
22212
22508
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
22213
22509
|
<plist version="1.0">
|
|
@@ -22219,14 +22515,14 @@ cd /d "${cwd}"\r
|
|
|
22219
22515
|
<string>${cliMjs}</string>
|
|
22220
22516
|
<string>start</string>
|
|
22221
22517
|
<string>--config</string>
|
|
22222
|
-
<string>${
|
|
22518
|
+
<string>${path30.resolve(configPath2)}</string>
|
|
22223
22519
|
</array>
|
|
22224
22520
|
<key>WorkingDirectory</key><string>${cwd}</string>
|
|
22225
22521
|
<key>RunAtLoad</key><true/>
|
|
22226
22522
|
<key>KeepAlive</key><true/>
|
|
22227
22523
|
</dict>
|
|
22228
22524
|
</plist>`;
|
|
22229
|
-
|
|
22525
|
+
fs28.writeFileSync(plistPath, plist);
|
|
22230
22526
|
try {
|
|
22231
22527
|
execSync3(`launchctl load "${plistPath}"`, { stdio: "inherit" });
|
|
22232
22528
|
console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
|
|
@@ -22237,9 +22533,9 @@ cd /d "${cwd}"\r
|
|
|
22237
22533
|
}
|
|
22238
22534
|
} else {
|
|
22239
22535
|
const svcName = "engine7";
|
|
22240
|
-
const svcDir =
|
|
22241
|
-
|
|
22242
|
-
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`);
|
|
22243
22539
|
const svc = `[Unit]
|
|
22244
22540
|
Description=Engine 7 Agent
|
|
22245
22541
|
After=network.target
|
|
@@ -22247,13 +22543,13 @@ After=network.target
|
|
|
22247
22543
|
[Service]
|
|
22248
22544
|
Type=simple
|
|
22249
22545
|
WorkingDirectory=${cwd}
|
|
22250
|
-
ExecStart=${process.execPath} ${engine7Bin} start --config ${
|
|
22546
|
+
ExecStart=${process.execPath} ${engine7Bin} start --config ${path30.resolve(configPath2)}
|
|
22251
22547
|
Restart=on-failure
|
|
22252
22548
|
RestartSec=10
|
|
22253
22549
|
|
|
22254
22550
|
[Install]
|
|
22255
22551
|
WantedBy=default.target`;
|
|
22256
|
-
|
|
22552
|
+
fs28.writeFileSync(svcPath, svc);
|
|
22257
22553
|
try {
|
|
22258
22554
|
execSync3(`systemctl --user daemon-reload`, { stdio: "inherit" });
|
|
22259
22555
|
execSync3(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
|
|
@@ -22274,13 +22570,13 @@ WantedBy=default.target`;
|
|
|
22274
22570
|
process.exit(1);
|
|
22275
22571
|
}
|
|
22276
22572
|
} else if (process.platform === "darwin") {
|
|
22277
|
-
const plistPath =
|
|
22573
|
+
const plistPath = path30.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
|
|
22278
22574
|
try {
|
|
22279
22575
|
execSync3(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
|
|
22280
22576
|
} catch {
|
|
22281
22577
|
}
|
|
22282
22578
|
try {
|
|
22283
|
-
|
|
22579
|
+
fs28.unlinkSync(plistPath);
|
|
22284
22580
|
} catch {
|
|
22285
22581
|
}
|
|
22286
22582
|
console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u5220\u9664`);
|
|
@@ -22289,9 +22585,9 @@ WantedBy=default.target`;
|
|
|
22289
22585
|
execSync3(`systemctl --user disable engine7`, { stdio: "inherit" });
|
|
22290
22586
|
} catch {
|
|
22291
22587
|
}
|
|
22292
|
-
const svcPath =
|
|
22588
|
+
const svcPath = path30.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
|
|
22293
22589
|
try {
|
|
22294
|
-
|
|
22590
|
+
fs28.unlinkSync(svcPath);
|
|
22295
22591
|
} catch {
|
|
22296
22592
|
}
|
|
22297
22593
|
try {
|
|
@@ -22308,8 +22604,8 @@ WantedBy=default.target`;
|
|
|
22308
22604
|
console.log("\u274C \u672A\u5B89\u88C5");
|
|
22309
22605
|
}
|
|
22310
22606
|
} else if (process.platform === "darwin") {
|
|
22311
|
-
const plistPath =
|
|
22312
|
-
if (
|
|
22607
|
+
const plistPath = path30.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
|
|
22608
|
+
if (fs28.existsSync(plistPath)) {
|
|
22313
22609
|
console.log("\u2705 \u5DF2\u5B89\u88C5\uFF08launchd\uFF09");
|
|
22314
22610
|
} else {
|
|
22315
22611
|
console.log("\u274C \u672A\u5B89\u88C5");
|
|
@@ -22332,16 +22628,16 @@ WantedBy=default.target`;
|
|
|
22332
22628
|
console.log(`
|
|
22333
22629
|
\u{1F680} engine7 init`);
|
|
22334
22630
|
console.log(` state-dir: ${opts.stateDir}`);
|
|
22335
|
-
if (
|
|
22336
|
-
const files =
|
|
22631
|
+
if (fs28.existsSync(opts.stateDir) && !opts.dryRun) {
|
|
22632
|
+
const files = fs28.readdirSync(opts.stateDir);
|
|
22337
22633
|
if (files.length > 0) {
|
|
22338
22634
|
if (opts.force) {
|
|
22339
22635
|
console.log(`
|
|
22340
22636
|
\u26A0\uFE0F --force: \u6E05\u7A7A\u5DF2\u6709\u76EE\u5F55 ${opts.stateDir}`);
|
|
22341
|
-
|
|
22637
|
+
fs28.rmSync(opts.stateDir, { recursive: true, force: true });
|
|
22342
22638
|
} else {
|
|
22343
|
-
const existingConfig =
|
|
22344
|
-
if (
|
|
22639
|
+
const existingConfig = path30.join(opts.stateDir, "configs", "main7.json");
|
|
22640
|
+
if (fs28.existsSync(existingConfig)) {
|
|
22345
22641
|
console.log(`
|
|
22346
22642
|
\u267B\uFE0F \u68C0\u6D4B\u5230\u5DF2\u6709\u914D\u7F6E: ${existingConfig}`);
|
|
22347
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`);
|
|
@@ -22365,7 +22661,7 @@ WantedBy=default.target`;
|
|
|
22365
22661
|
rl.close();
|
|
22366
22662
|
}
|
|
22367
22663
|
const config = generateConfig(values);
|
|
22368
|
-
const configPath =
|
|
22664
|
+
const configPath = path30.join(opts.stateDir, "configs", "main7.json");
|
|
22369
22665
|
const tree = buildDirTree(values);
|
|
22370
22666
|
tree.push({
|
|
22371
22667
|
path: configPath,
|
|
@@ -22376,9 +22672,9 @@ WantedBy=default.target`;
|
|
|
22376
22672
|
dryRun(tree);
|
|
22377
22673
|
const skillsSrc = findTemplateDir("skills");
|
|
22378
22674
|
if (skillsSrc) {
|
|
22379
|
-
const skills =
|
|
22675
|
+
const skills = fs28.readdirSync(skillsSrc);
|
|
22380
22676
|
for (const s of skills) {
|
|
22381
|
-
console.log(` \u{1F4C1} ${
|
|
22677
|
+
console.log(` \u{1F4C1} ${path30.join(opts.stateDir, "workspace", "skills", s)}`);
|
|
22382
22678
|
}
|
|
22383
22679
|
}
|
|
22384
22680
|
} else {
|
|
@@ -22386,16 +22682,16 @@ WantedBy=default.target`;
|
|
|
22386
22682
|
execute(tree);
|
|
22387
22683
|
if (values.primaryApiKey && values.primaryApiKey.trim()) {
|
|
22388
22684
|
const envName = values.primaryProvider.toUpperCase().replace(/[^A-Z0-9_]/g, "_") + "_API_KEY";
|
|
22389
|
-
const secretsDir =
|
|
22390
|
-
if (!
|
|
22391
|
-
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");
|
|
22392
22688
|
let envContent = "";
|
|
22393
|
-
if (
|
|
22689
|
+
if (fs28.existsSync(envFile)) envContent = fs28.readFileSync(envFile, "utf8");
|
|
22394
22690
|
const lines = envContent.split("\n").filter((l) => l && !l.startsWith(envName + "="));
|
|
22395
22691
|
lines.push(envName + "=" + values.primaryApiKey.trim());
|
|
22396
|
-
|
|
22692
|
+
fs28.writeFileSync(envFile, lines.join("\n") + "\n", "utf8");
|
|
22397
22693
|
try {
|
|
22398
|
-
|
|
22694
|
+
fs28.chmodSync(envFile, 384);
|
|
22399
22695
|
} catch {
|
|
22400
22696
|
}
|
|
22401
22697
|
console.log("\u{1F511} API key \u5DF2\u5B58\u5165: " + envFile);
|
|
@@ -22403,55 +22699,55 @@ WantedBy=default.target`;
|
|
|
22403
22699
|
}
|
|
22404
22700
|
const skillsSrc = findTemplateDir("skills");
|
|
22405
22701
|
if (skillsSrc) {
|
|
22406
|
-
const skillsDest =
|
|
22407
|
-
|
|
22408
|
-
const skills =
|
|
22702
|
+
const skillsDest = path30.join(opts.stateDir, "workspace", "skills");
|
|
22703
|
+
fs28.mkdirSync(skillsDest, { recursive: true });
|
|
22704
|
+
const skills = fs28.readdirSync(skillsSrc);
|
|
22409
22705
|
for (const s of skills) {
|
|
22410
|
-
copyDirRecursive(
|
|
22706
|
+
copyDirRecursive(path30.join(skillsSrc, s), path30.join(skillsDest, s));
|
|
22411
22707
|
console.log(` \u{1F4E6} skill: ${s}`);
|
|
22412
22708
|
}
|
|
22413
22709
|
}
|
|
22414
22710
|
console.log(`
|
|
22415
22711
|
\u2705 \u521D\u59CB\u5316\u5B8C\u6210\uFF01
|
|
22416
22712
|
`);
|
|
22417
|
-
const homePointer =
|
|
22713
|
+
const homePointer = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
|
|
22418
22714
|
const pointerData = { stateDir: opts.stateDir };
|
|
22419
|
-
|
|
22715
|
+
fs28.writeFileSync(homePointer, JSON.stringify(pointerData, null, 2) + "\n");
|
|
22420
22716
|
console.log(` \u{1F4C4} ${homePointer}\uFF08\u4ECE\u4EFB\u610F\u76EE\u5F55\u90FD\u80FD\u627E\u5230\u6B64 agent\uFF09`);
|
|
22421
22717
|
console.log(`\u4E0B\u4E00\u6B65\uFF1A`);
|
|
22422
22718
|
console.log(` 1. \u68C0\u67E5\u5E76\u4FEE\u6539 ${opts.stateDir}/configs/main7.json`);
|
|
22423
22719
|
console.log(` 2. \u542F\u52A8 Engine: engine7 start\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
|
|
22424
22720
|
console.log(` 3. \u5F00\u673A\u81EA\u542F: engine7 service install\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
|
|
22425
|
-
console.log(` 4. \u67E5\u770B workspace: ${
|
|
22721
|
+
console.log(` 4. \u67E5\u770B workspace: ${path30.join(opts.stateDir, "workspace")}`);
|
|
22426
22722
|
}
|
|
22427
22723
|
}
|
|
22428
22724
|
function copyDirRecursive(src, dest) {
|
|
22429
|
-
|
|
22430
|
-
for (const entry of
|
|
22431
|
-
const srcPath =
|
|
22432
|
-
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);
|
|
22433
22729
|
if (entry.isDirectory()) {
|
|
22434
22730
|
copyDirRecursive(srcPath, destPath);
|
|
22435
22731
|
} else {
|
|
22436
|
-
|
|
22732
|
+
fs28.copyFileSync(srcPath, destPath);
|
|
22437
22733
|
}
|
|
22438
22734
|
}
|
|
22439
22735
|
}
|
|
22440
22736
|
function findTemplateDir(name) {
|
|
22441
22737
|
const candidates = [
|
|
22442
|
-
|
|
22443
|
-
|
|
22444
|
-
|
|
22738
|
+
path30.join(__dirname, "..", "templates", name),
|
|
22739
|
+
path30.join(__dirname, "..", "..", "templates", name),
|
|
22740
|
+
path30.join(process.cwd(), "templates", name)
|
|
22445
22741
|
];
|
|
22446
22742
|
for (const p of candidates) {
|
|
22447
|
-
if (
|
|
22743
|
+
if (fs28.existsSync(p)) return p;
|
|
22448
22744
|
}
|
|
22449
22745
|
return null;
|
|
22450
22746
|
}
|
|
22451
22747
|
function readHomePointer() {
|
|
22452
|
-
const ptrPath =
|
|
22748
|
+
const ptrPath = path30.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
|
|
22453
22749
|
try {
|
|
22454
|
-
return JSON.parse(
|
|
22750
|
+
return JSON.parse(fs28.readFileSync(ptrPath, "utf-8"));
|
|
22455
22751
|
} catch {
|
|
22456
22752
|
return null;
|
|
22457
22753
|
}
|
|
@@ -22462,4 +22758,3 @@ main().catch((err) => {
|
|
|
22462
22758
|
console.error(err.stack);
|
|
22463
22759
|
process.exit(1);
|
|
22464
22760
|
});
|
|
22465
|
-
//# sourceMappingURL=cli.mjs.map
|