@akira-tl/forgerelay 0.9.3 → 0.10.0
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/CHANGELOG.md +22 -0
- package/README.md +10 -4
- package/dist/cli/init.js +111 -24
- package/dist/cli/maintenance-prune.js +479 -0
- package/dist/cli/maintenance-retention.js +93 -0
- package/dist/cli/maintenance.js +598 -0
- package/dist/cli/setup-support.js +21 -0
- package/dist/cli/shell/setup.js +99 -0
- package/dist/cli.js +72 -16
- package/dist/mcp/hooks/hooks.js +6 -3
- package/dist/mcp/oauth/public-url.js +3 -0
- package/dist/mcp/oauth/router.js +14 -9
- package/dist/mcp/process/process-platform.js +24 -26
- package/dist/mcp/process/process-sessions.js +6 -3
- package/dist/mcp/server/transport/http-server.js +17 -9
- package/dist/mcp/server/workspace/runtime/workspace-open-presentation.js +6 -0
- package/dist/mcp/server/workspace/runtime/workspace-tools.js +1 -1
- package/dist/mcp/server-instructions.js +10 -1
- package/dist/runtime/config/config.js +60 -6
- package/dist/runtime/instructions/shell-instructions.js +100 -0
- package/dist/runtime/security/runtime-privilege.js +120 -0
- package/dist/runtime/shell/command-shell-runtime.js +235 -0
- package/dist/runtime/state/runtime-lease.js +109 -0
- package/dist/ui/.vite/manifest.json +276 -276
- package/dist/ui/activity-panel-app.html +2 -2
- package/dist/ui/assets/{activity-panel-app-Sl1Jro8v.js → activity-panel-app-BkODhDLg.js} +1 -1
- package/dist/ui/assets/{activity-panel-app-7Xe0alhm.css → activity-panel-app-DkfJzTZ3.css} +1 -1
- package/dist/ui/assets/{angular-html-B_yn91wW.js → angular-html-DjuELMdF.js} +1 -1
- package/dist/ui/assets/{angular-ts-DSgtloKz.js → angular-ts-2EXVZIIX.js} +1 -1
- package/dist/ui/assets/{apl-NatWtF8X.js → apl-Bb4IeT5V.js} +1 -1
- package/dist/ui/assets/{astro-BYFEVBuN.js → astro-Bjavu3nT.js} +1 -1
- package/dist/ui/assets/{blade-DoO7yvMR.js → blade-DKW2uHZo.js} +1 -1
- package/dist/ui/assets/{c-Rl2hMCcg.js → c-oLeHmzbj.js} +1 -1
- package/dist/ui/assets/{cobol-ByC5mWiB.js → cobol-CcqFMr5T.js} +1 -1
- package/dist/ui/assets/{coffee-Dez77Qov.js → coffee-BA20zqRF.js} +1 -1
- package/dist/ui/assets/{cpp-DtaAQT9h.js → cpp-D750WmDa.js} +1 -1
- package/dist/ui/assets/{crystal-Bgmbf8ec.js → crystal-Cv5I6OMI.js} +1 -1
- package/dist/ui/assets/{css-C1tjBtVN.js → css-CjPPWPeH.js} +1 -1
- package/dist/ui/assets/{edge-DeH6u8Wg.js → edge-aYRuudEZ.js} +1 -1
- package/dist/ui/assets/{elixir-_H3KnmWT.js → elixir-ChLitmz7.js} +1 -1
- package/dist/ui/assets/{elm-CsCe3U28.js → elm-Fs7L7u36.js} +1 -1
- package/dist/ui/assets/{erb-CbM-L2g8.js → erb-B-qXHxN1.js} +1 -1
- package/dist/ui/assets/{git-rebase-D0s5pDh9.js → git-rebase-DOVN5OEg.js} +1 -1
- package/dist/ui/assets/{glimmer-js-BfOToq_A.js → glimmer-js-BFt_vCTW.js} +1 -1
- package/dist/ui/assets/{glimmer-ts-CCUOkL2K.js → glimmer-ts-ufCHlR6C.js} +1 -1
- package/dist/ui/assets/{glsl-DH4ec9dE.js → glsl-Ex4JXGuC.js} +1 -1
- package/dist/ui/assets/{graphql-DilAMBoI.js → graphql-pQPXtBk5.js} +1 -1
- package/dist/ui/assets/{hack-BDkNDZlF.js → hack-B5hDguhd.js} +1 -1
- package/dist/ui/assets/{haml-D_QBp6K7.js → haml-BrNeI29U.js} +1 -1
- package/dist/ui/assets/{handlebars-DePUrTpC.js → handlebars-DCqTsL9-.js} +1 -1
- package/dist/ui/assets/{heavy-payload-DOwZpO6n.js → heavy-payload-DsmmHgvt.js} +3 -3
- package/dist/ui/assets/{html-By4dNnM4.js → html-D8k0CC9V.js} +1 -1
- package/dist/ui/assets/{html-derivative-DDw9Ef4Q.js → html-derivative-CC8flWmC.js} +1 -1
- package/dist/ui/assets/{http-B0QxWc9M.js → http-BYnWqNep.js} +1 -1
- package/dist/ui/assets/{hurl-vMQ4lda1.js → hurl-BND-z85s.js} +1 -1
- package/dist/ui/assets/{java-DYRe2lWG.js → java-Dug0oB9T.js} +1 -1
- package/dist/ui/assets/{javascript-CxyGqwcL.js → javascript-oDJ7WITC.js} +1 -1
- package/dist/ui/assets/{jinja-JUwV-fZt.js → jinja-Cv0t_F1U.js} +1 -1
- package/dist/ui/assets/{jison-7ZqCEvS8.js → jison-Car3MF55.js} +1 -1
- package/dist/ui/assets/{json-dbltgiiA.js → json-CEViCsf4.js} +1 -1
- package/dist/ui/assets/{jsx-oDopT7YQ.js → jsx-BfZ0zgSH.js} +1 -1
- package/dist/ui/assets/{julia-CkKiNSav.js → julia-CmX0b3Tn.js} +1 -1
- package/dist/ui/assets/{just-DuqCAKJ3.js → just-BuugLCVk.js} +1 -1
- package/dist/ui/assets/{latex-sudcRDSn.js → latex-FpTXqO03.js} +1 -1
- package/dist/ui/assets/{liquid-Di-08Js7.js → liquid-B37OzUFu.js} +1 -1
- package/dist/ui/assets/{lua-YlqdMoV0.js → lua-BHjcb8oq.js} +1 -1
- package/dist/ui/assets/{marko-CJRNyJDb.js → marko-CApj_fsH.js} +1 -1
- package/dist/ui/assets/{mdc-t12CzZHs.js → mdc-Ed5vQWq8.js} +1 -1
- package/dist/ui/assets/{nginx-57-b4XwT.js → nginx-u_rVEBox.js} +1 -1
- package/dist/ui/assets/{nim-BzrswYQa.js → nim-Ba9EdchT.js} +1 -1
- package/dist/ui/assets/{perl-D9JR_iIh.js → perl-BpU_6Wvz.js} +1 -1
- package/dist/ui/assets/{php-Py2gFHil.js → php-bKabofky.js} +1 -1
- package/dist/ui/assets/{pug-PzLLy0h1.js → pug-C_aLNkqe.js} +1 -1
- package/dist/ui/assets/{qml-By8fwgV4.js → qml-D9VisnRy.js} +1 -1
- package/dist/ui/assets/{r-CcezTbLq.js → r-CYqB1sLx.js} +1 -1
- package/dist/ui/assets/{razor-dG-vdhL_.js → razor-DNJKI8Rs.js} +1 -1
- package/dist/ui/assets/{regexp-BlsQ-N_8.js → regexp-DHrTHXkz.js} +1 -1
- package/dist/ui/assets/{rst-C2awDCat.js → rst-CbNdSFHv.js} +1 -1
- package/dist/ui/assets/{ruby-zA2W_49d.js → ruby-FyKG-pkF.js} +1 -1
- package/dist/ui/assets/{sas-D49bhyaN.js → sas-BbSPDl3X.js} +1 -1
- package/dist/ui/assets/{scss-BQb-cp01.js → scss-2nX9g6gD.js} +1 -1
- package/dist/ui/assets/{shellscript-Dga4H_Ni.js → shellscript-CmON6x2x.js} +1 -1
- package/dist/ui/assets/{shellsession-n3-5CqcF.js → shellsession-DtqIGlAX.js} +1 -1
- package/dist/ui/assets/{soy-XYBOf_BA.js → soy-BzUJMmJT.js} +1 -1
- package/dist/ui/assets/{sql-ET4u5Cpl.js → sql-CgVcFZmb.js} +1 -1
- package/dist/ui/assets/{stata-CLHcJHO_.js → stata-CNitlMot.js} +1 -1
- package/dist/ui/assets/{surrealql-BdjQ60T4.js → surrealql-BA8-xsRZ.js} +1 -1
- package/dist/ui/assets/{svelte-B2RPtKJe.js → svelte-El02yAxv.js} +1 -1
- package/dist/ui/assets/{templ-CrByPW_W.js → templ-DeUQ84aR.js} +1 -1
- package/dist/ui/assets/{tex-DZBkg363.js → tex-Cu-FqpPS.js} +1 -1
- package/dist/ui/assets/{ts-tags-DJR3Gphb.js → ts-tags-X42N6TGA.js} +1 -1
- package/dist/ui/assets/{tsx-CajzROyy.js → tsx-C1aPp9rY.js} +1 -1
- package/dist/ui/assets/{twig-BZjk5Zda.js → twig-Cj1Q4SQc.js} +1 -1
- package/dist/ui/assets/{typescript-B-EWToLj.js → typescript-Du9lVt1G.js} +1 -1
- package/dist/ui/assets/{vue-D_rHCCr8.js → vue-_uMGbFv8.js} +1 -1
- package/dist/ui/assets/{vue-html-CC4WlvVt.js → vue-html-D61naG-Q.js} +1 -1
- package/dist/ui/assets/{vue-vine-BgNMVgpk.js → vue-vine-CkFae4yV.js} +1 -1
- package/dist/ui/assets/{xml-BI86-WbH.js → xml-Cbwsc6ws.js} +1 -1
- package/dist/ui/assets/{xsl-DXeLZV4J.js → xsl-NyBx72XB.js} +1 -1
- package/dist/ui/assets/{yaml-60_PFlWa.js → yaml-Cgb6Uq9u.js} +1 -1
- package/dist/workspaces/context.js +32 -5
- package/dist/workspaces/presentation/workspace-presentation.js +1 -0
- package/dist/workspaces/sessions.js +2 -0
- package/dist/workspaces.js +2 -1
- package/docs/configuration.md +101 -14
- package/package.json +2 -2
- package/scripts/release/release-gate.test.mjs +1 -0
- package/scripts/release-proof.mjs +85 -9
- package/scripts/release-proof.test.mjs +79 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { closeSync, constants as fsConstants, mkdirSync, openSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
const RUNTIME_LEASE_FILE = "forgerelay-runtime.lock";
|
|
5
|
+
export function runtimeLeasePath(stateDir) {
|
|
6
|
+
return join(stateDir, RUNTIME_LEASE_FILE);
|
|
7
|
+
}
|
|
8
|
+
export function acquireRuntimeLease(stateDir) {
|
|
9
|
+
mkdirSync(stateDir, { recursive: true, mode: 0o700 });
|
|
10
|
+
const path = runtimeLeasePath(stateDir);
|
|
11
|
+
const record = {
|
|
12
|
+
pid: process.pid,
|
|
13
|
+
token: randomBytes(16).toString("hex"),
|
|
14
|
+
startedAt: new Date().toISOString(),
|
|
15
|
+
};
|
|
16
|
+
const serialized = `${JSON.stringify(record)}\n`;
|
|
17
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
18
|
+
let fd;
|
|
19
|
+
try {
|
|
20
|
+
fd = openSync(path, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY, 0o600);
|
|
21
|
+
writeFileSync(fd, serialized, "utf8");
|
|
22
|
+
closeSync(fd);
|
|
23
|
+
fd = undefined;
|
|
24
|
+
return {
|
|
25
|
+
path,
|
|
26
|
+
pid: record.pid,
|
|
27
|
+
release: () => releaseRuntimeLease(path, record),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (fd !== undefined)
|
|
32
|
+
closeSync(fd);
|
|
33
|
+
if (!isErrno(error, "EEXIST"))
|
|
34
|
+
throw error;
|
|
35
|
+
const inspection = inspectRuntimeLease(stateDir);
|
|
36
|
+
if (inspection.active || inspection.malformed) {
|
|
37
|
+
const owner = inspection.pid === undefined ? "an unknown process" : `PID ${inspection.pid}`;
|
|
38
|
+
throw new Error(`ForgeRelay state is already in use by ${owner}: ${path}`);
|
|
39
|
+
}
|
|
40
|
+
rmSync(path, { force: true });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Unable to acquire ForgeRelay runtime lease: ${path}`);
|
|
44
|
+
}
|
|
45
|
+
export function inspectRuntimeLease(stateDir) {
|
|
46
|
+
const path = runtimeLeasePath(stateDir);
|
|
47
|
+
let raw;
|
|
48
|
+
try {
|
|
49
|
+
raw = readFileSync(path, "utf8");
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (isErrno(error, "ENOENT")) {
|
|
53
|
+
return { path, active: false, stale: false, malformed: false };
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
const record = parseRecord(raw);
|
|
58
|
+
if (!record)
|
|
59
|
+
return { path, active: true, stale: false, malformed: true };
|
|
60
|
+
const active = processIsAlive(record.pid);
|
|
61
|
+
return {
|
|
62
|
+
path,
|
|
63
|
+
active,
|
|
64
|
+
stale: !active,
|
|
65
|
+
pid: record.pid,
|
|
66
|
+
malformed: false,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function releaseRuntimeLease(path, expected) {
|
|
70
|
+
let current;
|
|
71
|
+
try {
|
|
72
|
+
current = parseRecord(readFileSync(path, "utf8"));
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (isErrno(error, "ENOENT"))
|
|
76
|
+
return;
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
if (!current || current.pid !== expected.pid || current.token !== expected.token)
|
|
80
|
+
return;
|
|
81
|
+
rmSync(path, { force: true });
|
|
82
|
+
}
|
|
83
|
+
function parseRecord(raw) {
|
|
84
|
+
try {
|
|
85
|
+
const value = JSON.parse(raw);
|
|
86
|
+
if (!Number.isSafeInteger(value.pid) || (value.pid ?? 0) <= 0)
|
|
87
|
+
return undefined;
|
|
88
|
+
if (typeof value.token !== "string" || value.token.length < 16)
|
|
89
|
+
return undefined;
|
|
90
|
+
if (typeof value.startedAt !== "string" || !Number.isFinite(Date.parse(value.startedAt)))
|
|
91
|
+
return undefined;
|
|
92
|
+
return { pid: value.pid, token: value.token, startedAt: value.startedAt };
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function processIsAlive(pid) {
|
|
99
|
+
try {
|
|
100
|
+
process.kill(pid, 0);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
return !isErrno(error, "ESRCH");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function isErrno(error, code) {
|
|
108
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
109
|
+
}
|