@minonl/dia 0.0.16 → 0.0.17
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/README.md +2 -0
- package/dist/cli.js +394 -256
- package/docs/builtin-kit-design.md +65 -0
- package/docs/cli.md +1 -1
- package/docs/index.md +1 -0
- package/docs/status.md +1 -0
- package/kits/node/knowledge/pnpm.md +172 -19
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ var __esm = (fn, res, err) => () => {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
// src/paths.ts
|
|
14
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
14
15
|
import { homedir as homedir2 } from "node:os";
|
|
15
16
|
import { dirname as dirname2, join as join3 } from "node:path";
|
|
16
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -20,26 +21,31 @@ function diaHome() {
|
|
|
20
21
|
}
|
|
21
22
|
function installDir() {
|
|
22
23
|
const env = process.env.DIA_INSTALL_DIR || process.env.DIA_HOME_INSTALL;
|
|
23
|
-
if (env)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return diaHome();
|
|
24
|
+
if (env) {
|
|
25
|
+
if (existsSync3(env))
|
|
26
|
+
return env;
|
|
27
|
+
process.stderr.write(`! warn: DIA_INSTALL_DIR=${env} 不存在,忽略该覆盖并自动探测安装目录
|
|
28
|
+
`);
|
|
29
29
|
}
|
|
30
|
+
try {
|
|
31
|
+
const derived = dirname2(dirname2(fileURLToPath(import.meta.url)));
|
|
32
|
+
if (existsSync3(derived))
|
|
33
|
+
return derived;
|
|
34
|
+
} catch {}
|
|
35
|
+
return diaHome();
|
|
30
36
|
}
|
|
31
37
|
var personasDir = () => join3(diaHome(), "personas"), msgRoot = () => join3(diaHome(), "msg"), agentsRoot = () => join3(diaHome(), "agents"), stateDir = () => process.env.DIA_STATE_DIR || join3(diaHome(), "state"), cacheRoot = () => join3(diaHome(), "cache"), jobRoot = () => join3(diaHome(), "job"), ingestDir = () => join3(diaHome(), "ingest"), srcCacheDir = () => process.env.DIA_CACHE_DIR || join3(cacheRoot(), "src");
|
|
32
38
|
var init_paths = () => {};
|
|
33
39
|
|
|
34
40
|
// src/runtime.ts
|
|
35
|
-
import { existsSync as
|
|
41
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
36
42
|
import { join as join5 } from "node:path";
|
|
37
43
|
function callsFile() {
|
|
38
44
|
return join5(DATA2(), "runtime", "calls.jsonl");
|
|
39
45
|
}
|
|
40
46
|
function allCalls() {
|
|
41
47
|
const f = callsFile();
|
|
42
|
-
if (!
|
|
48
|
+
if (!existsSync5(f))
|
|
43
49
|
return [];
|
|
44
50
|
const out = [];
|
|
45
51
|
for (const line of readFileSync3(f, "utf8").split(`
|
|
@@ -69,10 +75,10 @@ var init_runtime = __esm(() => {
|
|
|
69
75
|
});
|
|
70
76
|
|
|
71
77
|
// src/freeze.ts
|
|
72
|
-
import { chmodSync, existsSync as
|
|
78
|
+
import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2, statSync as statSync3 } from "node:fs";
|
|
73
79
|
import { join as join6 } from "node:path";
|
|
74
80
|
function status() {
|
|
75
|
-
if (!
|
|
81
|
+
if (!existsSync6(FILE))
|
|
76
82
|
return { frozen: false };
|
|
77
83
|
try {
|
|
78
84
|
const s = JSON.parse(readFileSync4(FILE, "utf8"));
|
|
@@ -139,7 +145,7 @@ function thaw(opts) {
|
|
|
139
145
|
}
|
|
140
146
|
function snapshot() {
|
|
141
147
|
const p = join6(STATE, "freeze-snapshot.json");
|
|
142
|
-
if (!
|
|
148
|
+
if (!existsSync6(p))
|
|
143
149
|
return null;
|
|
144
150
|
return JSON.parse(readFileSync4(p, "utf8"));
|
|
145
151
|
}
|
|
@@ -155,7 +161,7 @@ var init_freeze = __esm(() => {
|
|
|
155
161
|
import {
|
|
156
162
|
appendFileSync as appendFileSync2,
|
|
157
163
|
chmodSync as chmodSync2,
|
|
158
|
-
existsSync as
|
|
164
|
+
existsSync as existsSync7,
|
|
159
165
|
mkdirSync as mkdirSync4,
|
|
160
166
|
readFileSync as readFileSync5,
|
|
161
167
|
realpathSync,
|
|
@@ -217,7 +223,7 @@ function checkpointTarget() {
|
|
|
217
223
|
};
|
|
218
224
|
}
|
|
219
225
|
try {
|
|
220
|
-
if (
|
|
226
|
+
if (existsSync7(file) && statSync4(file).isDirectory()) {
|
|
221
227
|
return { ok: false, path: file, error: `${CHECKPOINT_ENV} points at a directory (${file}); expected a file path` };
|
|
222
228
|
}
|
|
223
229
|
} catch {}
|
|
@@ -229,7 +235,7 @@ function readCheckpoint(target = checkpointTarget()) {
|
|
|
229
235
|
if (!target.ok)
|
|
230
236
|
return { state: "misconfigured", path: target.path, error: target.error };
|
|
231
237
|
const file = target.path;
|
|
232
|
-
if (!
|
|
238
|
+
if (!existsSync7(file))
|
|
233
239
|
return { state: "missing", path: file };
|
|
234
240
|
let parsed;
|
|
235
241
|
try {
|
|
@@ -401,7 +407,7 @@ function holderAlive(dir) {
|
|
|
401
407
|
}
|
|
402
408
|
function readHead() {
|
|
403
409
|
const file = headFile();
|
|
404
|
-
if (!
|
|
410
|
+
if (!existsSync7(file))
|
|
405
411
|
return { state: "missing" };
|
|
406
412
|
let parsed;
|
|
407
413
|
try {
|
|
@@ -498,8 +504,8 @@ function append(ev) {
|
|
|
498
504
|
full = { ...base, prev_hash };
|
|
499
505
|
full.hash = hashEvent(full, prev_hash);
|
|
500
506
|
const before = {
|
|
501
|
-
size:
|
|
502
|
-
head:
|
|
507
|
+
size: existsSync7(file) ? statSync4(file).size : 0,
|
|
508
|
+
head: existsSync7(headFile()) ? readFileSync5(headFile()) : null
|
|
503
509
|
};
|
|
504
510
|
const anchored = { last_seq: last.seq ?? 0, last_hash: last.hash ?? GENESIS, row_count: last.count };
|
|
505
511
|
const cpId = checkpoint_id || randomUUID2();
|
|
@@ -568,7 +574,7 @@ function append(ev) {
|
|
|
568
574
|
}
|
|
569
575
|
function rawLines() {
|
|
570
576
|
const file = auditFile();
|
|
571
|
-
if (!
|
|
577
|
+
if (!existsSync7(file))
|
|
572
578
|
return [];
|
|
573
579
|
return readFileSync5(file, "utf8").split(`
|
|
574
580
|
`).filter((l) => l.trim());
|
|
@@ -1288,7 +1294,7 @@ function getDoc(root, rel, section) {
|
|
|
1288
1294
|
// src/ingest.ts
|
|
1289
1295
|
import { execFileSync } from "node:child_process";
|
|
1290
1296
|
import { createHash as createHash2 } from "node:crypto";
|
|
1291
|
-
import { appendFileSync, existsSync as
|
|
1297
|
+
import { appendFileSync, existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync as statSync2, writeFileSync } from "node:fs";
|
|
1292
1298
|
import { homedir as homedir3 } from "node:os";
|
|
1293
1299
|
import { basename as basename2, dirname as dirname3, join as join4 } from "node:path";
|
|
1294
1300
|
import { zstdDecompressSync } from "node:zlib";
|
|
@@ -1480,7 +1486,7 @@ async function readOpencode(dbPath, domain, project) {
|
|
|
1480
1486
|
}
|
|
1481
1487
|
function loadState(cacheDir) {
|
|
1482
1488
|
const p = join4(cacheDir || CACHE, "state.json");
|
|
1483
|
-
if (!
|
|
1489
|
+
if (!existsSync4(p))
|
|
1484
1490
|
return {};
|
|
1485
1491
|
try {
|
|
1486
1492
|
return JSON.parse(readFileSync2(p, "utf8"));
|
|
@@ -1490,7 +1496,7 @@ function loadState(cacheDir) {
|
|
|
1490
1496
|
}
|
|
1491
1497
|
function seenSet(file) {
|
|
1492
1498
|
const set = new Set;
|
|
1493
|
-
if (!
|
|
1499
|
+
if (!existsSync4(file))
|
|
1494
1500
|
return set;
|
|
1495
1501
|
for (const line of readFileSync2(file, "utf8").split(`
|
|
1496
1502
|
`)) {
|
|
@@ -1518,7 +1524,7 @@ async function ingest(opts = {}) {
|
|
|
1518
1524
|
let episodes = [];
|
|
1519
1525
|
if (sources.includes("dsh")) {
|
|
1520
1526
|
const root = opts.sessionsRoot || join4(homedir3(), ".dsh", "sessions");
|
|
1521
|
-
if (
|
|
1527
|
+
if (existsSync4(root)) {
|
|
1522
1528
|
const cutoff = opts.full ? 0 : sinceMs ?? Number(state.dsh?.lastMtime || 0);
|
|
1523
1529
|
for (const file of walkDsh(root)) {
|
|
1524
1530
|
const mtime = Math.floor(statSync2(file).mtimeMs);
|
|
@@ -1536,7 +1542,7 @@ async function ingest(opts = {}) {
|
|
|
1536
1542
|
}
|
|
1537
1543
|
if (sources.includes("opencode")) {
|
|
1538
1544
|
const dbPath = opts.opencodeDb || join4(homedir3(), ".local", "share", "opencode", "opencode.db");
|
|
1539
|
-
if (
|
|
1545
|
+
if (existsSync4(dbPath)) {
|
|
1540
1546
|
const cutoff = opts.full ? 0 : sinceMs ?? Number(state.opencode?.lastUpdated || 0);
|
|
1541
1547
|
const all = await readOpencode(dbPath, domain, opts.project);
|
|
1542
1548
|
result.scanned += all.length;
|
|
@@ -1699,7 +1705,7 @@ function resumeCard(session) {
|
|
|
1699
1705
|
|
|
1700
1706
|
// src/persona.ts
|
|
1701
1707
|
import { createHash as createHash7 } from "node:crypto";
|
|
1702
|
-
import { closeSync, cpSync as cpSync2, existsSync as
|
|
1708
|
+
import { closeSync as closeSync2, cpSync as cpSync2, existsSync as existsSync12, lstatSync as lstatSync2, mkdirSync as mkdirSync10, openSync as openSync2, readFileSync as readFileSync10, readdirSync as readdirSync6, realpathSync as realpathSync3, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync8, symlinkSync as symlinkSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "node:fs";
|
|
1703
1709
|
import { homedir as homedir8 } from "node:os";
|
|
1704
1710
|
import { basename as basename6, dirname as dirname8, join as join13, relative as relative4, resolve as resolve7, sep as sep5 } from "node:path";
|
|
1705
1711
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
@@ -1707,14 +1713,17 @@ import { execFileSync as execFileSync3 } from "node:child_process";
|
|
|
1707
1713
|
// src/kit.ts
|
|
1708
1714
|
import { createHash as createHash6 } from "node:crypto";
|
|
1709
1715
|
import {
|
|
1716
|
+
closeSync,
|
|
1710
1717
|
cpSync,
|
|
1711
|
-
existsSync as
|
|
1718
|
+
existsSync as existsSync9,
|
|
1712
1719
|
lstatSync,
|
|
1713
1720
|
mkdirSync as mkdirSync7,
|
|
1721
|
+
openSync,
|
|
1714
1722
|
readFileSync as readFileSync7,
|
|
1715
1723
|
readdirSync as readdirSync3,
|
|
1716
1724
|
readlinkSync,
|
|
1717
1725
|
realpathSync as realpathSync2,
|
|
1726
|
+
renameSync as renameSync3,
|
|
1718
1727
|
rmSync as rmSync3,
|
|
1719
1728
|
statSync as statSync5,
|
|
1720
1729
|
symlinkSync,
|
|
@@ -1728,7 +1737,7 @@ import { execFileSync as execFileSync2 } from "node:child_process";
|
|
|
1728
1737
|
// src/config.ts
|
|
1729
1738
|
init_paths();
|
|
1730
1739
|
import { createHash as createHash5 } from "node:crypto";
|
|
1731
|
-
import { existsSync as
|
|
1740
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
|
|
1732
1741
|
import { homedir as homedir4 } from "node:os";
|
|
1733
1742
|
import { dirname as dirname5, join as join9 } from "node:path";
|
|
1734
1743
|
var home = () => process.env.DIA_HOME || homedir4();
|
|
@@ -1811,7 +1820,7 @@ function apply(entries, opts = {}) {
|
|
|
1811
1820
|
const applied = [];
|
|
1812
1821
|
for (const e of entries) {
|
|
1813
1822
|
const path = expand(e.file);
|
|
1814
|
-
const exists =
|
|
1823
|
+
const exists = existsSync8(path);
|
|
1815
1824
|
const before = exists ? readFileSync6(path, "utf8") : "";
|
|
1816
1825
|
let doc = {};
|
|
1817
1826
|
if (exists && before.trim()) {
|
|
@@ -1846,7 +1855,7 @@ function apply(entries, opts = {}) {
|
|
|
1846
1855
|
function revert(records) {
|
|
1847
1856
|
const restored = [], skipped = [];
|
|
1848
1857
|
for (const r of records) {
|
|
1849
|
-
if (!
|
|
1858
|
+
if (!existsSync8(r.path)) {
|
|
1850
1859
|
skipped.push(r.path);
|
|
1851
1860
|
continue;
|
|
1852
1861
|
}
|
|
@@ -1891,13 +1900,64 @@ function assertInsideHome(p) {
|
|
|
1891
1900
|
function assertInside(base, p) {
|
|
1892
1901
|
const abs = resolve5(base, p);
|
|
1893
1902
|
const rootReal = realpathSync2(base);
|
|
1894
|
-
if (!
|
|
1903
|
+
if (!existsSync9(abs))
|
|
1895
1904
|
throw new Error(`E_MANIFEST: source missing: ${p}`);
|
|
1896
1905
|
const real = realpathSync2(abs);
|
|
1897
1906
|
if (real !== rootReal && !real.startsWith(rootReal + sep4))
|
|
1898
1907
|
throw new Error(`E_MANIFEST: source escapes kit: ${p}`);
|
|
1899
1908
|
return abs;
|
|
1900
1909
|
}
|
|
1910
|
+
var EMPTY_TREE_HASH = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
|
1911
|
+
function cmpVersion(a, b) {
|
|
1912
|
+
const pa = a.split(/[.+-]/), pb = b.split(/[.+-]/);
|
|
1913
|
+
for (let i = 0;i < Math.max(pa.length, pb.length); i++) {
|
|
1914
|
+
const x = pa[i] ?? "0", y = pb[i] ?? "0";
|
|
1915
|
+
const nx = Number(x), ny = Number(y);
|
|
1916
|
+
const both = !Number.isNaN(nx) && !Number.isNaN(ny);
|
|
1917
|
+
if (both ? nx !== ny : x !== y)
|
|
1918
|
+
return both ? nx - ny : x < y ? -1 : 1;
|
|
1919
|
+
}
|
|
1920
|
+
return 0;
|
|
1921
|
+
}
|
|
1922
|
+
function versionDirs(dir) {
|
|
1923
|
+
return readdirSync3(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).sort(cmpVersion);
|
|
1924
|
+
}
|
|
1925
|
+
function sleepSync2(ms) {
|
|
1926
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
1927
|
+
}
|
|
1928
|
+
function withInstallLock(lockFile, fn) {
|
|
1929
|
+
const budget = Number(process.env.DIA_KIT_LOCK_MS || 5000);
|
|
1930
|
+
const start = Date.now();
|
|
1931
|
+
mkdirSync7(dirname6(lockFile), { recursive: true });
|
|
1932
|
+
for (;; ) {
|
|
1933
|
+
try {
|
|
1934
|
+
const fd = openSync(lockFile, "wx");
|
|
1935
|
+
writeFileSync5(fd, JSON.stringify({ pid: process.pid, at: Date.now() }));
|
|
1936
|
+
closeSync(fd);
|
|
1937
|
+
break;
|
|
1938
|
+
} catch (e) {
|
|
1939
|
+
if (e?.code !== "EEXIST")
|
|
1940
|
+
throw e;
|
|
1941
|
+
try {
|
|
1942
|
+
const st = statSync5(lockFile);
|
|
1943
|
+
if (Date.now() - st.mtimeMs > 120000) {
|
|
1944
|
+
rmSync3(lockFile, { force: true });
|
|
1945
|
+
continue;
|
|
1946
|
+
}
|
|
1947
|
+
} catch {
|
|
1948
|
+
continue;
|
|
1949
|
+
}
|
|
1950
|
+
if (Date.now() - start > budget)
|
|
1951
|
+
throw new Error(`E_KIT_BUSY: 另一个 dia 进程正在安装 kit(锁 ${lockFile};可用 DIA_KIT_LOCK_MS 调整等待)`);
|
|
1952
|
+
sleepSync2(50);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
try {
|
|
1956
|
+
return fn();
|
|
1957
|
+
} finally {
|
|
1958
|
+
rmSync3(lockFile, { force: true });
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1901
1961
|
var TREE_SKIP = new Set([".git", "node_modules", ".data"]);
|
|
1902
1962
|
function copyFilter(base) {
|
|
1903
1963
|
return (p) => !relative3(base, p).split(sep4).some((s) => TREE_SKIP.has(s));
|
|
@@ -1927,7 +1987,7 @@ function hashTree(root) {
|
|
|
1927
1987
|
}
|
|
1928
1988
|
function readKitManifest(dir) {
|
|
1929
1989
|
const p = join10(dir, "dia.json");
|
|
1930
|
-
if (!
|
|
1990
|
+
if (!existsSync9(p))
|
|
1931
1991
|
throw new Error("E_MANIFEST: dia.json not found");
|
|
1932
1992
|
let m;
|
|
1933
1993
|
try {
|
|
@@ -1951,7 +2011,7 @@ function resolveSource(from, ref) {
|
|
|
1951
2011
|
const key = createHash6("sha1").update(url).digest("hex").slice(0, 12);
|
|
1952
2012
|
const dir = join10(cacheDir2(), key);
|
|
1953
2013
|
const git = (args) => execFileSync2("git", ["-C", dir, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
1954
|
-
if (!
|
|
2014
|
+
if (!existsSync9(dir)) {
|
|
1955
2015
|
mkdirSync7(cacheDir2(), { recursive: true });
|
|
1956
2016
|
try {
|
|
1957
2017
|
execFileSync2("git", ["clone", "--quiet", url, dir], { stdio: "pipe" });
|
|
@@ -1976,7 +2036,7 @@ function resolveSource(from, ref) {
|
|
|
1976
2036
|
return { dir, commit: git(["rev-parse", "HEAD"]).trim() };
|
|
1977
2037
|
}
|
|
1978
2038
|
const dir = resolve5(from);
|
|
1979
|
-
if (!
|
|
2039
|
+
if (!existsSync9(dir))
|
|
1980
2040
|
throw new Error("E_SOURCE: path not found");
|
|
1981
2041
|
let commit = "local";
|
|
1982
2042
|
try {
|
|
@@ -1985,7 +2045,7 @@ function resolveSource(from, ref) {
|
|
|
1985
2045
|
return { dir, commit };
|
|
1986
2046
|
}
|
|
1987
2047
|
function checkTargetFree(path, kind, expected) {
|
|
1988
|
-
if (!
|
|
2048
|
+
if (!existsSync9(path) && !isSymlink(path))
|
|
1989
2049
|
return;
|
|
1990
2050
|
if (kind === "file") {
|
|
1991
2051
|
if (!isSymlink(path) && statSync5(path).isFile() && shaFile(path) === expected)
|
|
@@ -2051,7 +2111,7 @@ function renderContent(baseDir, targetDir, m, opts = {}) {
|
|
|
2051
2111
|
try {
|
|
2052
2112
|
if (p.entry.type === "file" && p.content !== undefined) {
|
|
2053
2113
|
checkTargetFree(p.dest, "file", sha256(Buffer.from(p.content, "base64")));
|
|
2054
|
-
} else if (p.linkTarget && (
|
|
2114
|
+
} else if (p.linkTarget && (existsSync9(p.dest) || isSymlink(p.dest))) {
|
|
2055
2115
|
if (!linkManaged(p.dest, p.linkTarget))
|
|
2056
2116
|
conflict = true;
|
|
2057
2117
|
}
|
|
@@ -2065,7 +2125,7 @@ function renderContent(baseDir, targetDir, m, opts = {}) {
|
|
|
2065
2125
|
throw new Error(`E_CONFLICT: ${p.dest} exists and differs`);
|
|
2066
2126
|
throw new Error(`E_CONFLICT: ${p.dest} exists and is not managed`);
|
|
2067
2127
|
}
|
|
2068
|
-
if (!isSymlink(p.dest) &&
|
|
2128
|
+
if (!isSymlink(p.dest) && existsSync9(p.dest)) {
|
|
2069
2129
|
mkdirSync7(backupDir, { recursive: true });
|
|
2070
2130
|
cpSync(p.dest, join10(backupDir, basename5(p.dest)));
|
|
2071
2131
|
}
|
|
@@ -2079,7 +2139,7 @@ function renderContent(baseDir, targetDir, m, opts = {}) {
|
|
|
2079
2139
|
writeFileSync5(p.dest, Buffer.from(p.content, "base64"));
|
|
2080
2140
|
p.entry.value = shaFile(p.dest);
|
|
2081
2141
|
} else if (p.linkTarget) {
|
|
2082
|
-
if (
|
|
2142
|
+
if (existsSync9(p.dest) || isSymlink(p.dest))
|
|
2083
2143
|
unlinkSync(p.dest);
|
|
2084
2144
|
symlinkSync(resolve5(p.linkTarget), p.dest);
|
|
2085
2145
|
p.entry.value = relative3(targetDir, resolve5(p.linkTarget));
|
|
@@ -2095,8 +2155,9 @@ function renderContent(baseDir, targetDir, m, opts = {}) {
|
|
|
2095
2155
|
function install(from, opts = {}) {
|
|
2096
2156
|
const src = resolveSource(from, opts.ref);
|
|
2097
2157
|
const m = readKitManifest(src.dir);
|
|
2098
|
-
const
|
|
2099
|
-
|
|
2158
|
+
const kitsRoot = resolve5(dataDir2(), "kits");
|
|
2159
|
+
const target = resolve5(kitsRoot, m.id, m.version);
|
|
2160
|
+
if (!target.startsWith(kitsRoot + sep4))
|
|
2100
2161
|
throw new Error("E_MANIFEST: version escapes install dir");
|
|
2101
2162
|
const kitRootRel = m.root ?? ".";
|
|
2102
2163
|
const kitRoot = resolve5(target, kitRootRel);
|
|
@@ -2108,43 +2169,78 @@ function install(from, opts = {}) {
|
|
|
2108
2169
|
const planned = renderContent(src.dir, target, m, { dryRun: true }) ?? [];
|
|
2109
2170
|
if (opts.dryRun)
|
|
2110
2171
|
return { id: m.id, version: m.version, dir: target, root: kitRoot, rendered: planned, hash: null, changed: false };
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2172
|
+
return withInstallLock(join10(kitsRoot, ".install.lock"), () => {
|
|
2173
|
+
const alreadyInstalled = existsSync9(join10(target, "kit.lock"));
|
|
2174
|
+
const changed = !alreadyInstalled || hashTree(src.dir) !== hashTree(target);
|
|
2175
|
+
if (changed) {
|
|
2176
|
+
const staging = join10(kitsRoot, ".staging", `${m.id}-${m.version}-${process.pid}-${Date.now()}`);
|
|
2177
|
+
mkdirSync7(staging, { recursive: true });
|
|
2178
|
+
try {
|
|
2179
|
+
cpSync(src.dir, staging, { recursive: true, dereference: true, filter: copyFilter(src.dir) });
|
|
2180
|
+
const stagedHash = hashTree(staging);
|
|
2181
|
+
if (stagedHash === EMPTY_TREE_HASH)
|
|
2182
|
+
throw new Error(`E_KIT_EMPTY: kit ${m.id}@${m.version} 内容为空(检查 source 与清单路径)`);
|
|
2183
|
+
writeFileSync5(join10(staging, "kit.lock"), JSON.stringify({
|
|
2184
|
+
id: m.id,
|
|
2185
|
+
version: m.version,
|
|
2186
|
+
commit: src.commit,
|
|
2187
|
+
root: kitRootRel,
|
|
2188
|
+
hash: stagedHash,
|
|
2189
|
+
rendered: [],
|
|
2190
|
+
commands: m.commands ?? [],
|
|
2191
|
+
knowledge: m.knowledge ?? [],
|
|
2192
|
+
dataRoot: m.data_root ?? null,
|
|
2193
|
+
env: m.env ?? null,
|
|
2194
|
+
config: []
|
|
2195
|
+
}, null, 1));
|
|
2196
|
+
mkdirSync7(dirname6(target), { recursive: true });
|
|
2197
|
+
if (existsSync9(target)) {
|
|
2198
|
+
const bak = `${target}.old-${process.pid}-${Date.now()}`;
|
|
2199
|
+
renameSync3(target, bak);
|
|
2200
|
+
try {
|
|
2201
|
+
renameSync3(staging, target);
|
|
2202
|
+
rmSync3(bak, { recursive: true, force: true });
|
|
2203
|
+
} catch (e) {
|
|
2204
|
+
try {
|
|
2205
|
+
renameSync3(bak, target);
|
|
2206
|
+
} catch {}
|
|
2207
|
+
throw e;
|
|
2208
|
+
}
|
|
2209
|
+
} else {
|
|
2210
|
+
renameSync3(staging, target);
|
|
2211
|
+
}
|
|
2212
|
+
} finally {
|
|
2213
|
+
rmSync3(staging, { recursive: true, force: true });
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
const rendered = renderContent(src.dir, target, m) ?? planned;
|
|
2217
|
+
const appliedConfig = apply(m.config ?? []);
|
|
2218
|
+
const hash = hashTree(target);
|
|
2219
|
+
writeFileSync5(join10(target, "kit.lock"), JSON.stringify({
|
|
2220
|
+
id: m.id,
|
|
2221
|
+
version: m.version,
|
|
2222
|
+
commit: src.commit,
|
|
2223
|
+
root: kitRootRel,
|
|
2224
|
+
hash,
|
|
2225
|
+
rendered,
|
|
2226
|
+
commands: m.commands ?? [],
|
|
2227
|
+
knowledge: m.knowledge ?? [],
|
|
2228
|
+
dataRoot: m.data_root ?? null,
|
|
2229
|
+
env: m.env ?? null,
|
|
2230
|
+
config: appliedConfig
|
|
2231
|
+
}, null, 1));
|
|
2232
|
+
return { id: m.id, version: m.version, dir: target, root: kitRoot, rendered, hash, changed };
|
|
2233
|
+
});
|
|
2138
2234
|
}
|
|
2139
2235
|
function installed() {
|
|
2140
2236
|
const root = join10(dataDir2(), "kits");
|
|
2141
|
-
if (!
|
|
2237
|
+
if (!existsSync9(root))
|
|
2142
2238
|
return [];
|
|
2143
2239
|
const out = [];
|
|
2144
2240
|
for (const e of readdirSync3(root, { withFileTypes: true })) {
|
|
2145
|
-
if (!e.isDirectory())
|
|
2241
|
+
if (!e.isDirectory() || e.name.startsWith("."))
|
|
2146
2242
|
continue;
|
|
2147
|
-
const versions =
|
|
2243
|
+
const versions = versionDirs(join10(root, e.name));
|
|
2148
2244
|
const version = versions[versions.length - 1];
|
|
2149
2245
|
if (!version)
|
|
2150
2246
|
continue;
|
|
@@ -2159,10 +2255,10 @@ function installed() {
|
|
|
2159
2255
|
}
|
|
2160
2256
|
function list() {
|
|
2161
2257
|
const root = join10(dataDir2(), "kits");
|
|
2162
|
-
if (!
|
|
2258
|
+
if (!existsSync9(root))
|
|
2163
2259
|
return [];
|
|
2164
|
-
return readdirSync3(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => {
|
|
2165
|
-
const versions =
|
|
2260
|
+
return readdirSync3(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => {
|
|
2261
|
+
const versions = versionDirs(join10(root, e.name));
|
|
2166
2262
|
const latest = versions[versions.length - 1];
|
|
2167
2263
|
let tags = [];
|
|
2168
2264
|
if (latest) {
|
|
@@ -2175,11 +2271,11 @@ function list() {
|
|
|
2175
2271
|
}
|
|
2176
2272
|
function readLock(id, version) {
|
|
2177
2273
|
const idDir = join10(dataDir2(), "kits", id);
|
|
2178
|
-
if (!
|
|
2274
|
+
if (!existsSync9(idDir))
|
|
2179
2275
|
throw new Error("E_NOT_INSTALLED");
|
|
2180
|
-
const v = version ||
|
|
2276
|
+
const v = version || versionDirs(idDir).pop();
|
|
2181
2277
|
const lockFile = join10(idDir, v, "kit.lock");
|
|
2182
|
-
if (!
|
|
2278
|
+
if (!existsSync9(lockFile))
|
|
2183
2279
|
throw new Error("E_NOT_INSTALLED");
|
|
2184
2280
|
return { version: v, lock: JSON.parse(readFileSync7(lockFile, "utf8")) };
|
|
2185
2281
|
}
|
|
@@ -2196,7 +2292,7 @@ function verify2(id, version) {
|
|
|
2196
2292
|
for (const r of lock.rendered) {
|
|
2197
2293
|
if (r.type === "dir")
|
|
2198
2294
|
continue;
|
|
2199
|
-
if (!
|
|
2295
|
+
if (!existsSync9(r.path)) {
|
|
2200
2296
|
drift.push(`missing: ${r.path}`);
|
|
2201
2297
|
continue;
|
|
2202
2298
|
}
|
|
@@ -2220,19 +2316,19 @@ function verify2(id, version) {
|
|
|
2220
2316
|
}
|
|
2221
2317
|
function remove(id) {
|
|
2222
2318
|
const idDir = join10(dataDir2(), "kits", id);
|
|
2223
|
-
if (!
|
|
2319
|
+
if (!existsSync9(idDir))
|
|
2224
2320
|
throw new Error("E_NOT_INSTALLED");
|
|
2225
2321
|
const removed = [];
|
|
2226
2322
|
const skipped = [];
|
|
2227
2323
|
for (const v of readdirSync3(idDir)) {
|
|
2228
2324
|
const dir = join10(idDir, v);
|
|
2229
2325
|
const lockFile = join10(dir, "kit.lock");
|
|
2230
|
-
if (
|
|
2326
|
+
if (existsSync9(lockFile)) {
|
|
2231
2327
|
const lock = JSON.parse(readFileSync7(lockFile, "utf8"));
|
|
2232
2328
|
for (const r of lock.rendered) {
|
|
2233
2329
|
if (r.type === "dir")
|
|
2234
2330
|
continue;
|
|
2235
|
-
if (!
|
|
2331
|
+
if (!existsSync9(r.path) && !isSymlink(r.path))
|
|
2236
2332
|
continue;
|
|
2237
2333
|
if (r.type === "file") {
|
|
2238
2334
|
if (!isSymlink(r.path) && shaFile(r.path) === r.value) {
|
|
@@ -2249,7 +2345,7 @@ function remove(id) {
|
|
|
2249
2345
|
continue;
|
|
2250
2346
|
}
|
|
2251
2347
|
const want = resolve5(dir, r.value);
|
|
2252
|
-
if (
|
|
2348
|
+
if (existsSync9(want) && cur === realpathSync2(want)) {
|
|
2253
2349
|
unlinkSync(r.path);
|
|
2254
2350
|
removed.push(r.path);
|
|
2255
2351
|
} else
|
|
@@ -2264,7 +2360,7 @@ function remove(id) {
|
|
|
2264
2360
|
}
|
|
2265
2361
|
|
|
2266
2362
|
// src/default-msg.ts
|
|
2267
|
-
import { existsSync as
|
|
2363
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readdirSync as readdirSync4, readFileSync as readFileSync8, renameSync as renameSync4, statSync as statSync6, writeFileSync as writeFileSync6 } from "node:fs";
|
|
2268
2364
|
import { homedir as homedir6 } from "node:os";
|
|
2269
2365
|
import { dirname as dirname7, join as join11, resolve as resolve6 } from "node:path";
|
|
2270
2366
|
init_paths();
|
|
@@ -2290,7 +2386,7 @@ function writeConfig(c) {
|
|
|
2290
2386
|
const tmp = `${file}.tmp.${process.pid}`;
|
|
2291
2387
|
writeFileSync6(tmp, JSON.stringify(next, null, 1) + `
|
|
2292
2388
|
`, { mode: 384 });
|
|
2293
|
-
|
|
2389
|
+
renameSync4(tmp, file);
|
|
2294
2390
|
return next;
|
|
2295
2391
|
}
|
|
2296
2392
|
function setEnabled(enabled, personaId) {
|
|
@@ -2317,7 +2413,7 @@ function isEnabled(personaId) {
|
|
|
2317
2413
|
}
|
|
2318
2414
|
function installedVersion() {
|
|
2319
2415
|
const dir = join11(diaHome(), "kits", "dia-msg");
|
|
2320
|
-
if (!
|
|
2416
|
+
if (!existsSync10(dir))
|
|
2321
2417
|
return null;
|
|
2322
2418
|
try {
|
|
2323
2419
|
const rows = readdirSync4(dir).filter((v) => statSync6(join11(dir, v)).isDirectory()).sort();
|
|
@@ -2333,6 +2429,27 @@ function autoInstallAllowed() {
|
|
|
2333
2429
|
return false;
|
|
2334
2430
|
return resolve6(diaHome()) === resolve6(join11(homedir6(), ".dia"));
|
|
2335
2431
|
}
|
|
2432
|
+
function pkgVersion() {
|
|
2433
|
+
try {
|
|
2434
|
+
return String(JSON.parse(readFileSync8(join11(installDir(), "package.json"), "utf8")).version || "unknown");
|
|
2435
|
+
} catch {
|
|
2436
|
+
return "unknown";
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
var stampFile = () => join11(stateDir(), "bootstrap.json");
|
|
2440
|
+
function readStamp() {
|
|
2441
|
+
try {
|
|
2442
|
+
return JSON.parse(readFileSync8(stampFile(), "utf8"));
|
|
2443
|
+
} catch {
|
|
2444
|
+
return null;
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2447
|
+
function writeStamp(kitId) {
|
|
2448
|
+
try {
|
|
2449
|
+
mkdirSync8(stateDir(), { recursive: true });
|
|
2450
|
+
writeFileSync6(stampFile(), JSON.stringify({ pkg: pkgVersion(), kit: kitId ?? null, at: new Date().toISOString() }, null, 1));
|
|
2451
|
+
} catch {}
|
|
2452
|
+
}
|
|
2336
2453
|
function ensure(personaId, opts = {}) {
|
|
2337
2454
|
const gate = isEnabled(personaId);
|
|
2338
2455
|
if (!gate.enabled && !opts.force)
|
|
@@ -2340,10 +2457,11 @@ function ensure(personaId, opts = {}) {
|
|
|
2340
2457
|
if (!opts.force && !autoInstallAllowed())
|
|
2341
2458
|
return { ok: false, reason: "auto-install-skipped:non-default-root(dia collab enable 可强制安装)" };
|
|
2342
2459
|
const source = builtinKitDir();
|
|
2343
|
-
if (!
|
|
2460
|
+
if (!existsSync10(join11(source, "dia.json")))
|
|
2344
2461
|
return { ok: false, reason: `missing-kit:${source}` };
|
|
2345
2462
|
try {
|
|
2346
2463
|
const r = install(source);
|
|
2464
|
+
writeStamp(r.id);
|
|
2347
2465
|
return { ok: true, kit: `${r.id}@${r.version}` };
|
|
2348
2466
|
} catch (e) {
|
|
2349
2467
|
return { ok: false, reason: `kit-install:${e?.message || String(e)}` };
|
|
@@ -2372,7 +2490,7 @@ function ensureForPersona(id, capabilities) {
|
|
|
2372
2490
|
|
|
2373
2491
|
// src/active.ts
|
|
2374
2492
|
init_paths();
|
|
2375
|
-
import { existsSync as
|
|
2493
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync9, readFileSync as readFileSync9, readdirSync as readdirSync5, statSync as statSync7, appendFileSync as appendFileSync4, writeFileSync as writeFileSync7 } from "node:fs";
|
|
2376
2494
|
import { userInfo } from "node:os";
|
|
2377
2495
|
import { join as join12 } from "node:path";
|
|
2378
2496
|
var dataDir3 = () => diaHome();
|
|
@@ -2388,10 +2506,10 @@ function readAll() {
|
|
|
2388
2506
|
}
|
|
2389
2507
|
function installedVersions(id) {
|
|
2390
2508
|
const dir = join12(dataDir3(), "personas", id);
|
|
2391
|
-
if (!
|
|
2509
|
+
if (!existsSync11(dir))
|
|
2392
2510
|
return [];
|
|
2393
2511
|
const verRoot = join12(dir, "versions");
|
|
2394
|
-
if (
|
|
2512
|
+
if (existsSync11(verRoot))
|
|
2395
2513
|
return readdirSync5(verRoot).filter((v) => statSync7(join12(verRoot, v)).isDirectory()).sort();
|
|
2396
2514
|
const skip = new Set(["current", "latest", "data", "repo", "repo.git", "worktrees", "versions", ".lock"]);
|
|
2397
2515
|
return readdirSync5(dir).filter((v) => !skip.has(v) && !v.startsWith(".staging-") && statSync7(join12(dir, v)).isDirectory()).sort();
|
|
@@ -2439,7 +2557,7 @@ function use(id, version, opts = {}) {
|
|
|
2439
2557
|
return { previous, current: entry };
|
|
2440
2558
|
}
|
|
2441
2559
|
function history(id, limit = 20) {
|
|
2442
|
-
if (!
|
|
2560
|
+
if (!existsSync11(auditFile2()))
|
|
2443
2561
|
return [];
|
|
2444
2562
|
const rows = readFileSync9(auditFile2(), "utf8").split(`
|
|
2445
2563
|
`).filter(Boolean).map((l) => {
|
|
@@ -2736,7 +2854,7 @@ var opencodeConfigDir = () => process.env.DIA_OPENCODE_CONFIG_DIR || join13(home
|
|
|
2736
2854
|
var opencodeConfigCandidates = () => process.env.DIA_OPENCODE_CONFIG ? [process.env.DIA_OPENCODE_CONFIG] : OPENCODE_CONFIG_NAMES.map((n) => join13(opencodeConfigDir(), n));
|
|
2737
2855
|
var opencodeConfig = () => {
|
|
2738
2856
|
const candidates = opencodeConfigCandidates();
|
|
2739
|
-
return candidates.find((p) =>
|
|
2857
|
+
return candidates.find((p) => existsSync12(p)) ?? candidates[0];
|
|
2740
2858
|
};
|
|
2741
2859
|
function shaFile2(p) {
|
|
2742
2860
|
return createHash7("sha256").update(readFileSync10(p)).digest("hex");
|
|
@@ -2758,7 +2876,7 @@ function walkFiles2(root) {
|
|
|
2758
2876
|
}
|
|
2759
2877
|
function readManifest(dir) {
|
|
2760
2878
|
const p = join13(dir, "dia.json");
|
|
2761
|
-
if (!
|
|
2879
|
+
if (!existsSync12(p))
|
|
2762
2880
|
throw new Error("E_MANIFEST: dia.json not found");
|
|
2763
2881
|
let m;
|
|
2764
2882
|
try {
|
|
@@ -2782,7 +2900,7 @@ function resolveSource2(from, ref) {
|
|
|
2782
2900
|
const key = createHash7("sha1").update(url).digest("hex").slice(0, 12);
|
|
2783
2901
|
const dir = join13(cacheDir3(), key);
|
|
2784
2902
|
const git = (args) => execFileSync3("git", ["-C", dir, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
2785
|
-
if (!
|
|
2903
|
+
if (!existsSync12(dir)) {
|
|
2786
2904
|
mkdirSync10(cacheDir3(), { recursive: true });
|
|
2787
2905
|
try {
|
|
2788
2906
|
execFileSync3("git", ["clone", "--quiet", url, dir], { stdio: "pipe" });
|
|
@@ -2808,7 +2926,7 @@ function resolveSource2(from, ref) {
|
|
|
2808
2926
|
return { dir, commit };
|
|
2809
2927
|
}
|
|
2810
2928
|
const dir = resolve7(from);
|
|
2811
|
-
if (!
|
|
2929
|
+
if (!existsSync12(dir))
|
|
2812
2930
|
throw new Error("E_SOURCE: path not found");
|
|
2813
2931
|
let commit = "local";
|
|
2814
2932
|
try {
|
|
@@ -2847,7 +2965,7 @@ function install2(from, opts = {}) {
|
|
|
2847
2965
|
if (!entry)
|
|
2848
2966
|
throw new Error("E_MANIFEST: missing entry.opencode");
|
|
2849
2967
|
const entryAbs = resolve7(src.dir, entry);
|
|
2850
|
-
if (!
|
|
2968
|
+
if (!existsSync12(entryAbs))
|
|
2851
2969
|
throw new Error("E_MANIFEST: entry.opencode file missing");
|
|
2852
2970
|
if (lstatSync2(entryAbs).isSymbolicLink())
|
|
2853
2971
|
throw new Error("E_MANIFEST: entry must not be a symlink");
|
|
@@ -2856,7 +2974,7 @@ function install2(from, opts = {}) {
|
|
|
2856
2974
|
if (!entryReal.startsWith(srcReal + sep5))
|
|
2857
2975
|
throw new Error("E_MANIFEST: entry escapes persona dir");
|
|
2858
2976
|
const dest = join13(opencodeAgents(), `${m.id}.md`);
|
|
2859
|
-
if (
|
|
2977
|
+
if (existsSync12(dest) && !readFileSync10(dest).equals(readFileSync10(entryAbs))) {
|
|
2860
2978
|
if (!opts.force)
|
|
2861
2979
|
throw new Error("E_CONFLICT: agent file exists and differs; remove it first (或 --force 覆盖,覆盖前会备份)");
|
|
2862
2980
|
overwrites.push(dest);
|
|
@@ -2867,7 +2985,7 @@ function install2(from, opts = {}) {
|
|
|
2867
2985
|
if (!dshEntry)
|
|
2868
2986
|
throw new Error("E_MANIFEST: missing entry.dsh");
|
|
2869
2987
|
const dshSrc = resolve7(src.dir, dshEntry);
|
|
2870
|
-
if (!
|
|
2988
|
+
if (!existsSync12(dshSrc) || !statSync8(dshSrc).isDirectory())
|
|
2871
2989
|
throw new Error("E_MANIFEST: entry.dsh dir missing");
|
|
2872
2990
|
if (!realpathSync3(dshSrc).startsWith(realpathSync3(src.dir) + sep5) && realpathSync3(dshSrc) !== realpathSync3(src.dir))
|
|
2873
2991
|
throw new Error("E_MANIFEST: entry escapes persona dir");
|
|
@@ -2878,12 +2996,12 @@ function install2(from, opts = {}) {
|
|
|
2878
2996
|
if (!codexEntry)
|
|
2879
2997
|
throw new Error("E_MANIFEST: missing entry.codex");
|
|
2880
2998
|
const abs = resolve7(src.dir, codexEntry);
|
|
2881
|
-
if (!
|
|
2999
|
+
if (!existsSync12(abs) || !statSync8(abs).isFile())
|
|
2882
3000
|
throw new Error("E_MANIFEST: entry.codex file missing");
|
|
2883
3001
|
if (!realpathSync3(abs).startsWith(realpathSync3(src.dir) + sep5))
|
|
2884
3002
|
throw new Error("E_MANIFEST: entry escapes persona dir");
|
|
2885
3003
|
const dest = join13(codexHome, ".codex", "AGENTS.md");
|
|
2886
|
-
if (
|
|
3004
|
+
if (existsSync12(dest) && !readFileSync10(dest).equals(readFileSync10(abs))) {
|
|
2887
3005
|
if (!opts.force)
|
|
2888
3006
|
throw new Error("E_CONFLICT: codex AGENTS.md exists and differs; use --force (备份后再覆盖)");
|
|
2889
3007
|
overwrites.push(dest);
|
|
@@ -2902,12 +3020,12 @@ function install2(from, opts = {}) {
|
|
|
2902
3020
|
let lockFd = null;
|
|
2903
3021
|
try {
|
|
2904
3022
|
try {
|
|
2905
|
-
lockFd =
|
|
3023
|
+
lockFd = openSync2(lockPath, "wx");
|
|
2906
3024
|
} catch {
|
|
2907
3025
|
const st = statSync8(lockPath);
|
|
2908
3026
|
if (Date.now() - st.mtimeMs > 10 * 60000) {
|
|
2909
3027
|
rmSync4(lockPath, { force: true });
|
|
2910
|
-
lockFd =
|
|
3028
|
+
lockFd = openSync2(lockPath, "wx");
|
|
2911
3029
|
} else
|
|
2912
3030
|
throw new Error("E_LOCKED: 另一个安装正在进行(10 分钟后视为陈旧)");
|
|
2913
3031
|
}
|
|
@@ -2918,7 +3036,7 @@ function install2(from, opts = {}) {
|
|
|
2918
3036
|
cpSync2(src.dir, staging, { recursive: true, dereference: true, filter: copyFilter(src.dir) });
|
|
2919
3037
|
const stagingHash = hashTree2(staging);
|
|
2920
3038
|
let reuseTarget = false;
|
|
2921
|
-
if (
|
|
3039
|
+
if (existsSync12(target)) {
|
|
2922
3040
|
const existing = (() => {
|
|
2923
3041
|
try {
|
|
2924
3042
|
return JSON.parse(readFileSync10(join13(target, "dia.lock"), "utf8"));
|
|
@@ -2937,11 +3055,11 @@ function install2(from, opts = {}) {
|
|
|
2937
3055
|
}
|
|
2938
3056
|
}
|
|
2939
3057
|
if (!reuseTarget)
|
|
2940
|
-
|
|
3058
|
+
renameSync5(staging, target);
|
|
2941
3059
|
} finally {
|
|
2942
3060
|
if (lockFd !== null) {
|
|
2943
3061
|
try {
|
|
2944
|
-
|
|
3062
|
+
closeSync2(lockFd);
|
|
2945
3063
|
} catch {}
|
|
2946
3064
|
}
|
|
2947
3065
|
try {
|
|
@@ -2967,7 +3085,7 @@ function install2(from, opts = {}) {
|
|
|
2967
3085
|
const renderedDirs = [];
|
|
2968
3086
|
if (hosts.includes("dsh")) {
|
|
2969
3087
|
const dshDest = resolve7(dshProfiles(), m.id);
|
|
2970
|
-
if (
|
|
3088
|
+
if (existsSync12(dshDest) && !existsSync12(join13(dshDest, ".dia-managed"))) {
|
|
2971
3089
|
throw new Error("E_CONFLICT: dsh profile exists and is not managed by dia");
|
|
2972
3090
|
}
|
|
2973
3091
|
rmSync4(dshDest, { recursive: true, force: true });
|
|
@@ -2988,7 +3106,7 @@ function install2(from, opts = {}) {
|
|
|
2988
3106
|
const srcSkill = resolve7(target, sk.from);
|
|
2989
3107
|
if (!srcSkill.startsWith(target + sep5))
|
|
2990
3108
|
throw new Error("E_MANIFEST: skill escapes persona dir: " + sk.from);
|
|
2991
|
-
if (!
|
|
3109
|
+
if (!existsSync12(srcSkill))
|
|
2992
3110
|
continue;
|
|
2993
3111
|
const name = sk.name || basename6(srcSkill);
|
|
2994
3112
|
mkdirSync10(skillRoot, { recursive: true });
|
|
@@ -3010,7 +3128,7 @@ function install2(from, opts = {}) {
|
|
|
3010
3128
|
const kitDir = resolve7(target, ref);
|
|
3011
3129
|
if (!kitDir.startsWith(target + sep5))
|
|
3012
3130
|
throw new Error(`E_MANIFEST: kit escapes persona dir: ${ref}`);
|
|
3013
|
-
if (!
|
|
3131
|
+
if (!existsSync12(join13(kitDir, "dia.json")))
|
|
3014
3132
|
throw new Error(`E_MANIFEST: kit manifest missing: ${ref}`);
|
|
3015
3133
|
const r = install(kitDir);
|
|
3016
3134
|
kitRefs.push({ id: r.id, version: r.version });
|
|
@@ -3038,13 +3156,13 @@ function install2(from, opts = {}) {
|
|
|
3038
3156
|
}
|
|
3039
3157
|
function list2() {
|
|
3040
3158
|
const root = join13(dataDir4(), "personas");
|
|
3041
|
-
if (!
|
|
3159
|
+
if (!existsSync12(root))
|
|
3042
3160
|
return [];
|
|
3043
|
-
return readdirSync6(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => ({ id: e.name, versions:
|
|
3161
|
+
return readdirSync6(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => ({ id: e.name, versions: versionDirs2(join13(root, e.name)) }));
|
|
3044
3162
|
}
|
|
3045
|
-
function
|
|
3163
|
+
function versionDirs2(idDir) {
|
|
3046
3164
|
const verRoot = join13(idDir, "versions");
|
|
3047
|
-
const scan = (root, keep) =>
|
|
3165
|
+
const scan = (root, keep) => existsSync12(root) ? readdirSync6(root).filter((n) => {
|
|
3048
3166
|
if (!keep(n))
|
|
3049
3167
|
return false;
|
|
3050
3168
|
try {
|
|
@@ -3053,14 +3171,14 @@ function versionDirs(idDir) {
|
|
|
3053
3171
|
return false;
|
|
3054
3172
|
}
|
|
3055
3173
|
}).sort() : [];
|
|
3056
|
-
if (
|
|
3174
|
+
if (existsSync12(verRoot))
|
|
3057
3175
|
return scan(verRoot, () => true);
|
|
3058
3176
|
const keep = (n) => !["current", "latest", "data", "repo", "repo.git", "worktrees", "versions"].includes(n) && !n.startsWith(".staging-") && n !== ".lock";
|
|
3059
3177
|
return scan(idDir, keep);
|
|
3060
3178
|
}
|
|
3061
3179
|
function resolveVersion(id, sel) {
|
|
3062
3180
|
const dir = join13(dataDir4(), "personas", id);
|
|
3063
|
-
const all =
|
|
3181
|
+
const all = versionDirs2(dir);
|
|
3064
3182
|
if (all.includes(sel))
|
|
3065
3183
|
return sel;
|
|
3066
3184
|
const hits = all.filter((v) => v === sel || v.startsWith(sel + "+") || v.startsWith(sel + "-"));
|
|
@@ -3076,12 +3194,12 @@ function dirOf(id, version) {
|
|
|
3076
3194
|
return null;
|
|
3077
3195
|
const flat = join13(dataDir4(), "personas", id, v);
|
|
3078
3196
|
const nested = join13(dataDir4(), "personas", id, "versions", v);
|
|
3079
|
-
const dir =
|
|
3080
|
-
return
|
|
3197
|
+
const dir = existsSync12(nested) ? nested : flat;
|
|
3198
|
+
return existsSync12(dir) ? { dir, version: v } : null;
|
|
3081
3199
|
}
|
|
3082
3200
|
function readMarker(dir) {
|
|
3083
3201
|
const p = join13(dir, ".dia-managed");
|
|
3084
|
-
if (!
|
|
3202
|
+
if (!existsSync12(p))
|
|
3085
3203
|
return null;
|
|
3086
3204
|
try {
|
|
3087
3205
|
return JSON.parse(readFileSync10(p, "utf8"));
|
|
@@ -3110,9 +3228,9 @@ function cmpSemver(a, b) {
|
|
|
3110
3228
|
}
|
|
3111
3229
|
function gc(id, opts = {}) {
|
|
3112
3230
|
const idDir = join13(dataDir4(), "personas", id);
|
|
3113
|
-
if (!
|
|
3231
|
+
if (!existsSync12(idDir))
|
|
3114
3232
|
throw new Error("E_NOT_INSTALLED");
|
|
3115
|
-
const all =
|
|
3233
|
+
const all = versionDirs2(idDir);
|
|
3116
3234
|
const activeVer = effective(id)?.version;
|
|
3117
3235
|
const keep = Math.max(1, opts.keep ?? 3);
|
|
3118
3236
|
const sorted = [...all].sort((a, b) => cmpSemver(b, a));
|
|
@@ -3136,12 +3254,12 @@ function gc(id, opts = {}) {
|
|
|
3136
3254
|
}
|
|
3137
3255
|
function verify3(id, version) {
|
|
3138
3256
|
const idDir = join13(dataDir4(), "personas", id);
|
|
3139
|
-
if (!
|
|
3257
|
+
if (!existsSync12(idDir))
|
|
3140
3258
|
throw new Error("E_NOT_INSTALLED");
|
|
3141
|
-
const v = version || effective(id)?.version ||
|
|
3259
|
+
const v = version || effective(id)?.version || versionDirs2(idDir).sort((a, b) => cmpSemver(b, a))[0];
|
|
3142
3260
|
if (!v)
|
|
3143
3261
|
throw new Error("E_NOT_INSTALLED");
|
|
3144
|
-
const dir =
|
|
3262
|
+
const dir = existsSync12(join13(idDir, "versions", v)) ? join13(idDir, "versions", v) : join13(idDir, v);
|
|
3145
3263
|
const lock = JSON.parse(readFileSync10(join13(dir, "dia.lock"), "utf8"));
|
|
3146
3264
|
const files = walkFiles2(dir).filter((f) => basename6(f) !== "dia.lock");
|
|
3147
3265
|
const h = createHash7("sha256");
|
|
@@ -3153,13 +3271,13 @@ function verify3(id, version) {
|
|
|
3153
3271
|
if (real !== lock.hash)
|
|
3154
3272
|
issues.push(`内容哈希不一致(期望 ${lock.hash.slice(0, 8)} 实得 ${real.slice(0, 8)})`);
|
|
3155
3273
|
for (const [f, expectedHash] of Object.entries(lock.renderedHashes || {})) {
|
|
3156
|
-
if (!
|
|
3274
|
+
if (!existsSync12(f))
|
|
3157
3275
|
issues.push(`产物缺失:${f}`);
|
|
3158
3276
|
else if (shaFile2(f) !== expectedHash)
|
|
3159
3277
|
issues.push(`产物被改动:${f}`);
|
|
3160
3278
|
}
|
|
3161
3279
|
for (const d of lock.renderedDirs || []) {
|
|
3162
|
-
if (!
|
|
3280
|
+
if (!existsSync12(d.path)) {
|
|
3163
3281
|
issues.push(`宿主 profile 缺失:${d.path}`);
|
|
3164
3282
|
continue;
|
|
3165
3283
|
}
|
|
@@ -3172,7 +3290,7 @@ function verify3(id, version) {
|
|
|
3172
3290
|
for (const r of lock.content?.rendered ?? []) {
|
|
3173
3291
|
if (r.type === "dir")
|
|
3174
3292
|
continue;
|
|
3175
|
-
if (!
|
|
3293
|
+
if (!existsSync12(r.path)) {
|
|
3176
3294
|
issues.push(`内容产物缺失:${r.path}`);
|
|
3177
3295
|
continue;
|
|
3178
3296
|
}
|
|
@@ -3188,7 +3306,7 @@ function verify3(id, version) {
|
|
|
3188
3306
|
continue;
|
|
3189
3307
|
}
|
|
3190
3308
|
const want = resolve7(dir, r.value);
|
|
3191
|
-
if (!
|
|
3309
|
+
if (!existsSync12(want) || cur !== realpathSync3(want))
|
|
3192
3310
|
issues.push(`内容产物指向不符:${r.path}`);
|
|
3193
3311
|
}
|
|
3194
3312
|
}
|
|
@@ -3305,7 +3423,7 @@ function create(id, opts = {}) {
|
|
|
3305
3423
|
const hosts = opts.hosts?.length ? opts.hosts : ["opencode", "dsh"];
|
|
3306
3424
|
for (const h of hosts)
|
|
3307
3425
|
assertHost(h);
|
|
3308
|
-
if (
|
|
3426
|
+
if (existsSync12(dir) && readdirSync6(dir).length)
|
|
3309
3427
|
throw new Error(`E_CONFLICT: ${dir} 非空`);
|
|
3310
3428
|
const files = skeleton(id, hosts, opts.msg !== false);
|
|
3311
3429
|
if (!opts.dryRun) {
|
|
@@ -3333,7 +3451,7 @@ function compareDir(expected, actual) {
|
|
|
3333
3451
|
if (HOST_OWNED_FILES.has(rel))
|
|
3334
3452
|
continue;
|
|
3335
3453
|
const dest = join13(actual, rel);
|
|
3336
|
-
if (!
|
|
3454
|
+
if (!existsSync12(dest))
|
|
3337
3455
|
out.push({ path: dest, action: "missing" });
|
|
3338
3456
|
else if (shaFile2(dest) !== shaFile2(f))
|
|
3339
3457
|
out.push({ path: dest, action: "changed" });
|
|
@@ -3342,7 +3460,7 @@ function compareDir(expected, actual) {
|
|
|
3342
3460
|
}
|
|
3343
3461
|
function render(id, opts = {}) {
|
|
3344
3462
|
const idDir = join13(dataDir4(), "personas", id);
|
|
3345
|
-
if (!
|
|
3463
|
+
if (!existsSync12(idDir))
|
|
3346
3464
|
throw new Error(`E_NOT_INSTALLED: persona ${id}`);
|
|
3347
3465
|
const version = effective(id)?.version ?? readdirSync6(idDir).filter((v) => statSync8(join13(idDir, v)).isDirectory()).sort().pop();
|
|
3348
3466
|
const dir = join13(idDir, version);
|
|
@@ -3361,10 +3479,10 @@ function render(id, opts = {}) {
|
|
|
3361
3479
|
agentSrc = resolve7(dir, entry);
|
|
3362
3480
|
if (!agentSrc.startsWith(dir + sep5))
|
|
3363
3481
|
throw new Error("E_MANIFEST: entry escapes persona dir");
|
|
3364
|
-
if (!
|
|
3482
|
+
if (!existsSync12(agentSrc))
|
|
3365
3483
|
throw new Error("E_MANIFEST: entry.opencode file missing");
|
|
3366
3484
|
agentDest = join13(opencodeAgents(), `${id}.md`);
|
|
3367
|
-
if (!
|
|
3485
|
+
if (!existsSync12(agentDest))
|
|
3368
3486
|
drift.push({ path: agentDest, action: "missing" });
|
|
3369
3487
|
else if (shaFile2(agentDest) !== shaFile2(agentSrc))
|
|
3370
3488
|
drift.push({ path: agentDest, action: "changed" });
|
|
@@ -3376,10 +3494,10 @@ function render(id, opts = {}) {
|
|
|
3376
3494
|
codexSrc = resolve7(dir, entry);
|
|
3377
3495
|
if (!codexSrc.startsWith(dir + sep5))
|
|
3378
3496
|
throw new Error("E_MANIFEST: entry escapes persona dir");
|
|
3379
|
-
if (!
|
|
3497
|
+
if (!existsSync12(codexSrc))
|
|
3380
3498
|
throw new Error("E_MANIFEST: entry.codex file missing");
|
|
3381
3499
|
codexDest = join13(codexHomeFor(opts, m), ".codex", "AGENTS.md");
|
|
3382
|
-
if (!
|
|
3500
|
+
if (!existsSync12(codexDest))
|
|
3383
3501
|
drift.push({ path: codexDest, action: "missing" });
|
|
3384
3502
|
else if (shaFile2(codexDest) !== shaFile2(codexSrc))
|
|
3385
3503
|
drift.push({ path: codexDest, action: "changed" });
|
|
@@ -3391,15 +3509,15 @@ function render(id, opts = {}) {
|
|
|
3391
3509
|
dshSrc = resolve7(dir, entry);
|
|
3392
3510
|
if (!dshSrc.startsWith(dir + sep5))
|
|
3393
3511
|
throw new Error("E_MANIFEST: entry escapes persona dir");
|
|
3394
|
-
if (!
|
|
3512
|
+
if (!existsSync12(dshSrc))
|
|
3395
3513
|
throw new Error("E_MANIFEST: entry.dsh dir missing");
|
|
3396
3514
|
dshDest = resolve7(dshProfiles(), id);
|
|
3397
|
-
if (!
|
|
3515
|
+
if (!existsSync12(dshDest))
|
|
3398
3516
|
drift.push({ path: dshDest, action: "missing" });
|
|
3399
3517
|
else {
|
|
3400
3518
|
drift.push(...compareDir(dshSrc, dshDest));
|
|
3401
3519
|
const marker = join13(dshDest, ".dia-managed");
|
|
3402
|
-
if (!
|
|
3520
|
+
if (!existsSync12(marker))
|
|
3403
3521
|
drift.push({ path: marker, action: "missing" });
|
|
3404
3522
|
else {
|
|
3405
3523
|
try {
|
|
@@ -3419,7 +3537,7 @@ function render(id, opts = {}) {
|
|
|
3419
3537
|
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
3420
3538
|
const bdir = join13(dataDir4(), "backups", `render-${stamp}`);
|
|
3421
3539
|
for (const d of drift) {
|
|
3422
|
-
if (!
|
|
3540
|
+
if (!existsSync12(d.path))
|
|
3423
3541
|
continue;
|
|
3424
3542
|
mkdirSync10(bdir, { recursive: true });
|
|
3425
3543
|
const dest = join13(bdir, basename6(d.path));
|
|
@@ -3470,14 +3588,14 @@ function render(id, opts = {}) {
|
|
|
3470
3588
|
}
|
|
3471
3589
|
function renderDrift(id, opts = {}) {
|
|
3472
3590
|
const idDir = join13(dataDir4(), "personas", id);
|
|
3473
|
-
if (!
|
|
3591
|
+
if (!existsSync12(idDir))
|
|
3474
3592
|
throw new Error(`E_NOT_INSTALLED: persona ${id}`);
|
|
3475
3593
|
const version = effective(id)?.version ?? readdirSync6(idDir).filter((v) => statSync8(join13(idDir, v)).isDirectory()).sort().pop();
|
|
3476
3594
|
if (!version)
|
|
3477
3595
|
return { id, version: "", drift: [], skipped: `无已安装版本:${idDir}` };
|
|
3478
3596
|
const dir = join13(idDir, version);
|
|
3479
3597
|
const lockPath = join13(dir, "dia.lock");
|
|
3480
|
-
if (!
|
|
3598
|
+
if (!existsSync12(lockPath))
|
|
3481
3599
|
return { id, version, drift: [], skipped: `无 dia.lock(安装未完成):${dir}` };
|
|
3482
3600
|
let lock;
|
|
3483
3601
|
try {
|
|
@@ -3495,18 +3613,18 @@ function renderDrift(id, opts = {}) {
|
|
|
3495
3613
|
}
|
|
3496
3614
|
};
|
|
3497
3615
|
for (const [f, expected] of Object.entries(lock.renderedHashes ?? {})) {
|
|
3498
|
-
if (!
|
|
3616
|
+
if (!existsSync12(f))
|
|
3499
3617
|
push({ path: f, action: "missing" });
|
|
3500
3618
|
else if (shaFile2(f) !== expected)
|
|
3501
3619
|
push({ path: f, action: "changed" });
|
|
3502
3620
|
}
|
|
3503
3621
|
for (const d of lock.renderedDirs ?? []) {
|
|
3504
|
-
if (!
|
|
3622
|
+
if (!existsSync12(d.path)) {
|
|
3505
3623
|
push({ path: d.path, action: "missing" });
|
|
3506
3624
|
continue;
|
|
3507
3625
|
}
|
|
3508
3626
|
const marker = join13(d.path, ".dia-managed");
|
|
3509
|
-
if (!
|
|
3627
|
+
if (!existsSync12(marker)) {
|
|
3510
3628
|
push({ path: marker, action: "missing" });
|
|
3511
3629
|
continue;
|
|
3512
3630
|
}
|
|
@@ -3520,7 +3638,7 @@ function renderDrift(id, opts = {}) {
|
|
|
3520
3638
|
for (const c of lock.content?.rendered ?? []) {
|
|
3521
3639
|
if (c.type === "dir")
|
|
3522
3640
|
continue;
|
|
3523
|
-
if (!
|
|
3641
|
+
if (!existsSync12(c.path)) {
|
|
3524
3642
|
push({ path: c.path, action: "missing" });
|
|
3525
3643
|
continue;
|
|
3526
3644
|
}
|
|
@@ -3537,22 +3655,22 @@ function renderDrift(id, opts = {}) {
|
|
|
3537
3655
|
continue;
|
|
3538
3656
|
}
|
|
3539
3657
|
const want = resolve7(dir, c.value);
|
|
3540
|
-
if (!
|
|
3658
|
+
if (!existsSync12(want) || cur !== realpathSync3(want))
|
|
3541
3659
|
push({ path: c.path, action: "changed" });
|
|
3542
3660
|
}
|
|
3543
3661
|
return { id, version: r.version, drift };
|
|
3544
3662
|
}
|
|
3545
3663
|
function remove2(id) {
|
|
3546
3664
|
const idDir = join13(dataDir4(), "personas", id);
|
|
3547
|
-
if (!
|
|
3665
|
+
if (!existsSync12(idDir))
|
|
3548
3666
|
throw new Error("E_NOT_INSTALLED");
|
|
3549
3667
|
const removed = [];
|
|
3550
3668
|
const skipped = [];
|
|
3551
3669
|
const allowed = resolve7(opencodeAgents(), `${id}.md`);
|
|
3552
|
-
for (const v of
|
|
3553
|
-
const dir =
|
|
3670
|
+
for (const v of versionDirs2(idDir)) {
|
|
3671
|
+
const dir = existsSync12(join13(idDir, "versions", v)) ? join13(idDir, "versions", v) : join13(idDir, v);
|
|
3554
3672
|
const lockFile = join13(dir, "dia.lock");
|
|
3555
|
-
if (
|
|
3673
|
+
if (existsSync12(lockFile)) {
|
|
3556
3674
|
const lock = JSON.parse(readFileSync10(lockFile, "utf8"));
|
|
3557
3675
|
for (const d of lock.renderedDirs || []) {
|
|
3558
3676
|
const abs = resolve7(d.path);
|
|
@@ -3560,7 +3678,7 @@ function remove2(id) {
|
|
|
3560
3678
|
skipped.push(abs);
|
|
3561
3679
|
continue;
|
|
3562
3680
|
}
|
|
3563
|
-
if (!
|
|
3681
|
+
if (!existsSync12(abs))
|
|
3564
3682
|
continue;
|
|
3565
3683
|
const m = readMarker(abs);
|
|
3566
3684
|
if (!m || m.id !== id) {
|
|
@@ -3573,10 +3691,10 @@ function remove2(id) {
|
|
|
3573
3691
|
for (const r of lock.content?.rendered ?? []) {
|
|
3574
3692
|
if (r.type === "dir")
|
|
3575
3693
|
continue;
|
|
3576
|
-
if (!
|
|
3694
|
+
if (!existsSync12(r.path))
|
|
3577
3695
|
continue;
|
|
3578
3696
|
if (r.type === "file") {
|
|
3579
|
-
if (!
|
|
3697
|
+
if (!existsSync12(r.path) || shaFile2(r.path) !== r.value) {
|
|
3580
3698
|
skipped.push(r.path);
|
|
3581
3699
|
continue;
|
|
3582
3700
|
}
|
|
@@ -3591,7 +3709,7 @@ function remove2(id) {
|
|
|
3591
3709
|
continue;
|
|
3592
3710
|
}
|
|
3593
3711
|
const want = resolve7(dir, r.value);
|
|
3594
|
-
if (
|
|
3712
|
+
if (existsSync12(want) && cur === realpathSync3(want)) {
|
|
3595
3713
|
unlinkSync2(r.path);
|
|
3596
3714
|
removed.push(r.path);
|
|
3597
3715
|
} else
|
|
@@ -3606,7 +3724,7 @@ function remove2(id) {
|
|
|
3606
3724
|
continue;
|
|
3607
3725
|
}
|
|
3608
3726
|
const expectedHash = lock.renderedHashes?.[f];
|
|
3609
|
-
if (!expectedHash || !
|
|
3727
|
+
if (!expectedHash || !existsSync12(abs) || shaFile2(abs) !== expectedHash) {
|
|
3610
3728
|
skipped.push(abs);
|
|
3611
3729
|
continue;
|
|
3612
3730
|
}
|
|
@@ -3637,7 +3755,7 @@ function showDefaultAgent(opts = {}) {
|
|
|
3637
3755
|
if (host !== "opencode")
|
|
3638
3756
|
throw new Error("E_HOST: only opencode has default_agent");
|
|
3639
3757
|
const file = opencodeConfig();
|
|
3640
|
-
if (!
|
|
3758
|
+
if (!existsSync12(file))
|
|
3641
3759
|
return { file, current: null };
|
|
3642
3760
|
const cfg = readOpencodeConfig(file);
|
|
3643
3761
|
return { file, current: typeof cfg.default_agent === "string" ? cfg.default_agent : null };
|
|
@@ -3655,13 +3773,13 @@ function setDefaultAgent(id, opts = {}) {
|
|
|
3655
3773
|
if (host !== "opencode")
|
|
3656
3774
|
throw new Error("E_HOST: only opencode has default_agent");
|
|
3657
3775
|
const file = opencodeConfig();
|
|
3658
|
-
if (!
|
|
3776
|
+
if (!existsSync12(file))
|
|
3659
3777
|
throw new Error(`E_CONFIG: ${file} 不存在(先装宿主,或设 DIA_OPENCODE_CONFIG)`);
|
|
3660
3778
|
const raw = readFileSync10(file, "utf8");
|
|
3661
3779
|
const cfg = readOpencodeConfig(file);
|
|
3662
3780
|
const stateFile = join13(dataDir4(), "state", "default-agent.json");
|
|
3663
3781
|
let state = { file, previous: null, set_at: null };
|
|
3664
|
-
if (
|
|
3782
|
+
if (existsSync12(stateFile)) {
|
|
3665
3783
|
try {
|
|
3666
3784
|
state = JSON.parse(readFileSync10(stateFile, "utf8"));
|
|
3667
3785
|
} catch {}
|
|
@@ -3684,7 +3802,7 @@ function setDefaultAgent(id, opts = {}) {
|
|
|
3684
3802
|
}
|
|
3685
3803
|
function checkUpstream(id, version) {
|
|
3686
3804
|
const idDir = join13(dataDir4(), "personas", id);
|
|
3687
|
-
if (!
|
|
3805
|
+
if (!existsSync12(idDir))
|
|
3688
3806
|
throw new Error("E_NOT_INSTALLED");
|
|
3689
3807
|
const v = version || (effective(id)?.version ?? readdirSync6(idDir).sort().pop());
|
|
3690
3808
|
const lock = JSON.parse(readFileSync10(join13(idDir, v, "dia.lock"), "utf8"));
|
|
@@ -3718,7 +3836,7 @@ function checkUpstream(id, version) {
|
|
|
3718
3836
|
}
|
|
3719
3837
|
function update(id, opts = {}) {
|
|
3720
3838
|
const idDir = join13(dataDir4(), "personas", id);
|
|
3721
|
-
if (!
|
|
3839
|
+
if (!existsSync12(idDir))
|
|
3722
3840
|
throw new Error("E_NOT_INSTALLED");
|
|
3723
3841
|
const cur = effective(id)?.version ?? readdirSync6(idDir).sort().pop();
|
|
3724
3842
|
const lock = JSON.parse(readFileSync10(join13(idDir, cur, "dia.lock"), "utf8"));
|
|
@@ -3732,7 +3850,7 @@ function update(id, opts = {}) {
|
|
|
3732
3850
|
|
|
3733
3851
|
// src/msg.ts
|
|
3734
3852
|
init_paths();
|
|
3735
|
-
import { existsSync as
|
|
3853
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync11, readdirSync as readdirSync7, readFileSync as readFileSync11, renameSync as renameSync6, statSync as statSync9, writeFileSync as writeFileSync9 } from "node:fs";
|
|
3736
3854
|
import { join as join14 } from "node:path";
|
|
3737
3855
|
import { randomBytes } from "node:crypto";
|
|
3738
3856
|
var msgRoot2 = () => msgRoot();
|
|
@@ -3744,11 +3862,11 @@ function atomicWrite(path, data) {
|
|
|
3744
3862
|
mkdirSync11(join14(path, ".."), { recursive: true });
|
|
3745
3863
|
const tmp = `${path}.tmp.${process.pid}.${randomBytes(2).toString("hex")}`;
|
|
3746
3864
|
writeFileSync9(tmp, data);
|
|
3747
|
-
|
|
3865
|
+
renameSync6(tmp, path);
|
|
3748
3866
|
}
|
|
3749
3867
|
function readAll2(agent) {
|
|
3750
3868
|
const dir = dirOf2(agent);
|
|
3751
|
-
if (!
|
|
3869
|
+
if (!existsSync13(dir))
|
|
3752
3870
|
return [];
|
|
3753
3871
|
return readdirSync7(dir).filter((f) => f.endsWith(".json")).map((f) => {
|
|
3754
3872
|
try {
|
|
@@ -3767,7 +3885,7 @@ function newId(prefix) {
|
|
|
3767
3885
|
}
|
|
3768
3886
|
function allInboxes() {
|
|
3769
3887
|
const root = msgRoot2();
|
|
3770
|
-
if (!
|
|
3888
|
+
if (!existsSync13(root))
|
|
3771
3889
|
return [];
|
|
3772
3890
|
return readdirSync7(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => ({ agent: e.name, messages: readAll2(e.name) }));
|
|
3773
3891
|
}
|
|
@@ -3780,7 +3898,7 @@ function send(opts) {
|
|
|
3780
3898
|
throw new Error("E_USAGE: --subject 必填");
|
|
3781
3899
|
if (opts.body && opts.bodyFile)
|
|
3782
3900
|
throw new Error("E_USAGE: --body 与 --body-file 只能给一个");
|
|
3783
|
-
if (opts.bodyFile && !
|
|
3901
|
+
if (opts.bodyFile && !existsSync13(opts.bodyFile))
|
|
3784
3902
|
throw new Error(`E_USAGE: body file 不存在: ${opts.bodyFile}`);
|
|
3785
3903
|
const threadId = opts.threadId || newId("th");
|
|
3786
3904
|
const existing = [...readAll2(opts.to), ...readAll2(opts.from)].filter((m) => m.thread_id === threadId);
|
|
@@ -3823,7 +3941,7 @@ function inbox(agent, opts = {}) {
|
|
|
3823
3941
|
}
|
|
3824
3942
|
function findInbox(agent, id) {
|
|
3825
3943
|
const dir = dirOf2(agent);
|
|
3826
|
-
if (!
|
|
3944
|
+
if (!existsSync13(dir))
|
|
3827
3945
|
return null;
|
|
3828
3946
|
for (const f of readdirSync7(dir)) {
|
|
3829
3947
|
if (!f.endsWith(".json"))
|
|
@@ -3932,7 +4050,7 @@ function stuck(minutes = 30, now = new Date) {
|
|
|
3932
4050
|
}
|
|
3933
4051
|
function agents() {
|
|
3934
4052
|
const root = msgRoot2();
|
|
3935
|
-
if (!
|
|
4053
|
+
if (!existsSync13(root))
|
|
3936
4054
|
return [];
|
|
3937
4055
|
return readdirSync7(root, { withFileTypes: true }).filter((e) => e.isDirectory() && statSync9(join14(root, e.name)).isDirectory()).map((e) => e.name);
|
|
3938
4056
|
}
|
|
@@ -3940,13 +4058,13 @@ function agents() {
|
|
|
3940
4058
|
// src/collab.ts
|
|
3941
4059
|
init_paths();
|
|
3942
4060
|
import {
|
|
3943
|
-
closeSync as
|
|
3944
|
-
existsSync as
|
|
4061
|
+
closeSync as closeSync3,
|
|
4062
|
+
existsSync as existsSync14,
|
|
3945
4063
|
mkdirSync as mkdirSync12,
|
|
3946
|
-
openSync as
|
|
4064
|
+
openSync as openSync3,
|
|
3947
4065
|
readdirSync as readdirSync8,
|
|
3948
4066
|
readFileSync as readFileSync12,
|
|
3949
|
-
renameSync as
|
|
4067
|
+
renameSync as renameSync7,
|
|
3950
4068
|
rmSync as rmSync5,
|
|
3951
4069
|
statSync as statSync10,
|
|
3952
4070
|
writeFileSync as writeFileSync10
|
|
@@ -3985,7 +4103,7 @@ function writeAtomic(path, data) {
|
|
|
3985
4103
|
ensureDir(dirname9(path));
|
|
3986
4104
|
const tmp = `${path}.tmp.${process.pid}.${randomBytes2(2).toString("hex")}`;
|
|
3987
4105
|
writeFileSync10(tmp, data, { mode: 384 });
|
|
3988
|
-
|
|
4106
|
+
renameSync7(tmp, path);
|
|
3989
4107
|
}
|
|
3990
4108
|
function sleep(ms) {
|
|
3991
4109
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
@@ -3998,7 +4116,7 @@ function withLock(name, fn) {
|
|
|
3998
4116
|
let fd;
|
|
3999
4117
|
for (let i = 0;i < 150; i++) {
|
|
4000
4118
|
try {
|
|
4001
|
-
fd =
|
|
4119
|
+
fd = openSync3(lock, "wx", 384);
|
|
4002
4120
|
break;
|
|
4003
4121
|
} catch (e) {
|
|
4004
4122
|
if (e?.code !== "EEXIST")
|
|
@@ -4016,7 +4134,7 @@ function withLock(name, fn) {
|
|
|
4016
4134
|
return fn();
|
|
4017
4135
|
} finally {
|
|
4018
4136
|
try {
|
|
4019
|
-
|
|
4137
|
+
closeSync3(fd);
|
|
4020
4138
|
} catch {}
|
|
4021
4139
|
try {
|
|
4022
4140
|
rmSync5(lock, { force: true });
|
|
@@ -4084,7 +4202,7 @@ function messageFile(sessionId, id) {
|
|
|
4084
4202
|
}
|
|
4085
4203
|
function readAll3(sessionId) {
|
|
4086
4204
|
const dir = join15(inboxRoot(), normalizeSessionId(sessionId));
|
|
4087
|
-
if (!
|
|
4205
|
+
if (!existsSync14(dir))
|
|
4088
4206
|
return [];
|
|
4089
4207
|
const out = [];
|
|
4090
4208
|
for (const f of readdirSync8(dir)) {
|
|
@@ -4098,7 +4216,7 @@ function readAll3(sessionId) {
|
|
|
4098
4216
|
return out.sort((a, b) => a.msg.created_at.localeCompare(b.msg.created_at) || a.msg.seq - b.msg.seq);
|
|
4099
4217
|
}
|
|
4100
4218
|
function allSessionsWithInbox() {
|
|
4101
|
-
if (!
|
|
4219
|
+
if (!existsSync14(inboxRoot()))
|
|
4102
4220
|
return [];
|
|
4103
4221
|
return readdirSync8(inboxRoot(), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
4104
4222
|
}
|
|
@@ -4121,7 +4239,7 @@ function legacySlug(agent) {
|
|
|
4121
4239
|
return `${base}-${createHash8("sha1").update(agent).digest("hex").slice(0, 6)}`;
|
|
4122
4240
|
}
|
|
4123
4241
|
function legacyAll() {
|
|
4124
|
-
if (!
|
|
4242
|
+
if (!existsSync14(legacyRoot()))
|
|
4125
4243
|
return [];
|
|
4126
4244
|
const out = [];
|
|
4127
4245
|
for (const slug of readdirSync8(legacyRoot(), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name)) {
|
|
@@ -4163,7 +4281,7 @@ function readBody(opts) {
|
|
|
4163
4281
|
throw new Error(`E_USAGE: body 超过 ${MAX_BODY} 字节,请拆分或引用文件`);
|
|
4164
4282
|
return { body: opts.body, body_bytes: bytes };
|
|
4165
4283
|
}
|
|
4166
|
-
if (!
|
|
4284
|
+
if (!existsSync14(opts.bodyFile))
|
|
4167
4285
|
throw new Error(`E_USAGE: body file 不存在: ${opts.bodyFile}`);
|
|
4168
4286
|
const buf = readFileSync12(opts.bodyFile);
|
|
4169
4287
|
if (buf.byteLength > MAX_BODY)
|
|
@@ -4343,13 +4461,13 @@ function close(sessionId, id, reason) {
|
|
|
4343
4461
|
}
|
|
4344
4462
|
function migrateLegacy(opts = {}) {
|
|
4345
4463
|
const oldRoot = join15(diaHome(), "msg");
|
|
4346
|
-
if (!
|
|
4464
|
+
if (!existsSync14(oldRoot))
|
|
4347
4465
|
return { total: 0, migrated: 0, skipped: 0, messages: [] };
|
|
4348
4466
|
const rows = [];
|
|
4349
4467
|
let migrated = 0, skipped = 0, total = 0;
|
|
4350
4468
|
for (const agent of readdirSync8(oldRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name)) {
|
|
4351
4469
|
const dir = join15(oldRoot, agent, "inbox");
|
|
4352
|
-
if (!
|
|
4470
|
+
if (!existsSync14(dir))
|
|
4353
4471
|
continue;
|
|
4354
4472
|
const slug = legacySlug(agent);
|
|
4355
4473
|
for (const f of readdirSync8(dir)) {
|
|
@@ -4367,7 +4485,7 @@ function migrateLegacy(opts = {}) {
|
|
|
4367
4485
|
continue;
|
|
4368
4486
|
}
|
|
4369
4487
|
const target = join15(legacyRoot(), slug, `${legacyId}.json`);
|
|
4370
|
-
if (
|
|
4488
|
+
if (existsSync14(target)) {
|
|
4371
4489
|
skipped++;
|
|
4372
4490
|
continue;
|
|
4373
4491
|
}
|
|
@@ -4379,7 +4497,7 @@ function migrateLegacy(opts = {}) {
|
|
|
4379
4497
|
const allowed = [resolve8(oldRoot), resolve8(tmpdir())].some((base) => abs === base || abs.startsWith(base + sep6));
|
|
4380
4498
|
if (!allowed) {
|
|
4381
4499
|
bodyMissing = true;
|
|
4382
|
-
} else if (
|
|
4500
|
+
} else if (existsSync14(abs)) {
|
|
4383
4501
|
const buf = readFileSync12(abs);
|
|
4384
4502
|
bodyBytes = buf.byteLength;
|
|
4385
4503
|
if (bodyBytes > MAX_BODY) {
|
|
@@ -4427,7 +4545,7 @@ function migrateLegacy(opts = {}) {
|
|
|
4427
4545
|
|
|
4428
4546
|
// src/claims.ts
|
|
4429
4547
|
init_paths();
|
|
4430
|
-
import { appendFileSync as appendFileSync5, existsSync as
|
|
4548
|
+
import { appendFileSync as appendFileSync5, existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as readFileSync13, renameSync as renameSync8, writeFileSync as writeFileSync11 } from "node:fs";
|
|
4431
4549
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
4432
4550
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
4433
4551
|
import { basename as basename7, join as join16, relative as relative5, resolve as resolve9, sep as sep7 } from "node:path";
|
|
@@ -4439,7 +4557,7 @@ function append2(e) {
|
|
|
4439
4557
|
`, { mode: 384 });
|
|
4440
4558
|
}
|
|
4441
4559
|
function fold() {
|
|
4442
|
-
if (!
|
|
4560
|
+
if (!existsSync15(file()))
|
|
4443
4561
|
return [];
|
|
4444
4562
|
const map = new Map;
|
|
4445
4563
|
for (const line of readFileSync13(file(), "utf8").split(`
|
|
@@ -4551,7 +4669,7 @@ function compact(opts = {}) {
|
|
|
4551
4669
|
const cutoff = now.getTime() - days * 86400000;
|
|
4552
4670
|
return withLock("claims", () => {
|
|
4553
4671
|
const f = file();
|
|
4554
|
-
if (!
|
|
4672
|
+
if (!existsSync15(f))
|
|
4555
4673
|
return { before: 0, after: 0, dropped: 0 };
|
|
4556
4674
|
const raw = readFileSync13(f, "utf8");
|
|
4557
4675
|
const lines = raw.split(`
|
|
@@ -4591,16 +4709,16 @@ function compact(opts = {}) {
|
|
|
4591
4709
|
writeFileSync11(tmp, kept.join(`
|
|
4592
4710
|
`) + (kept.length ? `
|
|
4593
4711
|
` : ""), { mode: 384 });
|
|
4594
|
-
|
|
4712
|
+
renameSync8(tmp, f);
|
|
4595
4713
|
}
|
|
4596
|
-
const after =
|
|
4714
|
+
const after = existsSync15(f) ? readFileSync13(f, "utf8").length : 0;
|
|
4597
4715
|
return { before: raw.length, after, dropped };
|
|
4598
4716
|
});
|
|
4599
4717
|
}
|
|
4600
4718
|
|
|
4601
4719
|
// src/task.ts
|
|
4602
4720
|
init_paths();
|
|
4603
|
-
import { appendFileSync as appendFileSync6, existsSync as
|
|
4721
|
+
import { appendFileSync as appendFileSync6, existsSync as existsSync16, mkdirSync as mkdirSync14, readFileSync as readFileSync14 } from "node:fs";
|
|
4604
4722
|
import { join as join17 } from "node:path";
|
|
4605
4723
|
import { createHash as createHash9 } from "node:crypto";
|
|
4606
4724
|
var DATA5 = () => diaHome();
|
|
@@ -4634,7 +4752,7 @@ function file2() {
|
|
|
4634
4752
|
var uniq = (xs) => [...new Set(xs.filter(Boolean))];
|
|
4635
4753
|
function fold2() {
|
|
4636
4754
|
const map = new Map;
|
|
4637
|
-
if (!
|
|
4755
|
+
if (!existsSync16(file2()))
|
|
4638
4756
|
return map;
|
|
4639
4757
|
for (const line of readFileSync14(file2(), "utf8").split(`
|
|
4640
4758
|
`)) {
|
|
@@ -6150,7 +6268,7 @@ init_paths();
|
|
|
6150
6268
|
|
|
6151
6269
|
// src/agents.ts
|
|
6152
6270
|
init_paths();
|
|
6153
|
-
import { existsSync as
|
|
6271
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync15, readdirSync as readdirSync9, readFileSync as readFileSync15, renameSync as renameSync9, rmSync as rmSync6, writeFileSync as writeFileSync12 } from "node:fs";
|
|
6154
6272
|
import { basename as basename8, join as join18, resolve as resolve10 } from "node:path";
|
|
6155
6273
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
6156
6274
|
var agentsRoot2 = () => agentsRoot();
|
|
@@ -6159,7 +6277,7 @@ function atomicWrite2(path, data) {
|
|
|
6159
6277
|
mkdirSync15(join18(path, ".."), { recursive: true });
|
|
6160
6278
|
const tmp = `${path}.tmp.${process.pid}`;
|
|
6161
6279
|
writeFileSync12(tmp, data);
|
|
6162
|
-
|
|
6280
|
+
renameSync9(tmp, path);
|
|
6163
6281
|
}
|
|
6164
6282
|
function sh(cmd, args) {
|
|
6165
6283
|
try {
|
|
@@ -6180,14 +6298,14 @@ function register(rec) {
|
|
|
6180
6298
|
}
|
|
6181
6299
|
function unregister(agent) {
|
|
6182
6300
|
const p = fileOf(agent);
|
|
6183
|
-
if (!
|
|
6301
|
+
if (!existsSync17(p))
|
|
6184
6302
|
return false;
|
|
6185
6303
|
rmSync6(p, { force: true });
|
|
6186
6304
|
return true;
|
|
6187
6305
|
}
|
|
6188
6306
|
function read2(agent) {
|
|
6189
6307
|
const p = fileOf(agent);
|
|
6190
|
-
if (!
|
|
6308
|
+
if (!existsSync17(p))
|
|
6191
6309
|
return null;
|
|
6192
6310
|
try {
|
|
6193
6311
|
return JSON.parse(readFileSync15(p, "utf8"));
|
|
@@ -6197,7 +6315,7 @@ function read2(agent) {
|
|
|
6197
6315
|
}
|
|
6198
6316
|
function all() {
|
|
6199
6317
|
const root = agentsRoot2();
|
|
6200
|
-
if (!
|
|
6318
|
+
if (!existsSync17(root))
|
|
6201
6319
|
return [];
|
|
6202
6320
|
return readdirSync9(root).filter((f) => f.endsWith(".json")).map((f) => {
|
|
6203
6321
|
try {
|
|
@@ -6463,7 +6581,7 @@ async function deliverAcp(agent, id, opts = {}) {
|
|
|
6463
6581
|
}
|
|
6464
6582
|
|
|
6465
6583
|
// src/scope.ts
|
|
6466
|
-
import { existsSync as
|
|
6584
|
+
import { existsSync as existsSync18, readFileSync as readFileSync16, readdirSync as readdirSync10, statSync as statSync11 } from "node:fs";
|
|
6467
6585
|
init_paths();
|
|
6468
6586
|
import { homedir as homedir9 } from "node:os";
|
|
6469
6587
|
import { join as join20, resolve as resolve11 } from "node:path";
|
|
@@ -6503,7 +6621,7 @@ function loadKit(id, version) {
|
|
|
6503
6621
|
}
|
|
6504
6622
|
function installedPersonas() {
|
|
6505
6623
|
const p = join20(dataDir5(), "personas");
|
|
6506
|
-
if (!
|
|
6624
|
+
if (!existsSync18(p))
|
|
6507
6625
|
return [];
|
|
6508
6626
|
return readdirSync10(p, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
6509
6627
|
}
|
|
@@ -6519,7 +6637,7 @@ function current(explicit) {
|
|
|
6519
6637
|
if (!id)
|
|
6520
6638
|
return null;
|
|
6521
6639
|
const idDir = join20(dataDir5(), "personas", id);
|
|
6522
|
-
if (!
|
|
6640
|
+
if (!existsSync18(idDir))
|
|
6523
6641
|
throw new Error(`E_SCOPE: persona not installed: ${id}`);
|
|
6524
6642
|
const version = effective(id)?.version ?? latest(idDir);
|
|
6525
6643
|
const dir = join20(idDir, version);
|
|
@@ -6569,13 +6687,13 @@ function scopeEnv(s, extra = {}) {
|
|
|
6569
6687
|
}
|
|
6570
6688
|
|
|
6571
6689
|
// src/doctor.ts
|
|
6572
|
-
import { closeSync as
|
|
6690
|
+
import { closeSync as closeSync4, existsSync as existsSync23, openSync as openSync4, readFileSync as readFileSync19, readSync, realpathSync as realpathSync5, statSync as statSync12 } from "node:fs";
|
|
6573
6691
|
import { homedir as homedir12 } from "node:os";
|
|
6574
6692
|
import { delimiter, dirname as dirname13, join as join25, resolve as resolve13 } from "node:path";
|
|
6575
6693
|
|
|
6576
6694
|
// src/dsh.ts
|
|
6577
6695
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
6578
|
-
import { existsSync as
|
|
6696
|
+
import { existsSync as existsSync19, realpathSync as realpathSync4 } from "node:fs";
|
|
6579
6697
|
import { dirname as dirname10, join as join21 } from "node:path";
|
|
6580
6698
|
var dshBin = () => process.env.DIA_DSH_BIN || "dsh";
|
|
6581
6699
|
function which(cmd) {
|
|
@@ -6583,7 +6701,7 @@ function which(cmd) {
|
|
|
6583
6701
|
if (!dir)
|
|
6584
6702
|
continue;
|
|
6585
6703
|
const p = join21(dir, cmd);
|
|
6586
|
-
if (
|
|
6704
|
+
if (existsSync19(p))
|
|
6587
6705
|
return p;
|
|
6588
6706
|
}
|
|
6589
6707
|
return null;
|
|
@@ -6606,7 +6724,7 @@ var packageFor = (id) => `@deepseek-ai/dsh-${id}`;
|
|
|
6606
6724
|
function requireConfig(root, id) {
|
|
6607
6725
|
const pkg = packageFor(id);
|
|
6608
6726
|
const dir = join21(root, "node_modules", ...pkg.split("/"), "lib", "index.js");
|
|
6609
|
-
if (!
|
|
6727
|
+
if (!existsSync19(dir))
|
|
6610
6728
|
return { required: false };
|
|
6611
6729
|
try {
|
|
6612
6730
|
const out = execFileSync7(process.execPath, [
|
|
@@ -6651,7 +6769,7 @@ function pluginsWithoutConfig(dump, personaId) {
|
|
|
6651
6769
|
return missing;
|
|
6652
6770
|
}
|
|
6653
6771
|
function checkPreset(personaId, profileDir) {
|
|
6654
|
-
if (!
|
|
6772
|
+
if (!existsSync19(profileDir))
|
|
6655
6773
|
return { ok: true, skipped: "未渲染 dsh profile", issues: [] };
|
|
6656
6774
|
let dump;
|
|
6657
6775
|
try {
|
|
@@ -6679,7 +6797,7 @@ function checkPreset(personaId, profileDir) {
|
|
|
6679
6797
|
}
|
|
6680
6798
|
|
|
6681
6799
|
// src/platforms.ts
|
|
6682
|
-
import { existsSync as
|
|
6800
|
+
import { existsSync as existsSync20, readFileSync as readFileSync17 } from "node:fs";
|
|
6683
6801
|
init_paths();
|
|
6684
6802
|
import { join as join22 } from "node:path";
|
|
6685
6803
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
@@ -6694,7 +6812,7 @@ function registryCandidates() {
|
|
|
6694
6812
|
return out;
|
|
6695
6813
|
}
|
|
6696
6814
|
function registryPath() {
|
|
6697
|
-
return registryCandidates().find((p) =>
|
|
6815
|
+
return registryCandidates().find((p) => existsSync20(p)) ?? null;
|
|
6698
6816
|
}
|
|
6699
6817
|
function load() {
|
|
6700
6818
|
const p = registryPath();
|
|
@@ -6768,7 +6886,7 @@ function checks(reg) {
|
|
|
6768
6886
|
|
|
6769
6887
|
// src/deps.ts
|
|
6770
6888
|
init_paths();
|
|
6771
|
-
import { existsSync as
|
|
6889
|
+
import { existsSync as existsSync21, readFileSync as readFileSync18, mkdirSync as mkdirSync16, writeFileSync as writeFileSync14, chmodSync as chmodSync3 } from "node:fs";
|
|
6772
6890
|
import { homedir as homedir10 } from "node:os";
|
|
6773
6891
|
import { dirname as dirname11, join as join23 } from "node:path";
|
|
6774
6892
|
import { execFileSync as execFileSync9 } from "node:child_process";
|
|
@@ -6784,7 +6902,7 @@ function candidates() {
|
|
|
6784
6902
|
return out;
|
|
6785
6903
|
}
|
|
6786
6904
|
function file3() {
|
|
6787
|
-
return candidates().find((p) =>
|
|
6905
|
+
return candidates().find((p) => existsSync21(p)) ?? null;
|
|
6788
6906
|
}
|
|
6789
6907
|
function load2(p) {
|
|
6790
6908
|
const path = p ?? file3();
|
|
@@ -6846,7 +6964,7 @@ function check(e) {
|
|
|
6846
6964
|
return { id: e.id, status: "ok", detail: `${e.id}:无固定路径(跳过探测)` };
|
|
6847
6965
|
}
|
|
6848
6966
|
const path = expand3(r.replace(/^link:/, ""));
|
|
6849
|
-
return
|
|
6967
|
+
return existsSync21(path) ? { id: e.id, status: "ok", detail: `${e.id}:${path}` } : missing(`${path} 不存在`);
|
|
6850
6968
|
}
|
|
6851
6969
|
return { id: e.id, status: "ok", detail: `${e.id}:kind=${e.kind} 无探测规则` };
|
|
6852
6970
|
}
|
|
@@ -6874,7 +6992,7 @@ function append4(entry, p) {
|
|
|
6874
6992
|
mkdirSync16(dirname11(path), { recursive: true });
|
|
6875
6993
|
const line = JSON.stringify(entry) + `
|
|
6876
6994
|
`;
|
|
6877
|
-
const prev =
|
|
6995
|
+
const prev = existsSync21(path) ? readFileSync18(path, "utf8") : "";
|
|
6878
6996
|
writeFileSync14(path, prev.endsWith(`
|
|
6879
6997
|
`) || !prev ? prev + line : prev + `
|
|
6880
6998
|
` + line);
|
|
@@ -6890,7 +7008,7 @@ init_paths();
|
|
|
6890
7008
|
// src/job.ts
|
|
6891
7009
|
init_paths();
|
|
6892
7010
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
6893
|
-
import { existsSync as
|
|
7011
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
6894
7012
|
import { homedir as homedir11 } from "node:os";
|
|
6895
7013
|
import { dirname as dirname12, join as join24, resolve as resolve12 } from "node:path";
|
|
6896
7014
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -6898,7 +7016,7 @@ function jobBin() {
|
|
|
6898
7016
|
const env = process.env.DIA_JOB_BIN;
|
|
6899
7017
|
if (env) {
|
|
6900
7018
|
const abs = resolve12(env);
|
|
6901
|
-
return
|
|
7019
|
+
return existsSync22(abs) ? { bin: abs } : { bin: null, error: `DIA_JOB_BIN 不存在:${abs}` };
|
|
6902
7020
|
}
|
|
6903
7021
|
const here = dirname12(fileURLToPath2(import.meta.url));
|
|
6904
7022
|
const candidates = [
|
|
@@ -6906,7 +7024,7 @@ function jobBin() {
|
|
|
6906
7024
|
join24(here, "..", "..", "packages", "job", "bin", "dia-job"),
|
|
6907
7025
|
join24(homedir11(), ".local", "bin", "dia-job")
|
|
6908
7026
|
];
|
|
6909
|
-
const found = candidates.find((p) =>
|
|
7027
|
+
const found = candidates.find((p) => existsSync22(p));
|
|
6910
7028
|
return found ? { bin: found } : { bin: null };
|
|
6911
7029
|
}
|
|
6912
7030
|
function jobRootResolved() {
|
|
@@ -6914,7 +7032,7 @@ function jobRootResolved() {
|
|
|
6914
7032
|
return process.env.DIA_JOB_ROOT;
|
|
6915
7033
|
const next = jobRoot();
|
|
6916
7034
|
const legacy = join24(homedir11(), ".local", "share", "dia-job");
|
|
6917
|
-
return !
|
|
7035
|
+
return !existsSync22(next) && existsSync22(legacy) ? legacy : next;
|
|
6918
7036
|
}
|
|
6919
7037
|
function runJobCapture(argv) {
|
|
6920
7038
|
const { bin, error } = jobBin();
|
|
@@ -6976,13 +7094,13 @@ function pkgShimPath(p) {
|
|
|
6976
7094
|
const st = statSync12(p);
|
|
6977
7095
|
if (!st.isFile() || st.size > 1024 * 1024)
|
|
6978
7096
|
return false;
|
|
6979
|
-
const fd =
|
|
7097
|
+
const fd = openSync4(p, "r");
|
|
6980
7098
|
try {
|
|
6981
7099
|
const buf = Buffer.alloc(8192);
|
|
6982
7100
|
const n = readSync(fd, buf, 0, buf.length, 0);
|
|
6983
7101
|
return /@minonl\/dia|node_modules\/(@minonl\/)?dia\//.test(buf.subarray(0, n).toString("utf8"));
|
|
6984
7102
|
} finally {
|
|
6985
|
-
|
|
7103
|
+
closeSync4(fd);
|
|
6986
7104
|
}
|
|
6987
7105
|
} catch {
|
|
6988
7106
|
return false;
|
|
@@ -7035,7 +7153,7 @@ function installShadowCheck() {
|
|
|
7035
7153
|
const name = "install_shadow";
|
|
7036
7154
|
const install = installDir();
|
|
7037
7155
|
const installNpm = npmOwnedPath(realOrSelf(install));
|
|
7038
|
-
if (!installNpm && !
|
|
7156
|
+
if (!installNpm && !existsSync23(join25(install, "install.json"))) {
|
|
7039
7157
|
return { name, status: "ok", detail: `源码运行(install=${install} 无 install.json,跳过一致性判定)` };
|
|
7040
7158
|
}
|
|
7041
7159
|
const bin = whichDia();
|
|
@@ -7050,10 +7168,20 @@ function installShadowCheck() {
|
|
|
7050
7168
|
const fix = installNpm ? `ln -sfn "$(npm prefix -g)/bin/dia" ${quoteArg(bin)}` : `ln -sfn ${quoteArg(join25(install, "bin/dia.js"))} ${quoteArg(bin)}`;
|
|
7051
7169
|
return {
|
|
7052
7170
|
name,
|
|
7053
|
-
status: "
|
|
7171
|
+
status: "warn",
|
|
7054
7172
|
detail: `安装类型不一致:install=${install}(${kind(installNpm)})但 PATH dia=${binReal}(${kind(binNpm)});修复:${fix}`
|
|
7055
7173
|
};
|
|
7056
7174
|
}
|
|
7175
|
+
function bootstrapCheck() {
|
|
7176
|
+
const stamp = readStamp();
|
|
7177
|
+
const pkg = pkgVersion();
|
|
7178
|
+
if (!stamp)
|
|
7179
|
+
return { name: "bootstrap", status: "warn", detail: "内置能力尚未装配(首次 persona add/render 或 dia collab enable 会自动装)" };
|
|
7180
|
+
if (stamp.pkg !== pkg) {
|
|
7181
|
+
return { name: "bootstrap", status: "warn", detail: `内置能力可能过期:自举戳 pkg=${stamp.pkg},当前 ${pkg};修复:dia collab enable` };
|
|
7182
|
+
}
|
|
7183
|
+
return { name: "bootstrap", status: "ok", detail: `内置能力已装配(pkg=${pkg},kit=${stamp.kit ?? "-"})` };
|
|
7184
|
+
}
|
|
7057
7185
|
function describeStale(st) {
|
|
7058
7186
|
const diff = st.added + st.removed + st.changed;
|
|
7059
7187
|
const parts = [st.added ? `新增 ${st.added}` : "", st.removed ? `删除 ${st.removed}` : "", st.changed ? `修改 ${st.changed}` : ""].filter(Boolean);
|
|
@@ -7062,7 +7190,7 @@ function describeStale(st) {
|
|
|
7062
7190
|
}
|
|
7063
7191
|
async function knowledgeCheck(id, prefix, root) {
|
|
7064
7192
|
const name = `${prefix}knowledge`;
|
|
7065
|
-
if (!
|
|
7193
|
+
if (!existsSync23(root))
|
|
7066
7194
|
return { name, status: "fail", detail: root };
|
|
7067
7195
|
const rebuild = `dia kb index --persona ${quoteArg(id)}`;
|
|
7068
7196
|
let st;
|
|
@@ -7200,20 +7328,21 @@ async function run(opts = {}) {
|
|
|
7200
7328
|
detail: `install=${install} data=${diaHome()}${install === diaHome() ? "(安装物与数据同根)" : ""}`
|
|
7201
7329
|
});
|
|
7202
7330
|
checks.push(installShadowCheck());
|
|
7331
|
+
checks.push(bootstrapCheck());
|
|
7203
7332
|
const wt = join25(install, "packages/wt/bin/dia-wt");
|
|
7204
|
-
checks.push({ name: "wt", status:
|
|
7333
|
+
checks.push({ name: "wt", status: existsSync23(wt) ? "ok" : "warn", detail: existsSync23(wt) ? wt : "dia wt 未安装(dia install.sh)" });
|
|
7205
7334
|
const jobRoot = jobRootResolved();
|
|
7206
7335
|
checks.push({
|
|
7207
7336
|
name: "job",
|
|
7208
|
-
status:
|
|
7209
|
-
detail: `${jobRoot}${
|
|
7337
|
+
status: existsSync23(jobRoot) ? "ok" : "warn",
|
|
7338
|
+
detail: `${jobRoot}${existsSync23(jobRoot) ? "" : "(未创建;dia job install 首次运行会建)"}`
|
|
7210
7339
|
});
|
|
7211
7340
|
const verdict = checks.some((c) => c.status === "fail") ? "fail" : checks.some((c) => c.status === "warn") ? "warn" : "ok";
|
|
7212
7341
|
return { persona: ids.length === 1 ? ids[0] : null, personas: ids, checks, verdict };
|
|
7213
7342
|
}
|
|
7214
7343
|
|
|
7215
7344
|
// src/env.ts
|
|
7216
|
-
import { existsSync as
|
|
7345
|
+
import { existsSync as existsSync24, readFileSync as readFileSync20 } from "node:fs";
|
|
7217
7346
|
import { homedir as homedir13 } from "node:os";
|
|
7218
7347
|
import { join as join26 } from "node:path";
|
|
7219
7348
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
@@ -7257,7 +7386,7 @@ function loadValues(cfg) {
|
|
|
7257
7386
|
return all;
|
|
7258
7387
|
}
|
|
7259
7388
|
function list6(cfg) {
|
|
7260
|
-
const files = cfg.files.map((p) => ({ path: p, exists:
|
|
7389
|
+
const files = cfg.files.map((p) => ({ path: p, exists: existsSync24(p), keys: existsSync24(p) ? Object.keys(parseFile(p)).length : 0 }));
|
|
7261
7390
|
const values = loadValues(cfg);
|
|
7262
7391
|
return { files, keys: cfg.keys.map((k) => ({ key: k, found: !!values[k] })) };
|
|
7263
7392
|
}
|
|
@@ -7298,7 +7427,7 @@ function run2(cfg, cmd, opts = {}) {
|
|
|
7298
7427
|
}
|
|
7299
7428
|
|
|
7300
7429
|
// src/bw.ts
|
|
7301
|
-
import { chmodSync as chmodSync4, existsSync as
|
|
7430
|
+
import { chmodSync as chmodSync4, existsSync as existsSync25, mkdirSync as mkdirSync17, readFileSync as readFileSync21, rmSync as rmSync7, writeFileSync as writeFileSync15 } from "node:fs";
|
|
7302
7431
|
init_paths();
|
|
7303
7432
|
import { join as join27 } from "node:path";
|
|
7304
7433
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
@@ -7513,7 +7642,7 @@ function serve(opts = {}) {
|
|
|
7513
7642
|
}
|
|
7514
7643
|
function askBroker(req, timeoutMs = 5000) {
|
|
7515
7644
|
const sock = socketFile();
|
|
7516
|
-
if (!
|
|
7645
|
+
if (!existsSync25(sock))
|
|
7517
7646
|
return Promise.resolve(null);
|
|
7518
7647
|
return new Promise((resolve, reject) => {
|
|
7519
7648
|
const conn = connect(sock);
|
|
@@ -7552,19 +7681,19 @@ function askBroker(req, timeoutMs = 5000) {
|
|
|
7552
7681
|
|
|
7553
7682
|
// packages/cli/src/index.ts
|
|
7554
7683
|
import { execFileSync as execFileSync12, spawn as spawn3, spawnSync as spawnSync5 } from "node:child_process";
|
|
7555
|
-
import { mkdirSync as mkdirSync20, openSync as
|
|
7684
|
+
import { mkdirSync as mkdirSync20, openSync as openSync5 } from "node:fs";
|
|
7556
7685
|
import { basename as basename10, join as join32 } from "node:path";
|
|
7557
|
-
import { existsSync as
|
|
7686
|
+
import { existsSync as existsSync30, readFileSync as readFileSync26, writeFileSync as writeFileSync18 } from "node:fs";
|
|
7558
7687
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
7559
7688
|
import { resolve as resolvePath, sep as pathSep } from "node:path";
|
|
7560
7689
|
|
|
7561
7690
|
// src/team.ts
|
|
7562
|
-
import { appendFileSync as appendFileSync8, cpSync as cpSync3, existsSync as
|
|
7691
|
+
import { appendFileSync as appendFileSync8, cpSync as cpSync3, existsSync as existsSync27, mkdirSync as mkdirSync18, readFileSync as readFileSync23, readdirSync as readdirSync11, rmSync as rmSync8, writeFileSync as writeFileSync16 } from "node:fs";
|
|
7563
7692
|
import { homedir as homedir15, tmpdir as tmpdir3 } from "node:os";
|
|
7564
7693
|
import { join as join29, resolve as resolve14 } from "node:path";
|
|
7565
7694
|
|
|
7566
7695
|
// src/pricing.ts
|
|
7567
|
-
import { existsSync as
|
|
7696
|
+
import { existsSync as existsSync26, readFileSync as readFileSync22 } from "node:fs";
|
|
7568
7697
|
import { homedir as homedir14 } from "node:os";
|
|
7569
7698
|
import { join as join28 } from "node:path";
|
|
7570
7699
|
var DEFAULT = {
|
|
@@ -7576,7 +7705,7 @@ function pricesFile() {
|
|
|
7576
7705
|
return process.env.DIA_PRICES_FILE || join28(homedir14(), ".config", "dia", "prices.json");
|
|
7577
7706
|
}
|
|
7578
7707
|
function loadPrices() {
|
|
7579
|
-
if (!
|
|
7708
|
+
if (!existsSync26(pricesFile()))
|
|
7580
7709
|
return { ...DEFAULT };
|
|
7581
7710
|
try {
|
|
7582
7711
|
const user = JSON.parse(readFileSync22(pricesFile(), "utf8"));
|
|
@@ -7662,7 +7791,7 @@ function judgeWorkspace(dir, fallback) {
|
|
|
7662
7791
|
function gate(id) {
|
|
7663
7792
|
const dir = runDir(id);
|
|
7664
7793
|
const need = ["plan.md", "diff.patch", "test.log", "verify.json", "redteam.json", "packet.md", "run.json"];
|
|
7665
|
-
const missing = need.filter((f) => !
|
|
7794
|
+
const missing = need.filter((f) => !existsSync27(join29(dir, f)));
|
|
7666
7795
|
if (missing.length)
|
|
7667
7796
|
return { ok: false, reason: "missing: " + missing.join(",") };
|
|
7668
7797
|
let verify, redteam, run;
|
|
@@ -7708,7 +7837,7 @@ function gate(id) {
|
|
|
7708
7837
|
return { ok: false, reason: "mock run 不能作为验收证据(请用 --acp/--dsh 真跑判据)" };
|
|
7709
7838
|
}
|
|
7710
7839
|
const workspace = String(run.workspace || "");
|
|
7711
|
-
if (!workspace || !
|
|
7840
|
+
if (!workspace || !existsSync27(workspace))
|
|
7712
7841
|
return { ok: false, reason: "run.json workspace 不存在" };
|
|
7713
7842
|
const started = Date.now();
|
|
7714
7843
|
let exit = 1, out = "";
|
|
@@ -8116,11 +8245,11 @@ Return only the JSON object.`);
|
|
|
8116
8245
|
}
|
|
8117
8246
|
function dshSessionFile(sessionId) {
|
|
8118
8247
|
const root = join29(homedir15(), ".dsh", "sessions");
|
|
8119
|
-
if (!
|
|
8248
|
+
if (!existsSync27(root))
|
|
8120
8249
|
return null;
|
|
8121
8250
|
for (const d of readdirSync11(root)) {
|
|
8122
8251
|
const f = join29(root, d, sessionId, "session.v4.jsonl.zstd");
|
|
8123
|
-
if (
|
|
8252
|
+
if (existsSync27(f))
|
|
8124
8253
|
return f;
|
|
8125
8254
|
}
|
|
8126
8255
|
return null;
|
|
@@ -8410,7 +8539,7 @@ function reject(id, reason) {
|
|
|
8410
8539
|
var DEFAULT_ACP_TIMEOUT = 600000;
|
|
8411
8540
|
|
|
8412
8541
|
// src/proposal.ts
|
|
8413
|
-
import { existsSync as
|
|
8542
|
+
import { existsSync as existsSync28, readFileSync as readFileSync24, readdirSync as readdirSync12 } from "node:fs";
|
|
8414
8543
|
import { join as join30 } from "node:path";
|
|
8415
8544
|
import { createHash as createHash10 } from "node:crypto";
|
|
8416
8545
|
init_paths();
|
|
@@ -8433,7 +8562,7 @@ function readJson3(path) {
|
|
|
8433
8562
|
}
|
|
8434
8563
|
function collectRuns(out) {
|
|
8435
8564
|
const root = join30(DATA7(), "runs");
|
|
8436
|
-
if (!
|
|
8565
|
+
if (!existsSync28(root))
|
|
8437
8566
|
return;
|
|
8438
8567
|
for (const id of readdirSync12(root)) {
|
|
8439
8568
|
const dir = join30(root, id);
|
|
@@ -8477,7 +8606,7 @@ function collectTasks(out) {
|
|
|
8477
8606
|
}
|
|
8478
8607
|
}
|
|
8479
8608
|
function collectDeps(out, path) {
|
|
8480
|
-
if (!
|
|
8609
|
+
if (!existsSync28(path))
|
|
8481
8610
|
return;
|
|
8482
8611
|
for (const e of load2(path)) {
|
|
8483
8612
|
if (e.result === "unknown" || e.support === "unknown") {
|
|
@@ -8510,7 +8639,7 @@ function expandIds(cell) {
|
|
|
8510
8639
|
return out;
|
|
8511
8640
|
}
|
|
8512
8641
|
function collectHypotheses(out, path) {
|
|
8513
|
-
if (!
|
|
8642
|
+
if (!existsSync28(path))
|
|
8514
8643
|
return;
|
|
8515
8644
|
const lines = readFileSync24(path, "utf8").split(`
|
|
8516
8645
|
`);
|
|
@@ -8552,7 +8681,7 @@ import { createHash as createHash11, randomBytes as randomBytes4 } from "node:cr
|
|
|
8552
8681
|
import {
|
|
8553
8682
|
appendFileSync as appendFileSync9,
|
|
8554
8683
|
cpSync as cpSync4,
|
|
8555
|
-
existsSync as
|
|
8684
|
+
existsSync as existsSync29,
|
|
8556
8685
|
lstatSync as lstatSync3,
|
|
8557
8686
|
mkdirSync as mkdirSync19,
|
|
8558
8687
|
readFileSync as readFileSync25,
|
|
@@ -8746,7 +8875,7 @@ function validateServiceManifest(m) {
|
|
|
8746
8875
|
}
|
|
8747
8876
|
function readServiceManifest(dir) {
|
|
8748
8877
|
const p = join31(dir, "dia.json");
|
|
8749
|
-
if (!
|
|
8878
|
+
if (!existsSync29(p))
|
|
8750
8879
|
throw new Error(`E_NO_MANIFEST: dia.json not found in ${dir}(adopted 服务需先补 dia.json)`);
|
|
8751
8880
|
let raw;
|
|
8752
8881
|
try {
|
|
@@ -9017,7 +9146,7 @@ function diaCmd() {
|
|
|
9017
9146
|
resolve15(dirname14(process.argv[1] ?? ""), "..", "src", "cli.ts"),
|
|
9018
9147
|
resolve15(dirname14(process.argv[1] ?? ""), "..", "dist", "cli.js")
|
|
9019
9148
|
];
|
|
9020
|
-
const entry = entries.find((p) =>
|
|
9149
|
+
const entry = entries.find((p) => existsSync29(p));
|
|
9021
9150
|
return entry ? `${q(process.execPath)} ${q(entry)}` : "dia";
|
|
9022
9151
|
}
|
|
9023
9152
|
function decorateStatus(text, view) {
|
|
@@ -9045,10 +9174,10 @@ var serviceDir = (id) => join31(servicesRoot(), id);
|
|
|
9045
9174
|
var serviceLockPath = (id) => join31(serviceDir(id), "service.lock.json");
|
|
9046
9175
|
var healthStatePath = (id) => process.env.DIA_SERVICE_HEALTH_FILE || join31(jobRoot2(), "tasks", `${healthJobName(id)}.state.jsonl`);
|
|
9047
9176
|
function readLockFile(id) {
|
|
9048
|
-
if (!
|
|
9177
|
+
if (!existsSync29(serviceDir(id)))
|
|
9049
9178
|
throw new Error(`E_NOT_INSTALLED: service ${id}`);
|
|
9050
9179
|
const p = serviceLockPath(id);
|
|
9051
|
-
if (!
|
|
9180
|
+
if (!existsSync29(p))
|
|
9052
9181
|
throw new Error(`E_NOT_INSTALLED: service ${id}(缺 lock)`);
|
|
9053
9182
|
try {
|
|
9054
9183
|
return JSON.parse(readFileSync25(p, "utf8"));
|
|
@@ -9069,7 +9198,7 @@ function generationOf(id) {
|
|
|
9069
9198
|
return `g-sess${(++ephemeralGen).toString(16).padStart(4, "0")}`;
|
|
9070
9199
|
}
|
|
9071
9200
|
function readHealthLines(file) {
|
|
9072
|
-
if (!
|
|
9201
|
+
if (!existsSync29(file))
|
|
9073
9202
|
return [];
|
|
9074
9203
|
const rows = [];
|
|
9075
9204
|
const lines = readFileSync25(file, "utf8").split(`
|
|
@@ -9151,7 +9280,7 @@ function listServices(opts = {}) {
|
|
|
9151
9280
|
const reg = opts.registry === null ? null : readRegistryTasks(opts.registry ?? registryPath2());
|
|
9152
9281
|
const rows = [];
|
|
9153
9282
|
const seen = new Set;
|
|
9154
|
-
if (
|
|
9283
|
+
if (existsSync29(root)) {
|
|
9155
9284
|
for (const e of readdirSync13(root, { withFileTypes: true })) {
|
|
9156
9285
|
if (!e.isDirectory() || e.name.startsWith("."))
|
|
9157
9286
|
continue;
|
|
@@ -9160,7 +9289,7 @@ function listServices(opts = {}) {
|
|
|
9160
9289
|
}
|
|
9161
9290
|
}
|
|
9162
9291
|
const adoptRoot = join31(root, "adopted");
|
|
9163
|
-
if (
|
|
9292
|
+
if (existsSync29(adoptRoot)) {
|
|
9164
9293
|
for (const e of readdirSync13(adoptRoot, { withFileTypes: true })) {
|
|
9165
9294
|
if (!e.isDirectory() || seen.has(e.name))
|
|
9166
9295
|
continue;
|
|
@@ -9448,7 +9577,7 @@ function whichTimeout1() {
|
|
|
9448
9577
|
var serviceJobName = (id) => `svc-${id}`;
|
|
9449
9578
|
var healthJobName = (id) => `svc-${id}-health`;
|
|
9450
9579
|
function readRegistryTasks(file = registryPath2()) {
|
|
9451
|
-
if (!
|
|
9580
|
+
if (!existsSync29(file))
|
|
9452
9581
|
return null;
|
|
9453
9582
|
try {
|
|
9454
9583
|
const d = JSON.parse(readFileSync25(file, "utf8"));
|
|
@@ -9470,7 +9599,7 @@ function collectManagedFiles(base, hc) {
|
|
|
9470
9599
|
const out = {};
|
|
9471
9600
|
const rel = "dia.json";
|
|
9472
9601
|
const p = join31(base, rel);
|
|
9473
|
-
if (
|
|
9602
|
+
if (existsSync29(p))
|
|
9474
9603
|
out[rel] = shaFile3(p);
|
|
9475
9604
|
if (!hc)
|
|
9476
9605
|
return out;
|
|
@@ -9499,11 +9628,11 @@ function verify4(dir, opts = {}) {
|
|
|
9499
9628
|
const svc = readServiceManifest(dir);
|
|
9500
9629
|
const entry = resolveEntry(entryCmdOf(svc), dir);
|
|
9501
9630
|
const drift = [];
|
|
9502
|
-
if (!
|
|
9631
|
+
if (!existsSync29(entry.path))
|
|
9503
9632
|
drift.push({ code: "entry_missing", detail: `entry 不存在:${entry.path}` });
|
|
9504
9633
|
else if (!isExecutableFile(entry.path))
|
|
9505
9634
|
drift.push({ code: "entry_not_executable", detail: `entry 不可执行:${entry.path}` });
|
|
9506
|
-
const lock = opts.lock === undefined ?
|
|
9635
|
+
const lock = opts.lock === undefined ? existsSync29(serviceDir(svc.id)) ? tryLock(svc.id) : null : opts.lock;
|
|
9507
9636
|
if (lock) {
|
|
9508
9637
|
if (entry.kind === "ref") {
|
|
9509
9638
|
const want = lock.entry.link ? resolve15(lock.entry.link) : null;
|
|
@@ -9540,7 +9669,7 @@ function tryLock(id) {
|
|
|
9540
9669
|
return null;
|
|
9541
9670
|
}
|
|
9542
9671
|
}
|
|
9543
|
-
var looksLikeRepo = (from) =>
|
|
9672
|
+
var looksLikeRepo = (from) => existsSync29(join31(from, "dia.json")) || existsSync29(join31(from, ".git")) || existsSync29(join31(from, "package.json"));
|
|
9544
9673
|
function linkEntry(path) {
|
|
9545
9674
|
const dir = entryDir();
|
|
9546
9675
|
mkdirSync19(dir, { recursive: true });
|
|
@@ -9548,7 +9677,7 @@ function linkEntry(path) {
|
|
|
9548
9677
|
const dest = join31(dir, name);
|
|
9549
9678
|
if (isSymlink2(dest))
|
|
9550
9679
|
unlinkSync3(dest);
|
|
9551
|
-
else if (
|
|
9680
|
+
else if (existsSync29(dest))
|
|
9552
9681
|
throw new Error(`E_CONFLICT: 稳定入口 ${dest} 已存在且不是软链`);
|
|
9553
9682
|
symlinkSync3(resolve15(path), dest);
|
|
9554
9683
|
return dest;
|
|
@@ -9573,7 +9702,7 @@ function add2(opts) {
|
|
|
9573
9702
|
let copied = false;
|
|
9574
9703
|
if (opts.from !== undefined) {
|
|
9575
9704
|
const src = resolve15(opts.from);
|
|
9576
|
-
if (!
|
|
9705
|
+
if (!existsSync29(src))
|
|
9577
9706
|
throw new Error(`E_SOURCE: path not found: ${src}`);
|
|
9578
9707
|
if (looksLikeRepo(src))
|
|
9579
9708
|
cloneInto(src, rawDir);
|
|
@@ -9601,7 +9730,7 @@ function add2(opts) {
|
|
|
9601
9730
|
if (svc.healthcheck)
|
|
9602
9731
|
healthJobInterval(svc);
|
|
9603
9732
|
const entry = resolveEntry(entryCmdOf(svc), dir);
|
|
9604
|
-
if (!
|
|
9733
|
+
if (!existsSync29(entry.path))
|
|
9605
9734
|
throw new Error(`E_UNSTABLE_ENTRY: entry 不存在:${entry.path}`);
|
|
9606
9735
|
if (!isExecutableFile(entry.path))
|
|
9607
9736
|
throw new Error(`E_UNSTABLE_ENTRY: entry 不可执行:${entry.path}`);
|
|
@@ -9633,7 +9762,7 @@ function add2(opts) {
|
|
|
9633
9762
|
err.code = code;
|
|
9634
9763
|
throw err;
|
|
9635
9764
|
};
|
|
9636
|
-
if (
|
|
9765
|
+
if (existsSync29(serviceLockPath(svc.id)))
|
|
9637
9766
|
remove3({ id: svc.id, runner });
|
|
9638
9767
|
let entryPath = entry.path;
|
|
9639
9768
|
if (entry.kind === "repo") {
|
|
@@ -9704,7 +9833,7 @@ function copyTree(from, to) {
|
|
|
9704
9833
|
cpSync4(from, to, { recursive: true, dereference: true, filter: (p) => !isRuntimeNoise(relative6(from, p)) });
|
|
9705
9834
|
}
|
|
9706
9835
|
function copyAdopted(from, to) {
|
|
9707
|
-
if (
|
|
9836
|
+
if (existsSync29(to))
|
|
9708
9837
|
throw new Error(`E_CONFLICT: ${to} 已存在`);
|
|
9709
9838
|
mkdirSync19(dirname14(to), { recursive: true });
|
|
9710
9839
|
if (statSync13(from).isDirectory())
|
|
@@ -9715,7 +9844,7 @@ function copyAdopted(from, to) {
|
|
|
9715
9844
|
}
|
|
9716
9845
|
}
|
|
9717
9846
|
function isGitRepo(p) {
|
|
9718
|
-
return
|
|
9847
|
+
return existsSync29(join31(p, ".git"));
|
|
9719
9848
|
}
|
|
9720
9849
|
function remove3(opts) {
|
|
9721
9850
|
const lock = readLockFile(opts.id);
|
|
@@ -9742,7 +9871,7 @@ function remove3(opts) {
|
|
|
9742
9871
|
function runServiceHealth(id, opts = {}) {
|
|
9743
9872
|
const root = opts.servicesRoot ?? servicesRoot();
|
|
9744
9873
|
const dir = join31(root, id);
|
|
9745
|
-
if (!
|
|
9874
|
+
if (!existsSync29(dir))
|
|
9746
9875
|
throw usageError(`E_NOT_INSTALLED: service ${id}`);
|
|
9747
9876
|
const svc = readServiceManifest(dir);
|
|
9748
9877
|
if (!svc.healthcheck)
|
|
@@ -10018,6 +10147,8 @@ async function kb(argv) {
|
|
|
10018
10147
|
continue;
|
|
10019
10148
|
let kr = [];
|
|
10020
10149
|
try {
|
|
10150
|
+
if ((await indexStatus(k.dir)).state !== "ok")
|
|
10151
|
+
await buildIndex(k.dir);
|
|
10021
10152
|
kr = await search(k.dir, q, undefined, limit);
|
|
10022
10153
|
} catch {
|
|
10023
10154
|
try {
|
|
@@ -10033,8 +10164,13 @@ async function kb(argv) {
|
|
|
10033
10164
|
kitHits++;
|
|
10034
10165
|
}
|
|
10035
10166
|
}
|
|
10036
|
-
if (kitHits)
|
|
10037
|
-
rows.
|
|
10167
|
+
if (kitHits) {
|
|
10168
|
+
const kitRows = rows.filter((r) => r.source);
|
|
10169
|
+
const personaRows = rows.filter((r) => !r.source);
|
|
10170
|
+
const kitQuota = Math.min(kitRows.length, Math.max(1, Math.floor(limit / 2)));
|
|
10171
|
+
const picked = [...personaRows.slice(0, limit - kitQuota), ...kitRows.slice(0, kitQuota)];
|
|
10172
|
+
rows = picked.sort((a, b) => (b.score ?? 0) - (a.score ?? 0)).slice(0, limit);
|
|
10173
|
+
}
|
|
10038
10174
|
const full = sub === "query" && has(args, "--full");
|
|
10039
10175
|
const bytes = sub === "query" && has(args, "--bytes");
|
|
10040
10176
|
const enrich = rows.map((r) => {
|
|
@@ -10527,7 +10663,7 @@ async function graphCli(argv) {
|
|
|
10527
10663
|
const argPath = flag(argv, "--export-html");
|
|
10528
10664
|
const positionalOut = argPath && !argPath.startsWith("-") ? argPath : "";
|
|
10529
10665
|
const outPath = flag(argv, "--out") || positionalOut || join32(diaHome(), "export", `graph-${stamp}.html`);
|
|
10530
|
-
if (
|
|
10666
|
+
if (existsSync30(outPath) && !has(argv, "--force")) {
|
|
10531
10667
|
err(`E_GRAPH: 已存在 ${outPath}(用 --force 覆盖)`);
|
|
10532
10668
|
return 2;
|
|
10533
10669
|
}
|
|
@@ -10647,7 +10783,7 @@ function spawnDetachedDelivery(args) {
|
|
|
10647
10783
|
const dir = join32(root, agent);
|
|
10648
10784
|
mkdirSync20(dir, { recursive: true });
|
|
10649
10785
|
const log = join32(dir, `deliver-${id}.log`);
|
|
10650
|
-
const fd =
|
|
10786
|
+
const fd = openSync5(log, "a");
|
|
10651
10787
|
const bin = process.argv[1];
|
|
10652
10788
|
const child = spawn3(process.execPath, [bin, "msg", "deliver", ...args, "--wait"], {
|
|
10653
10789
|
detached: true,
|
|
@@ -11012,6 +11148,8 @@ async function collabCli(argv) {
|
|
|
11012
11148
|
}
|
|
11013
11149
|
const kitInfo = sub === "enable" ? ensure(personaId, { force: true }) : null;
|
|
11014
11150
|
out(asJson ? JSON.stringify({ ...c, removed, kit: kitInfo }, null, 1) : `${sub}d: enabled=${c.enabled}${c.disabled_personas.length ? ` disabled_personas=${c.disabled_personas.join(",")}` : ""}` + (removed.length ? ` removed=${removed.length}` : "") + (kitInfo ? kitInfo.ok ? ` kit=${kitInfo.kit}` : ` ⚠ ${kitInfo.reason}` : ""));
|
|
11151
|
+
if (kitInfo && !kitInfo.ok)
|
|
11152
|
+
return 32;
|
|
11015
11153
|
return 0;
|
|
11016
11154
|
}
|
|
11017
11155
|
if (sub === "whoami") {
|
|
@@ -11538,7 +11676,7 @@ function wtCli(argv) {
|
|
|
11538
11676
|
home,
|
|
11539
11677
|
resolvePath(fileURLToPath4(new URL("../", import.meta.url)), "packages/wt/bin/dia-wt")
|
|
11540
11678
|
].filter(Boolean);
|
|
11541
|
-
const bin = candidates.find((c) =>
|
|
11679
|
+
const bin = candidates.find((c) => existsSync30(c));
|
|
11542
11680
|
if (!bin) {
|
|
11543
11681
|
err("E_WT: dia-wt 未安装(先跑 dia install.sh,或设 DIA_WT_BIN)");
|
|
11544
11682
|
return 33;
|