@yorz/cli 0.6.1 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +268 -108
- package/dist/gui/assets/{abnfDiagram-VRR7QNED-CpQSXKD3.js → abnfDiagram-VRR7QNED-Dysui3FU.js} +1 -1
- package/dist/gui/assets/{arc-BFSj3oux.js → arc-Dva0_Fbz.js} +1 -1
- package/dist/gui/assets/{architectureDiagram-ZJ3FMSHR-DUUbTneR.js → architectureDiagram-ZJ3FMSHR-CSusN0wM.js} +1 -1
- package/dist/gui/assets/{blockDiagram-677ZJIJ3-b_cB7_jE.js → blockDiagram-677ZJIJ3-Boy63uL4.js} +1 -1
- package/dist/gui/assets/{c4Diagram-LMCZKHZV-BW2WDVS6.js → c4Diagram-LMCZKHZV-DREOCesJ.js} +1 -1
- package/dist/gui/assets/channel-BAEHbRlk.js +1 -0
- package/dist/gui/assets/{chunk-2Q5K7J3B-DBPdFkwf.js → chunk-2Q5K7J3B-CQGkW5Le.js} +1 -1
- package/dist/gui/assets/{chunk-32BRIVSS-DIbss3Mf.js → chunk-32BRIVSS-ByKgaOB0.js} +1 -1
- package/dist/gui/assets/{chunk-5VM5RSS4-iGPM2FiL.js → chunk-5VM5RSS4-ouTiIpFg.js} +1 -1
- package/dist/gui/assets/{chunk-EX3LRPZG-CFO6icXh.js → chunk-EX3LRPZG-BBKKhIQU.js} +1 -1
- package/dist/gui/assets/{chunk-JWPE2WC7-BoSzxOe1.js → chunk-JWPE2WC7-i8qqnqZU.js} +1 -1
- package/dist/gui/assets/{chunk-MOJQB5TN-DenA9g0A.js → chunk-MOJQB5TN-BmLvCJEW.js} +1 -1
- package/dist/gui/assets/{chunk-RYQCIY6F-6OVqI5Jh.js → chunk-RYQCIY6F-DgIPwUtq.js} +1 -1
- package/dist/gui/assets/{chunk-V7JOEXUC-CwTJoQCL.js → chunk-V7JOEXUC-CHFlZVs7.js} +1 -1
- package/dist/gui/assets/{chunk-VR4S4FIN-D1Hv1RW-.js → chunk-VR4S4FIN-CF4gb-1V.js} +1 -1
- package/dist/gui/assets/{chunk-XXDRQBXY-5jwTXqEl.js → chunk-XXDRQBXY-6Ajr-TJy.js} +1 -1
- package/dist/gui/assets/classDiagram-OUVF2IWQ-2TSTdFv6.js +1 -0
- package/dist/gui/assets/classDiagram-v2-EOCWNBFH-2TSTdFv6.js +1 -0
- package/dist/gui/assets/{cose-bilkent-JH36ORCC-Cc8VWY9x.js → cose-bilkent-JH36ORCC-Bq1NoHo9.js} +1 -1
- package/dist/gui/assets/{cynefin-VYW2F7L2-BXFPytZ_.js → cynefin-VYW2F7L2-BLZ43yIC.js} +1 -1
- package/dist/gui/assets/{cynefinDiagram-TSTJHNR4-WZDfGA2i.js → cynefinDiagram-TSTJHNR4-DOG8J1W-.js} +1 -1
- package/dist/gui/assets/{dagre-VKFMJZFB-Dip6iJOF.js → dagre-VKFMJZFB-6s-zIAym.js} +1 -1
- package/dist/gui/assets/{diagram-FQU43EPY-CFLYoHwF.js → diagram-FQU43EPY-MdHGL1Ep.js} +1 -1
- package/dist/gui/assets/{diagram-G47NLZAW-BswWoT3h.js → diagram-G47NLZAW-vNqROz2G.js} +1 -1
- package/dist/gui/assets/{diagram-NH7WQ7WH-BizhF8Pc.js → diagram-NH7WQ7WH-mBHJAt54.js} +1 -1
- package/dist/gui/assets/{diagram-OA4YK3LP-BckN9mPI.js → diagram-OA4YK3LP-Duzu45NT.js} +1 -1
- package/dist/gui/assets/{diagram-WEI45ONY-ht6wkF4x.js → diagram-WEI45ONY-B9KIE7jm.js} +1 -1
- package/dist/gui/assets/{ebnfDiagram-CCIWWBDH-DyVIzHp5.js → ebnfDiagram-CCIWWBDH-D-VxYOb1.js} +1 -1
- package/dist/gui/assets/{erDiagram-Q63AITRT-DRFWvAAm.js → erDiagram-Q63AITRT-bGX1YWnp.js} +1 -1
- package/dist/gui/assets/{flowDiagram-23GEKE2U-CiBwda7G.js → flowDiagram-23GEKE2U-BFbLxzKU.js} +1 -1
- package/dist/gui/assets/{ganttDiagram-NO4QXBWP-vRQNKo6Y.js → ganttDiagram-NO4QXBWP-CFlioSP9.js} +1 -1
- package/dist/gui/assets/{gitGraphDiagram-IHSO6WYX-BYCaD1Fo.js → gitGraphDiagram-IHSO6WYX-9m210Kgm.js} +1 -1
- package/dist/gui/assets/index-DDGLj_Fo.js +36 -0
- package/dist/gui/assets/{infoDiagram-FWYZ7A6U-1Y32iWPH.js → infoDiagram-FWYZ7A6U-D35ODxoC.js} +1 -1
- package/dist/gui/assets/{ishikawaDiagram-FXEZZL3T-BQDQ7prq.js → ishikawaDiagram-FXEZZL3T-B-mZqJl4.js} +1 -1
- package/dist/gui/assets/{journeyDiagram-5HDEW3XC-DSWI24Bt.js → journeyDiagram-5HDEW3XC-CmFLCu-y.js} +1 -1
- package/dist/gui/assets/{kanban-definition-HUTT4EX6-fiE0W_uC.js → kanban-definition-HUTT4EX6-C-risdsz.js} +1 -1
- package/dist/gui/assets/{linear-DqWevqMh.js → linear-D5TY5eoS.js} +1 -1
- package/dist/gui/assets/{mermaid.core-bsNbTKFB.js → mermaid.core-wGjSg1h-.js} +4 -4
- package/dist/gui/assets/{mindmap-definition-LN4V7U3C-DnUeh13j.js → mindmap-definition-LN4V7U3C-BSdCxt4H.js} +1 -1
- package/dist/gui/assets/{pegDiagram-2B236MQR-DE_8gOxy.js → pegDiagram-2B236MQR-DrexK9bW.js} +1 -1
- package/dist/gui/assets/{pieDiagram-ENE6RG2P-Wf_jl50X.js → pieDiagram-ENE6RG2P-ay6UKmgt.js} +1 -1
- package/dist/gui/assets/{quadrantDiagram-ABIIQ3AL-Dt-Yn4ZI.js → quadrantDiagram-ABIIQ3AL-DgoOnLZO.js} +1 -1
- package/dist/gui/assets/{railroadDiagram-RFXS5EU6-0I6kqmlH.js → railroadDiagram-RFXS5EU6-Dsg3x2_p.js} +1 -1
- package/dist/gui/assets/{requirementDiagram-TGXJPOKE-Dozq39w_.js → requirementDiagram-TGXJPOKE-BtbCKvwF.js} +1 -1
- package/dist/gui/assets/{sankeyDiagram-HTMAVEWB-Cs7yO0KJ.js → sankeyDiagram-HTMAVEWB-TabZvNT3.js} +1 -1
- package/dist/gui/assets/{sequenceDiagram-DBY2YBRQ-EQLpVCpV.js → sequenceDiagram-DBY2YBRQ-C53WsGFo.js} +1 -1
- package/dist/gui/assets/{sizeCapture-X5ZJPWSS-BXUb6X9N.js → sizeCapture-X5ZJPWSS-D_JRhNnb.js} +1 -1
- package/dist/gui/assets/{stateDiagram-2N3HPSRC-CYHgCnOc.js → stateDiagram-2N3HPSRC-D-_V4W7N.js} +1 -1
- package/dist/gui/assets/stateDiagram-v2-6OUMAXLB-COKZr5A4.js +1 -0
- package/dist/gui/assets/{swimlanes-5IMT3BWC-BgsUQUHx.js → swimlanes-5IMT3BWC-DgyOlILO.js} +2 -2
- package/dist/gui/assets/swimlanesDiagram-G3AALYLV-BaU_Y0XV.js +8 -0
- package/dist/gui/assets/{timeline-definition-FHXFAJF6-CQJufImP.js → timeline-definition-FHXFAJF6-7M8Rj4NA.js} +1 -1
- package/dist/gui/assets/{vennDiagram-L72KCM5P-L-2iYmD5.js → vennDiagram-L72KCM5P-DVyooCr2.js} +1 -1
- package/dist/gui/assets/{wardleyDiagram-EHGQE667-BamRRrE7.js → wardleyDiagram-EHGQE667-CYry07bZ.js} +1 -1
- package/dist/gui/assets/{xychartDiagram-FW5EYKEG-itKwurP4.js → xychartDiagram-FW5EYKEG-Dvx8ojch.js} +1 -1
- package/dist/gui/index.html +1 -1
- package/package.json +1 -1
- package/dist/gui/assets/channel-ChMv_4IC.js +0 -1
- package/dist/gui/assets/classDiagram-OUVF2IWQ-YMNyCLvX.js +0 -1
- package/dist/gui/assets/classDiagram-v2-EOCWNBFH-YMNyCLvX.js +0 -1
- package/dist/gui/assets/index-DzV2HQw-.js +0 -36
- package/dist/gui/assets/stateDiagram-v2-6OUMAXLB-CqWHqtRs.js +0 -1
- package/dist/gui/assets/swimlanesDiagram-G3AALYLV-CoZVjlW6.js +0 -8
package/dist/cli/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { homedir, platform
|
|
2
|
+
import { homedir, platform } from "node:os";
|
|
3
3
|
import { Command, Option } from "commander";
|
|
4
4
|
import { stat, mkdir, readFile, writeFile, rename, rm, access, readdir, appendFile, copyFile } from "node:fs/promises";
|
|
5
5
|
import { join, isAbsolute, resolve, basename as basename$1, dirname, extname, sep, relative, normalize } from "node:path";
|
|
6
6
|
import { createHash, randomUUID, randomBytes } from "node:crypto";
|
|
7
7
|
import { existsSync, openSync, closeSync, statSync, readSync, mkdirSync, watch, createReadStream } from "node:fs";
|
|
8
|
-
import { spawn, execFile } from "node:child_process";
|
|
8
|
+
import { spawn, execFile, execFileSync } from "node:child_process";
|
|
9
9
|
import { promisify } from "node:util";
|
|
10
10
|
import { serve } from "@hono/node-server";
|
|
11
|
+
import { isIP } from "node:net";
|
|
11
12
|
import { Hono } from "hono";
|
|
12
13
|
import { streamSSE } from "hono/streaming";
|
|
13
14
|
import { fileURLToPath } from "node:url";
|
|
@@ -22,7 +23,7 @@ import { createOpencode } from "@opencode-ai/sdk";
|
|
|
22
23
|
import { createInterface as createInterface$1 } from "node:readline/promises";
|
|
23
24
|
import MarkdownIt from "markdown-it";
|
|
24
25
|
const name = "@yorz/cli";
|
|
25
|
-
const version = "0.6.
|
|
26
|
+
const version = "0.6.4";
|
|
26
27
|
const type = "module";
|
|
27
28
|
const description = "";
|
|
28
29
|
const bin = { "yorz": "./dist/cli/index.js" };
|
|
@@ -861,12 +862,13 @@ function sanitize(text) {
|
|
|
861
862
|
return cleaned.replace(/^-+|-+$/g, "").slice(0, 64);
|
|
862
863
|
}
|
|
863
864
|
function uniquify(name2, existing) {
|
|
864
|
-
|
|
865
|
+
const occupied = new Set(existing.map((item) => item.toLocaleLowerCase("en-US")));
|
|
866
|
+
if (!occupied.has(name2.toLocaleLowerCase("en-US"))) return name2;
|
|
865
867
|
const ext = extname(name2);
|
|
866
868
|
const base = stripExt(name2);
|
|
867
869
|
for (let i = 1; i < 1e3; i++) {
|
|
868
870
|
const candidate = `${base}-${i}${ext}`;
|
|
869
|
-
if (!
|
|
871
|
+
if (!occupied.has(candidate.toLocaleLowerCase("en-US"))) return candidate;
|
|
870
872
|
}
|
|
871
873
|
return `${base}-${randomUUID().slice(0, 4)}${ext}`;
|
|
872
874
|
}
|
|
@@ -1712,6 +1714,22 @@ function createSessionsRoutes(resolveProject) {
|
|
|
1712
1714
|
return app;
|
|
1713
1715
|
}
|
|
1714
1716
|
const execFileP$1 = promisify(execFile);
|
|
1717
|
+
function withHiddenWindowsConsole(options, platform2 = process.platform) {
|
|
1718
|
+
if (platform2 !== "win32") return options;
|
|
1719
|
+
return { ...options, windowsHide: true };
|
|
1720
|
+
}
|
|
1721
|
+
async function execFileWithoutWindow(file, args, options) {
|
|
1722
|
+
const result = await execFileP$1(file, args, withHiddenWindowsConsole(options));
|
|
1723
|
+
return { stdout: result.stdout, stderr: result.stderr };
|
|
1724
|
+
}
|
|
1725
|
+
function spawnWithoutWindow(command, args, options) {
|
|
1726
|
+
return spawn(command, args, withHiddenWindowsConsole(options));
|
|
1727
|
+
}
|
|
1728
|
+
function resolveBrowserOpenInvocation(platform2, url) {
|
|
1729
|
+
if (platform2 === "win32") return { command: "explorer.exe", args: [url] };
|
|
1730
|
+
if (platform2 === "darwin") return { command: "open", args: [url] };
|
|
1731
|
+
return { command: "xdg-open", args: [url] };
|
|
1732
|
+
}
|
|
1715
1733
|
class GitError extends Error {
|
|
1716
1734
|
code;
|
|
1717
1735
|
stderr;
|
|
@@ -1766,7 +1784,7 @@ function assertSafeRelativePath(cwd, p) {
|
|
|
1766
1784
|
}
|
|
1767
1785
|
async function runGit(cwd, args) {
|
|
1768
1786
|
try {
|
|
1769
|
-
const result = await
|
|
1787
|
+
const result = await execFileWithoutWindow("git", args, {
|
|
1770
1788
|
cwd,
|
|
1771
1789
|
encoding: "utf8",
|
|
1772
1790
|
maxBuffer: 16 * 1024 * 1024
|
|
@@ -1785,7 +1803,7 @@ async function runGitChecked(cwd, args) {
|
|
|
1785
1803
|
}
|
|
1786
1804
|
async function runGitRaw(cwd, args) {
|
|
1787
1805
|
try {
|
|
1788
|
-
const result = await
|
|
1806
|
+
const result = await execFileWithoutWindow("git", args, {
|
|
1789
1807
|
cwd,
|
|
1790
1808
|
encoding: "utf8",
|
|
1791
1809
|
maxBuffer: 16 * 1024 * 1024
|
|
@@ -3404,6 +3422,8 @@ class CommandManager {
|
|
|
3404
3422
|
*/
|
|
3405
3423
|
pendingEnds = /* @__PURE__ */ new Map();
|
|
3406
3424
|
persisted = /* @__PURE__ */ new Set();
|
|
3425
|
+
/** 记录由 API 主动停止的运行,防止 Windows exit 事件把 killed 覆盖成 exited。 */
|
|
3426
|
+
intentionalStops = /* @__PURE__ */ new Set();
|
|
3407
3427
|
initPromise = null;
|
|
3408
3428
|
/** Idempotent startup pass: reap leftovers, drop expired records. */
|
|
3409
3429
|
init() {
|
|
@@ -3494,7 +3514,9 @@ class CommandManager {
|
|
|
3494
3514
|
shell: true,
|
|
3495
3515
|
cwd: this.projectPath,
|
|
3496
3516
|
env: process.env,
|
|
3497
|
-
detached
|
|
3517
|
+
// POSIX 依赖独立进程组发送负 PID 信号;Windows 使用 taskkill /T,且 detached
|
|
3518
|
+
// 会导致继承的日志文件描述符失效,所以 Windows 必须保持 attached。
|
|
3519
|
+
detached: process.platform !== "win32",
|
|
3498
3520
|
// No pipes: the child writes straight into the log fd. Keeps a chatty
|
|
3499
3521
|
// dev server from buffering through this process, and lets the REST
|
|
3500
3522
|
// first paint and the SSE tail read from one single source.
|
|
@@ -3570,6 +3592,7 @@ class CommandManager {
|
|
|
3570
3592
|
this.runSubscribers.delete(runId);
|
|
3571
3593
|
this.persisted.delete(runId);
|
|
3572
3594
|
this.pendingEnds.delete(runId);
|
|
3595
|
+
this.intentionalStops.delete(runId);
|
|
3573
3596
|
this.notifyRuns();
|
|
3574
3597
|
return true;
|
|
3575
3598
|
}
|
|
@@ -3628,23 +3651,12 @@ class CommandManager {
|
|
|
3628
3651
|
for (const [runId, child] of this.children) {
|
|
3629
3652
|
const pid = child.pid;
|
|
3630
3653
|
if (!pid) continue;
|
|
3631
|
-
|
|
3632
|
-
process.kill(-pid, "SIGKILL");
|
|
3633
|
-
} catch {
|
|
3634
|
-
try {
|
|
3635
|
-
process.kill(pid, "SIGKILL");
|
|
3636
|
-
} catch {
|
|
3637
|
-
}
|
|
3638
|
-
}
|
|
3654
|
+
killKnownProcessTreeSync(pid);
|
|
3639
3655
|
this.children.delete(runId);
|
|
3640
3656
|
}
|
|
3641
3657
|
for (const t of this.tailers.values()) t.stop();
|
|
3642
3658
|
}
|
|
3643
|
-
/**
|
|
3644
|
-
* Startup pass. Any record still marked `running` belongs to a previous
|
|
3645
|
-
* service process: kill it if it somehow survived (service SIGKILLed), then
|
|
3646
|
-
* mark it `killed`. Also drops records that finished long ago.
|
|
3647
|
-
*/
|
|
3659
|
+
/** 将上次运行遗留的记录标记为结束,并清理超过保留期的记录。 */
|
|
3648
3660
|
async reap() {
|
|
3649
3661
|
const runs = await this.store.list().catch(() => []);
|
|
3650
3662
|
if (runs.length === 0) return;
|
|
@@ -3654,8 +3666,10 @@ class CommandManager {
|
|
|
3654
3666
|
for (const run of runs) {
|
|
3655
3667
|
if (run.status === "running") {
|
|
3656
3668
|
if (run.pid > 0 && isAlive(run.pid)) {
|
|
3657
|
-
|
|
3658
|
-
|
|
3669
|
+
log$3().warn("ignored unverified persisted command pid", {
|
|
3670
|
+
runId: run.runId,
|
|
3671
|
+
pid: run.pid
|
|
3672
|
+
});
|
|
3659
3673
|
}
|
|
3660
3674
|
kept.push({ ...run, status: "killed", endedAt: run.endedAt ?? now, exitCode: null });
|
|
3661
3675
|
continue;
|
|
@@ -3671,22 +3685,37 @@ class CommandManager {
|
|
|
3671
3685
|
}
|
|
3672
3686
|
}
|
|
3673
3687
|
async terminate(run) {
|
|
3688
|
+
this.intentionalStops.add(run.runId);
|
|
3674
3689
|
if (run.pid > 0) {
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
}
|
|
3682
|
-
|
|
3683
|
-
|
|
3690
|
+
const child = this.children.get(run.runId);
|
|
3691
|
+
if (process.platform === "win32") {
|
|
3692
|
+
if (child?.pid === run.pid) {
|
|
3693
|
+
await killWindowsProcessTree(run.pid);
|
|
3694
|
+
const exited = await waitForExit(run.pid, STOP_GRACE_MS);
|
|
3695
|
+
if (!exited) throw new Error(`Windows command process tree did not exit: ${run.pid}`);
|
|
3696
|
+
} else {
|
|
3697
|
+
if (isAlive(run.pid)) {
|
|
3698
|
+
throw new Error(`refused to kill unverified Windows command pid: ${run.pid}`);
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
} else {
|
|
3702
|
+
killPosixProcessGroup(run.pid, "SIGTERM");
|
|
3703
|
+
const exited = await waitForExit(run.pid, STOP_GRACE_MS);
|
|
3704
|
+
if (!exited) {
|
|
3705
|
+
log$3().warn("command did not exit on SIGTERM, escalating", {
|
|
3706
|
+
runId: run.runId,
|
|
3707
|
+
pid: run.pid
|
|
3708
|
+
});
|
|
3709
|
+
killPosixProcessGroup(run.pid, "SIGKILL");
|
|
3710
|
+
await waitForExit(run.pid, STOP_GRACE_MS);
|
|
3711
|
+
}
|
|
3684
3712
|
}
|
|
3685
3713
|
}
|
|
3686
3714
|
this.children.delete(run.runId);
|
|
3687
3715
|
await this.markRunEnded(run.runId, "killed", null, "SIGTERM");
|
|
3688
3716
|
}
|
|
3689
3717
|
async handleExit(runId, status, exitCode, signal) {
|
|
3718
|
+
if (this.intentionalStops.has(runId)) return;
|
|
3690
3719
|
if (!this.persisted.has(runId)) {
|
|
3691
3720
|
this.pendingEnds.set(runId, { status, exitCode, signal: signal ?? null });
|
|
3692
3721
|
return;
|
|
@@ -3796,7 +3825,7 @@ function isAlive(pid) {
|
|
|
3796
3825
|
return false;
|
|
3797
3826
|
}
|
|
3798
3827
|
}
|
|
3799
|
-
function
|
|
3828
|
+
function killPosixProcessGroup(pid, signal) {
|
|
3800
3829
|
try {
|
|
3801
3830
|
process.kill(-pid, signal);
|
|
3802
3831
|
} catch {
|
|
@@ -3806,6 +3835,27 @@ function killGroup(pid, signal) {
|
|
|
3806
3835
|
}
|
|
3807
3836
|
}
|
|
3808
3837
|
}
|
|
3838
|
+
async function killWindowsProcessTree(pid) {
|
|
3839
|
+
await new Promise((resolve2, reject) => {
|
|
3840
|
+
execFile("taskkill.exe", ["/PID", String(pid), "/T", "/F"], { windowsHide: true }, (error) => {
|
|
3841
|
+
if (!error || !isAlive(pid)) resolve2();
|
|
3842
|
+
else reject(error);
|
|
3843
|
+
});
|
|
3844
|
+
});
|
|
3845
|
+
}
|
|
3846
|
+
function killKnownProcessTreeSync(pid) {
|
|
3847
|
+
if (process.platform === "win32") {
|
|
3848
|
+
try {
|
|
3849
|
+
execFileSync("taskkill.exe", ["/PID", String(pid), "/T", "/F"], {
|
|
3850
|
+
stdio: "ignore",
|
|
3851
|
+
windowsHide: true
|
|
3852
|
+
});
|
|
3853
|
+
} catch {
|
|
3854
|
+
}
|
|
3855
|
+
return;
|
|
3856
|
+
}
|
|
3857
|
+
killPosixProcessGroup(pid, "SIGKILL");
|
|
3858
|
+
}
|
|
3809
3859
|
async function waitForExit(pid, timeoutMs) {
|
|
3810
3860
|
const until = Date.now() + timeoutMs;
|
|
3811
3861
|
while (Date.now() < until) {
|
|
@@ -4289,11 +4339,9 @@ class WorktreeManager {
|
|
|
4289
4339
|
const head = await runGitChecked(mainPath, ["rev-parse", "HEAD"]);
|
|
4290
4340
|
const mergeCommit = head.stdout.trim();
|
|
4291
4341
|
await this.migrateSessions(wtPath, mainPath);
|
|
4292
|
-
await
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
}
|
|
4296
|
-
await runGitRaw(mainPath, ["branch", "-d", branch]);
|
|
4342
|
+
await this.registry.release(entry.id);
|
|
4343
|
+
await removeMergedWorktree(mainPath, wtPath);
|
|
4344
|
+
await deleteWorktreeBranch(mainPath, branch, "-d");
|
|
4297
4345
|
await this.registry.remove(entry.id);
|
|
4298
4346
|
if (mainEntry) {
|
|
4299
4347
|
await this.registry.reload(mainEntry.id);
|
|
@@ -4320,15 +4368,21 @@ class WorktreeManager {
|
|
|
4320
4368
|
const { mainPath, branch } = entry.worktree;
|
|
4321
4369
|
const wtPath = entry.path;
|
|
4322
4370
|
if (existsSync(wtPath)) {
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4371
|
+
if (existsSync(join(wtPath, ".git"))) {
|
|
4372
|
+
const status = await runGitChecked(wtPath, ["status", "--porcelain"]);
|
|
4373
|
+
if (status.stdout.trim().length > 0) {
|
|
4374
|
+
throw new GitError("dirty", "存在未提交 git 的变更");
|
|
4375
|
+
}
|
|
4326
4376
|
}
|
|
4327
|
-
await trash(wtPath);
|
|
4328
4377
|
}
|
|
4378
|
+
await this.registry.release(worktreeProjectId);
|
|
4379
|
+
await trashWorktreePath(wtPath);
|
|
4329
4380
|
if (existsSync(mainPath)) {
|
|
4330
|
-
await runGitRaw(mainPath, ["worktree", "prune"]);
|
|
4331
|
-
|
|
4381
|
+
const prune = await runGitRaw(mainPath, ["worktree", "prune"]);
|
|
4382
|
+
if (prune.code !== 0) {
|
|
4383
|
+
throw new GitError("worktree_prune_failed", "git worktree prune 失败", prune.stderr);
|
|
4384
|
+
}
|
|
4385
|
+
await deleteWorktreeBranch(mainPath, branch, "-D");
|
|
4332
4386
|
}
|
|
4333
4387
|
await this.registry.remove(worktreeProjectId);
|
|
4334
4388
|
this.onProjectsChanged?.();
|
|
@@ -4413,6 +4467,41 @@ class WorktreeManager {
|
|
|
4413
4467
|
};
|
|
4414
4468
|
}
|
|
4415
4469
|
}
|
|
4470
|
+
async function removeMergedWorktree(mainPath, wtPath) {
|
|
4471
|
+
const normal = await runGitRaw(mainPath, ["worktree", "remove", wtPath]);
|
|
4472
|
+
if (existsSync(wtPath)) {
|
|
4473
|
+
await runGitRaw(mainPath, ["worktree", "remove", "--force", wtPath]);
|
|
4474
|
+
}
|
|
4475
|
+
if (existsSync(wtPath)) await trashWorktreePath(wtPath);
|
|
4476
|
+
const prune = await runGitRaw(mainPath, ["worktree", "prune"]);
|
|
4477
|
+
if (prune.code !== 0) {
|
|
4478
|
+
throw new GitError("worktree_prune_failed", "git worktree prune 失败", prune.stderr);
|
|
4479
|
+
}
|
|
4480
|
+
if (normal.code !== 0) {
|
|
4481
|
+
worktreeLog().warn("normal worktree removal required recovery cleanup", {
|
|
4482
|
+
path: wtPath,
|
|
4483
|
+
stderr: normal.stderr
|
|
4484
|
+
});
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
async function trashWorktreePath(wtPath) {
|
|
4488
|
+
if (!existsSync(wtPath)) return;
|
|
4489
|
+
try {
|
|
4490
|
+
await trash(wtPath);
|
|
4491
|
+
} catch (error) {
|
|
4492
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
4493
|
+
throw new GitError("worktree_remove_failed", `worktree 目录删除失败:${wtPath};${detail}`);
|
|
4494
|
+
}
|
|
4495
|
+
if (existsSync(wtPath)) {
|
|
4496
|
+
throw new GitError("worktree_remove_failed", `worktree 目录仍然存在:${wtPath}`);
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4499
|
+
async function deleteWorktreeBranch(mainPath, branch, mode) {
|
|
4500
|
+
const result = await runGitRaw(mainPath, ["branch", mode, branch]);
|
|
4501
|
+
if (result.code !== 0) {
|
|
4502
|
+
throw new GitError("branch_remove_failed", `worktree 分支删除失败:${branch}`, result.stderr);
|
|
4503
|
+
}
|
|
4504
|
+
}
|
|
4416
4505
|
async function detectDefaultBranch(mainPath) {
|
|
4417
4506
|
const res = await runGitChecked(mainPath, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
4418
4507
|
const name2 = res.stdout.trim();
|
|
@@ -4569,6 +4658,14 @@ function createApp(opts) {
|
|
|
4569
4658
|
else httpLog.debug("request", meta);
|
|
4570
4659
|
});
|
|
4571
4660
|
const api = new Hono();
|
|
4661
|
+
if (opts.shutdown) {
|
|
4662
|
+
api.post("/internal/shutdown", (c) => {
|
|
4663
|
+
const token = c.req.header("x-yorz-shutdown-token");
|
|
4664
|
+
if (token !== opts.shutdown.token) return c.json({ error: "Forbidden" }, 403);
|
|
4665
|
+
setTimeout(opts.shutdown.request, 0);
|
|
4666
|
+
return c.json({ accepted: true }, 202);
|
|
4667
|
+
});
|
|
4668
|
+
}
|
|
4572
4669
|
const resolveProject = (id) => opts.registry.getOrCreate(id);
|
|
4573
4670
|
const projectsBus = new RegistryEventBus();
|
|
4574
4671
|
projectsBus.start(opts.registry.configPath());
|
|
@@ -5775,7 +5872,10 @@ class SessionManager {
|
|
|
5775
5872
|
running = /* @__PURE__ */ new Set();
|
|
5776
5873
|
/** Kind of sessions discovered via `listSessions()` but absent from the store. */
|
|
5777
5874
|
discoveredKinds = /* @__PURE__ */ new Map();
|
|
5875
|
+
/** 后台派发任务;项目关闭必须等待它们完成后才能删除 worktree。 */
|
|
5876
|
+
inFlight = /* @__PURE__ */ new Set();
|
|
5778
5877
|
statusEmitter = new EventEmitter();
|
|
5878
|
+
disposing = false;
|
|
5779
5879
|
emitterFor(sid) {
|
|
5780
5880
|
let e = this.emitters.get(sid);
|
|
5781
5881
|
if (!e) {
|
|
@@ -5909,6 +6009,7 @@ class SessionManager {
|
|
|
5909
6009
|
const session = await adapter.resumeSession(sid);
|
|
5910
6010
|
const ls = { kind, session };
|
|
5911
6011
|
this.live.set(sid, ls);
|
|
6012
|
+
if (this.disposing) session.abort();
|
|
5912
6013
|
return ls;
|
|
5913
6014
|
}
|
|
5914
6015
|
async send(sid, prompt) {
|
|
@@ -5920,7 +6021,7 @@ class SessionManager {
|
|
|
5920
6021
|
});
|
|
5921
6022
|
this.setRunning(sid, true);
|
|
5922
6023
|
agentLog().info("dispatch start", { sessionId: sid, runId, promptLength: prompt.length });
|
|
5923
|
-
|
|
6024
|
+
const task = (async () => {
|
|
5924
6025
|
try {
|
|
5925
6026
|
const ls = await this.ensureLive(sid);
|
|
5926
6027
|
for await (const ev of ls.session.send(prompt)) {
|
|
@@ -5957,6 +6058,11 @@ class SessionManager {
|
|
|
5957
6058
|
emitter.emit("done", currentSid);
|
|
5958
6059
|
}
|
|
5959
6060
|
})();
|
|
6061
|
+
this.inFlight.add(task);
|
|
6062
|
+
void task.then(
|
|
6063
|
+
() => this.inFlight.delete(task),
|
|
6064
|
+
() => this.inFlight.delete(task)
|
|
6065
|
+
);
|
|
5960
6066
|
return {
|
|
5961
6067
|
runId,
|
|
5962
6068
|
sessionId: sid,
|
|
@@ -5999,9 +6105,15 @@ class SessionManager {
|
|
|
5999
6105
|
return true;
|
|
6000
6106
|
}
|
|
6001
6107
|
async dispose() {
|
|
6108
|
+
this.disposing = true;
|
|
6109
|
+
for (const session of new Set([...this.live.values()].map((item) => item.session))) {
|
|
6110
|
+
session.abort();
|
|
6111
|
+
}
|
|
6112
|
+
await Promise.allSettled([...this.inFlight]);
|
|
6002
6113
|
await this.adapters.dispose();
|
|
6003
6114
|
this.live.clear();
|
|
6004
6115
|
this.emitters.clear();
|
|
6116
|
+
this.running.clear();
|
|
6005
6117
|
}
|
|
6006
6118
|
}
|
|
6007
6119
|
const execFileP = promisify(execFile);
|
|
@@ -6143,15 +6255,24 @@ class ProjectRegistry {
|
|
|
6143
6255
|
return await addProject(normalized, this.globalConfigPath);
|
|
6144
6256
|
}
|
|
6145
6257
|
async remove(id) {
|
|
6258
|
+
await this.release(id).catch(() => {
|
|
6259
|
+
});
|
|
6260
|
+
return await removeProject(id, this.globalConfigPath);
|
|
6261
|
+
}
|
|
6262
|
+
/**
|
|
6263
|
+
* 关闭并移除项目的缓存实例,但保留全局 registry 配置供失败恢复。
|
|
6264
|
+
*
|
|
6265
|
+
* @param id 要释放的项目 id。
|
|
6266
|
+
* @returns 缓存实例关闭完成后结束;关闭失败会原样抛出。
|
|
6267
|
+
*/
|
|
6268
|
+
async release(id) {
|
|
6146
6269
|
const cached = this.cache.get(id);
|
|
6147
|
-
if (cached)
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
}
|
|
6270
|
+
if (!cached) return;
|
|
6271
|
+
try {
|
|
6272
|
+
await cached.instance.close();
|
|
6273
|
+
} finally {
|
|
6152
6274
|
this.cache.delete(id);
|
|
6153
6275
|
}
|
|
6154
|
-
return await removeProject(id, this.globalConfigPath);
|
|
6155
6276
|
}
|
|
6156
6277
|
/**
|
|
6157
6278
|
* Drop the cached instance for a project so the next getOrCreate() rebuilds
|
|
@@ -6159,13 +6280,8 @@ class ProjectRegistry {
|
|
|
6159
6280
|
* project's `.yorz/config.json` changes (e.g. specsDir or agent override).
|
|
6160
6281
|
*/
|
|
6161
6282
|
async reload(id) {
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
try {
|
|
6165
|
-
await cached.instance.close();
|
|
6166
|
-
} catch {
|
|
6167
|
-
}
|
|
6168
|
-
this.cache.delete(id);
|
|
6283
|
+
await this.release(id).catch(() => {
|
|
6284
|
+
});
|
|
6169
6285
|
}
|
|
6170
6286
|
async closeAll() {
|
|
6171
6287
|
const tasks = [];
|
|
@@ -6465,10 +6581,20 @@ const DEFAULT_PORT = 7423;
|
|
|
6465
6581
|
const MAX_PORT_TRIES = 10;
|
|
6466
6582
|
const DEFAULT_HOST = "127.0.0.1";
|
|
6467
6583
|
function isLoopbackHost(host) {
|
|
6468
|
-
|
|
6584
|
+
const normalized = host.trim().toLowerCase().replace(/^\[|\]$/g, "");
|
|
6585
|
+
if (normalized === "localhost") return true;
|
|
6586
|
+
if (isIP(normalized) === 4) return normalized.startsWith("127.");
|
|
6587
|
+
if (isIP(normalized) === 6) {
|
|
6588
|
+
return normalized === "::1" || normalized === "0:0:0:0:0:0:0:1";
|
|
6589
|
+
}
|
|
6590
|
+
return false;
|
|
6469
6591
|
}
|
|
6470
6592
|
const log$1 = () => getLogger().child("serve");
|
|
6471
6593
|
async function start(opts = {}) {
|
|
6594
|
+
const host = opts.host?.trim() || DEFAULT_HOST;
|
|
6595
|
+
if (!isLoopbackHost(host)) {
|
|
6596
|
+
throw new Error(`host must be a loopback address: ${host}`);
|
|
6597
|
+
}
|
|
6472
6598
|
const registry = new ProjectRegistry({ globalConfigPath: opts.globalConfigPath });
|
|
6473
6599
|
const cwd = opts.cwd ?? process.cwd();
|
|
6474
6600
|
if (!opts.noRegisterCwd && existsSync(join(cwd, ".yorz"))) {
|
|
@@ -6480,18 +6606,17 @@ async function start(opts = {}) {
|
|
|
6480
6606
|
const projects = await registry.list();
|
|
6481
6607
|
const systemNotifications = new SystemNotificationCenter();
|
|
6482
6608
|
systemNotifications.startVersionChecks();
|
|
6483
|
-
const app = createApp({
|
|
6484
|
-
|
|
6609
|
+
const app = createApp({
|
|
6610
|
+
registry,
|
|
6611
|
+
guiRoot: opts.guiRoot,
|
|
6612
|
+
systemNotifications,
|
|
6613
|
+
shutdown: opts.shutdownToken && opts.onShutdownRequest ? { token: opts.shutdownToken, request: opts.onShutdownRequest } : void 0
|
|
6614
|
+
});
|
|
6485
6615
|
const port = await listen(app.fetch, opts.port ?? DEFAULT_PORT, host);
|
|
6486
6616
|
const url = `http://localhost:${port.port}/`;
|
|
6487
|
-
console.log(
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
for (const lanUrl of listLanUrls(port.port)) {
|
|
6491
|
-
console.log(` LAN: ${lanUrl}`);
|
|
6492
|
-
}
|
|
6493
|
-
log$1().warn("service bound to a non-loopback address", { host, port: port.port });
|
|
6494
|
-
}
|
|
6617
|
+
console.log(
|
|
6618
|
+
`YorZ Service ready at ${url} (${projects.length} project${projects.length === 1 ? "" : "s"})`
|
|
6619
|
+
);
|
|
6495
6620
|
for (const p of projects) {
|
|
6496
6621
|
console.log(` - ${p.name} -> ${p.path}`);
|
|
6497
6622
|
}
|
|
@@ -6563,23 +6688,16 @@ async function listen(fetchHandler, preferredPort, hostname) {
|
|
|
6563
6688
|
log$1().error("failed to bind any port", { preferredPort, tries: MAX_PORT_TRIES, err: fatal });
|
|
6564
6689
|
throw fatal;
|
|
6565
6690
|
}
|
|
6566
|
-
function listLanUrls(port) {
|
|
6567
|
-
const urls = [];
|
|
6568
|
-
const ifaces = networkInterfaces();
|
|
6569
|
-
for (const name2 of Object.keys(ifaces)) {
|
|
6570
|
-
for (const info of ifaces[name2] ?? []) {
|
|
6571
|
-
if (info.family === "IPv4" && !info.internal) {
|
|
6572
|
-
urls.push(`http://${info.address}:${port}/`);
|
|
6573
|
-
}
|
|
6574
|
-
}
|
|
6575
|
-
}
|
|
6576
|
-
return urls;
|
|
6577
|
-
}
|
|
6578
6691
|
async function tryOpenBrowser(url) {
|
|
6579
|
-
const
|
|
6580
|
-
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
6692
|
+
const invocation = resolveBrowserOpenInvocation(process.platform, url);
|
|
6581
6693
|
try {
|
|
6582
|
-
|
|
6694
|
+
const child = spawnWithoutWindow(invocation.command, invocation.args, {
|
|
6695
|
+
stdio: "ignore",
|
|
6696
|
+
detached: true
|
|
6697
|
+
});
|
|
6698
|
+
child.once("error", () => {
|
|
6699
|
+
});
|
|
6700
|
+
child.unref();
|
|
6583
6701
|
} catch {
|
|
6584
6702
|
}
|
|
6585
6703
|
}
|
|
@@ -6632,12 +6750,28 @@ async function runServe(opts) {
|
|
|
6632
6750
|
if (!opts.foreground) {
|
|
6633
6751
|
return startBackgroundServe(opts);
|
|
6634
6752
|
}
|
|
6635
|
-
const
|
|
6753
|
+
const shutdownToken = opts.recordRuntime ? randomUUID() : void 0;
|
|
6754
|
+
let handle = null;
|
|
6755
|
+
let shuttingDown = false;
|
|
6756
|
+
const shutdown = async () => {
|
|
6757
|
+
if (shuttingDown || !handle) return;
|
|
6758
|
+
shuttingDown = true;
|
|
6759
|
+
console.log("\nShutting down YorZ Service…");
|
|
6760
|
+
try {
|
|
6761
|
+
await handle.close();
|
|
6762
|
+
} finally {
|
|
6763
|
+
if (opts.recordRuntime) await removeRuntimeForPid(process.pid);
|
|
6764
|
+
process.exit(0);
|
|
6765
|
+
}
|
|
6766
|
+
};
|
|
6767
|
+
handle = await start({
|
|
6636
6768
|
port: opts.port,
|
|
6637
6769
|
host: opts.host,
|
|
6638
6770
|
open: opts.open,
|
|
6639
6771
|
cwd: opts.cwd ?? process.cwd(),
|
|
6640
|
-
noRegisterCwd: opts.noRegisterCwd
|
|
6772
|
+
noRegisterCwd: opts.noRegisterCwd,
|
|
6773
|
+
shutdownToken,
|
|
6774
|
+
onShutdownRequest: shutdownToken ? () => void shutdown() : void 0
|
|
6641
6775
|
});
|
|
6642
6776
|
if (opts.recordRuntime) {
|
|
6643
6777
|
const snapshot = await readProcessSnapshot(process.pid);
|
|
@@ -6648,21 +6782,13 @@ async function runServe(opts) {
|
|
|
6648
6782
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6649
6783
|
execPath: process.execPath,
|
|
6650
6784
|
argv: process.argv,
|
|
6651
|
-
processStartedAt: snapshot?.processStartedAt
|
|
6785
|
+
processStartedAt: snapshot?.processStartedAt,
|
|
6786
|
+
shutdownToken
|
|
6652
6787
|
});
|
|
6653
6788
|
console.log(`Stop with: yorz serve stop`);
|
|
6654
6789
|
} else {
|
|
6655
6790
|
console.log(`Stop with: Ctrl-C`);
|
|
6656
6791
|
}
|
|
6657
|
-
const shutdown = async () => {
|
|
6658
|
-
console.log("\nShutting down YorZ Service…");
|
|
6659
|
-
try {
|
|
6660
|
-
await handle.close();
|
|
6661
|
-
} finally {
|
|
6662
|
-
if (opts.recordRuntime) await removeRuntimeForPid(process.pid);
|
|
6663
|
-
process.exit(0);
|
|
6664
|
-
}
|
|
6665
|
-
};
|
|
6666
6792
|
process.once("SIGINT", () => void shutdown());
|
|
6667
6793
|
process.once("SIGTERM", () => void shutdown());
|
|
6668
6794
|
return handle;
|
|
@@ -6687,7 +6813,7 @@ function startBackgroundServe(opts) {
|
|
|
6687
6813
|
const entry = process.argv[1];
|
|
6688
6814
|
if (!entry) throw new Error("Cannot resolve CLI entrypoint for background service");
|
|
6689
6815
|
const stdio = backgroundStdio();
|
|
6690
|
-
const child =
|
|
6816
|
+
const child = spawnWithoutWindow(process.execPath, [entry, "serve", ...backgroundArgs(opts)], {
|
|
6691
6817
|
detached: true,
|
|
6692
6818
|
stdio: stdio.stdio
|
|
6693
6819
|
});
|
|
@@ -6773,7 +6899,7 @@ async function ensureSkillsInstalledWithLog(cwd) {
|
|
|
6773
6899
|
console.log(`[skill][legacy] ${r.skill} kept (not a YorZ skill): ${r.path}`);
|
|
6774
6900
|
}
|
|
6775
6901
|
}
|
|
6776
|
-
async function runStopServe() {
|
|
6902
|
+
async function runStopServe(opts = {}) {
|
|
6777
6903
|
silenceConsoleMirror();
|
|
6778
6904
|
const all = await readAllProcesses();
|
|
6779
6905
|
if (all.length === 0) {
|
|
@@ -6807,16 +6933,38 @@ async function runStopServe() {
|
|
|
6807
6933
|
const stoppedPids = [];
|
|
6808
6934
|
const stoppedUrls = [];
|
|
6809
6935
|
const failedPids = [];
|
|
6936
|
+
const platform2 = opts.platform ?? process.platform;
|
|
6810
6937
|
for (const { proc } of alive) {
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6938
|
+
let stopped = false;
|
|
6939
|
+
if (platform2 === "win32") {
|
|
6940
|
+
if (proc.shutdownToken) {
|
|
6941
|
+
try {
|
|
6942
|
+
await requestGracefulShutdown(proc);
|
|
6943
|
+
log().info("requested graceful shutdown", { pid: proc.pid, url: proc.url });
|
|
6944
|
+
stopped = await waitForProcessExit(proc.pid, 5e3);
|
|
6945
|
+
} catch (err) {
|
|
6946
|
+
log().warn("graceful shutdown request failed", { pid: proc.pid, err });
|
|
6947
|
+
stopped = await waitForProcessExit(proc.pid, 2e3);
|
|
6948
|
+
}
|
|
6949
|
+
} else {
|
|
6950
|
+
log().warn("refused to stop unverified legacy Windows runtime pid", { pid: proc.pid });
|
|
6951
|
+
}
|
|
6952
|
+
if (!stopped) {
|
|
6953
|
+
failedPids.push(proc.pid);
|
|
6954
|
+
continue;
|
|
6955
|
+
}
|
|
6956
|
+
}
|
|
6957
|
+
if (!stopped) {
|
|
6958
|
+
try {
|
|
6959
|
+
process.kill(proc.pid, "SIGTERM");
|
|
6960
|
+
log().info("sent SIGTERM", { pid: proc.pid, url: proc.url });
|
|
6961
|
+
} catch (err) {
|
|
6962
|
+
log().warn("SIGTERM failed", { pid: proc.pid, err });
|
|
6963
|
+
failedPids.push(proc.pid);
|
|
6964
|
+
continue;
|
|
6965
|
+
}
|
|
6966
|
+
stopped = await waitForProcessExit(proc.pid, 2e3);
|
|
6818
6967
|
}
|
|
6819
|
-
let stopped = await waitForProcessExit(proc.pid, 2e3);
|
|
6820
6968
|
if (!stopped) {
|
|
6821
6969
|
log().warn("still alive after SIGTERM, escalating to SIGKILL", { pid: proc.pid });
|
|
6822
6970
|
try {
|
|
@@ -6855,6 +7003,16 @@ async function runStopServe() {
|
|
|
6855
7003
|
message: `Stopped ${stoppedPids.length} YorZ Service process(es): ${pidList}.`
|
|
6856
7004
|
};
|
|
6857
7005
|
}
|
|
7006
|
+
async function requestGracefulShutdown(proc) {
|
|
7007
|
+
const response = await fetch(`http://127.0.0.1:${proc.port}/api/internal/shutdown`, {
|
|
7008
|
+
method: "POST",
|
|
7009
|
+
headers: { "x-yorz-shutdown-token": proc.shutdownToken },
|
|
7010
|
+
signal: AbortSignal.timeout(2e3)
|
|
7011
|
+
});
|
|
7012
|
+
if (!response.ok) {
|
|
7013
|
+
throw new Error(`Service rejected graceful shutdown with HTTP ${response.status}`);
|
|
7014
|
+
}
|
|
7015
|
+
}
|
|
6858
7016
|
function runtimePath() {
|
|
6859
7017
|
return join(resolveGlobalConfigDir(), RUNTIME_FILE);
|
|
6860
7018
|
}
|
|
@@ -6949,7 +7107,8 @@ function toProcessEntry(obj) {
|
|
|
6949
7107
|
startedAt: obj.startedAt,
|
|
6950
7108
|
execPath: typeof obj.execPath === "string" ? obj.execPath : void 0,
|
|
6951
7109
|
argv: Array.isArray(obj.argv) && obj.argv.every((v) => typeof v === "string") ? obj.argv : void 0,
|
|
6952
|
-
processStartedAt: typeof obj.processStartedAt === "string" ? obj.processStartedAt : void 0
|
|
7110
|
+
processStartedAt: typeof obj.processStartedAt === "string" ? obj.processStartedAt : void 0,
|
|
7111
|
+
shutdownToken: typeof obj.shutdownToken === "string" ? obj.shutdownToken : void 0
|
|
6953
7112
|
};
|
|
6954
7113
|
}
|
|
6955
7114
|
function tryV1Entry(parsed) {
|
|
@@ -6963,7 +7122,8 @@ function tryV1Entry(parsed) {
|
|
|
6963
7122
|
startedAt: parsed.startedAt,
|
|
6964
7123
|
execPath: typeof parsed.execPath === "string" ? parsed.execPath : void 0,
|
|
6965
7124
|
argv: Array.isArray(parsed.argv) && parsed.argv.every((v) => typeof v === "string") ? parsed.argv : void 0,
|
|
6966
|
-
processStartedAt: typeof parsed.processStartedAt === "string" ? parsed.processStartedAt : void 0
|
|
7125
|
+
processStartedAt: typeof parsed.processStartedAt === "string" ? parsed.processStartedAt : void 0,
|
|
7126
|
+
shutdownToken: typeof parsed.shutdownToken === "string" ? parsed.shutdownToken : void 0
|
|
6967
7127
|
};
|
|
6968
7128
|
}
|
|
6969
7129
|
async function upsertProcess(entry) {
|
package/dist/gui/assets/{abnfDiagram-VRR7QNED-CpQSXKD3.js → abnfDiagram-VRR7QNED-Dysui3FU.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-BmLvCJEW.js";import{p as f}from"./chunk-JWPE2WC7-i8qqnqZU.js";import{_ as n,l as o}from"./mermaid.core-wGjSg1h-.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BLZ43yIC.js";import"./index-DDGLj_Fo.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
|