@code-yeongyu/senpi 2026.9.29-2 → 2026.9.29-3
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 +14 -0
- package/dist/bundle/chunks/{anthropic-messages-OMTQOHSI.js → anthropic-messages-7WTVWELD.js} +1 -1
- package/dist/bundle/chunks/{app-server-command-ZC6A4C3L.js → app-server-command-5DSRGKFG.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-Z4FAFKPJ.js → azure-openai-responses-XVZ3FMH2.js} +1 -1
- package/dist/bundle/chunks/{chunk-U2SAEU63.js → chunk-27C3ZSZG.js} +1 -1
- package/dist/bundle/chunks/{chunk-YJUO37UX.js → chunk-2POUJCWM.js} +1 -1
- package/dist/bundle/chunks/{chunk-4LVZQRDG.js → chunk-4VWWEMCJ.js} +1 -1
- package/dist/bundle/chunks/{chunk-36ACNYQR.js → chunk-7RVWDN5Z.js} +1 -1
- package/dist/bundle/chunks/{chunk-YS72TY6S.js → chunk-CZNE6LIO.js} +1 -1
- package/dist/bundle/chunks/{chunk-ILELKDDB.js → chunk-DWNYCJ43.js} +1 -1
- package/dist/bundle/chunks/{chunk-OMLHHPMZ.js → chunk-EB3GDOU4.js} +1 -1
- package/dist/bundle/chunks/{chunk-2HWLCW54.js → chunk-EQBN6TVJ.js} +1 -1
- package/dist/bundle/chunks/{chunk-E5F5SVZF.js → chunk-FUGMDU6B.js} +1 -1
- package/dist/bundle/chunks/{chunk-RSPHQOSG.js → chunk-GE32OHDE.js} +7 -7
- package/dist/bundle/chunks/chunk-GKR74EKE.js +3 -0
- package/dist/bundle/chunks/{chunk-UYV2UM6E.js → chunk-ILQTW6KB.js} +1 -1
- package/dist/bundle/chunks/{chunk-TH4XD7AJ.js → chunk-JEWB5XTL.js} +1 -1
- package/dist/bundle/chunks/{chunk-FAV4DX74.js → chunk-K2SHQNAA.js} +1 -1
- package/dist/bundle/chunks/{chunk-NVJUCNHP.js → chunk-K7B7NFOK.js} +1 -1
- package/dist/bundle/chunks/{chunk-TZMNXKL2.js → chunk-KO6GO5ZY.js} +1 -1
- package/dist/bundle/chunks/{chunk-5CGFVKUK.js → chunk-LB2B2Q4P.js} +1 -1
- package/dist/bundle/chunks/{chunk-77OBRAUG.js → chunk-M4AHRI5L.js} +1 -1
- package/dist/bundle/chunks/{chunk-SW4U2HHU.js → chunk-OVDACFW2.js} +1 -1
- package/dist/bundle/chunks/{chunk-BTRONX2A.js → chunk-RUOJQL6B.js} +1 -1
- package/dist/bundle/chunks/{chunk-ASAQQ6VM.js → chunk-SH6VUPE4.js} +1 -1
- package/dist/bundle/chunks/{chunk-TFW6SS3P.js → chunk-SNDTJL2H.js} +1 -1
- package/dist/bundle/chunks/{chunk-Y5A6TKBN.js → chunk-T3HGPHPP.js} +1 -1
- package/dist/bundle/chunks/{chunk-BPZ5KIOS.js → chunk-UK5TE7WR.js} +1 -1
- package/dist/bundle/chunks/{chunk-NDNZU2X7.js → chunk-UNTVGMGW.js} +3 -3
- package/dist/bundle/chunks/{chunk-BQGFWWDC.js → chunk-VLTMFAWQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-XDZ5RSMX.js → chunk-W4AG5TN4.js} +1 -1
- package/dist/bundle/chunks/chunk-WCAKUCN3.js +14 -0
- package/dist/bundle/chunks/{chunk-UEWSEALS.js → chunk-WRPX2M5D.js} +1 -1
- package/dist/bundle/chunks/{chunk-DA4W77J7.js → chunk-XBGO2JZD.js} +1 -1
- package/dist/bundle/chunks/chunk-XVX4M3DZ.js +2 -0
- package/dist/bundle/chunks/chunk-YD32NXKZ.js +8 -0
- package/dist/bundle/chunks/chunk-YOPVJDSU.js +2 -0
- package/dist/bundle/chunks/cli-main-V3T5WOV6.js +3 -0
- package/dist/bundle/chunks/{google-generative-ai-NFSRK6V5.js → google-generative-ai-XO6BUQVD.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-6YEVHEPI.js → google-vertex-SGNV6ZMK.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-RYMO5ODA.js → help-fast-path-AYPE26W2.js} +1 -1
- package/dist/bundle/chunks/{host-command-BU6XSX4H.js → host-command-ZTMADQIT.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-22DRSTVI.js → host-lifecycle-FTH7WAQN.js} +1 -1
- package/dist/bundle/chunks/{interactive-host-runtime-P3FYZWSY.js → interactive-host-runtime-XDRXCEJ3.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-VCIOGSIZ.js → interactive-mode-6VFVZKKW.js} +1 -1
- package/dist/bundle/chunks/{list-tips-XXZ5PLE3.js → list-tips-ASETMEFS.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-R5PTP4P3.js → mistral-conversations-TVJBIL35.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-PRY7CJLK.js → multi-session-host-5VFMTPY7.js} +1 -1
- package/dist/bundle/chunks/{native-loader-SU5SGTSW.js → native-loader-WM7NDPEO.js} +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-6B2ZLWTN.js → openai-codex-responses-RUT66DHS.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-5NTZZNVJ.js → openai-completions-THHRTH7B.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-V4JEBGEX.js → openai-responses-ITED6XXB.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-RQ2NJAJ3.js → package-manager-cli-RAQRCH5L.js} +3 -3
- package/dist/bundle/chunks/{rg-engine-XHGOVGVG.js → rg-engine-G2YTYL2T.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-YQLGLRCX.js → rotation-stream-4FQW6IX5.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-U2EQRVC3.js → rpc-mode-W5P5QMF7.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-DXC3ECXT.js → schedule-command-EFQUSPN4.js} +1 -1
- package/dist/bundle/chunks/{session-picker-KTXLU6MQ.js → session-picker-FF2J4OQA.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +188 -188
- package/dist/bundle/chunks/{state-store-5A2TZ4SG.js → state-store-IIQL55GC.js} +1 -1
- package/dist/bundle/cli.js +2 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -0
- package/dist/cli.js +24 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -6
- package/dist/config.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -2
- package/dist/main.js.map +1 -1
- package/dist/package-manager-cli.js +3 -3
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/runtime-snapshot/enter.d.ts +17 -0
- package/dist/runtime-snapshot/enter.d.ts.map +1 -0
- package/dist/runtime-snapshot/enter.js +72 -0
- package/dist/runtime-snapshot/enter.js.map +1 -0
- package/dist/runtime-snapshot/layout.d.ts +15 -0
- package/dist/runtime-snapshot/layout.d.ts.map +1 -0
- package/dist/runtime-snapshot/layout.js +126 -0
- package/dist/runtime-snapshot/layout.js.map +1 -0
- package/dist/runtime-snapshot/marker.d.ts +13 -0
- package/dist/runtime-snapshot/marker.d.ts.map +1 -0
- package/dist/runtime-snapshot/marker.js +40 -0
- package/dist/runtime-snapshot/marker.js.map +1 -0
- package/dist/runtime-snapshot/registry.d.ts +14 -0
- package/dist/runtime-snapshot/registry.d.ts.map +1 -0
- package/dist/runtime-snapshot/registry.js +124 -0
- package/dist/runtime-snapshot/registry.js.map +1 -0
- package/dist/senpi +24 -4
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/lazy.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/lazy.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/lazy.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.d.ts +7 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.js +21 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/chunk-DXU53IPJ.js +0 -8
- package/dist/bundle/chunks/chunk-FILEUW2D.js +0 -3
- package/dist/bundle/chunks/chunk-PBWQK23Z.js +0 -14
- package/dist/bundle/chunks/chunk-TJV2LFKM.js +0 -2
- package/dist/bundle/chunks/chunk-UIOI2SK3.js +0 -2
- package/dist/bundle/chunks/cli-main-RPQFXRJ7.js +0 -3
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readdirSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import { RUNTIME_SNAPSHOT_MARKER } from "./marker.js";
|
|
4
|
+
export class RuntimeSnapshotLayoutError extends Error {
|
|
5
|
+
constructor(packageName) {
|
|
6
|
+
super(`runtime snapshot resolves ${packageName} differently from the install`);
|
|
7
|
+
this.packageName = packageName;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function isMissing(error) {
|
|
11
|
+
return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
|
|
12
|
+
}
|
|
13
|
+
function occupied(path) {
|
|
14
|
+
try {
|
|
15
|
+
lstatSync(path);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (isMissing(error))
|
|
20
|
+
return false;
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function linkEntry(source, target) {
|
|
25
|
+
let isDirectory;
|
|
26
|
+
try {
|
|
27
|
+
isDirectory = statSync(source).isDirectory();
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
// A dangling link in the install stays unresolvable from the snapshot too.
|
|
31
|
+
if (isMissing(error))
|
|
32
|
+
return;
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
// Windows file symlinks need a privilege; the files involved are small, so copy them.
|
|
36
|
+
if (process.platform === "win32" && !isDirectory) {
|
|
37
|
+
copyFileSync(source, target);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
symlinkSync(source, target, isDirectory ? "junction" : "file");
|
|
41
|
+
}
|
|
42
|
+
function linkChildren(sourceDir, targetDir, skip) {
|
|
43
|
+
for (const name of readdirSync(sourceDir)) {
|
|
44
|
+
if (skip.has(name) || occupied(join(targetDir, name)))
|
|
45
|
+
continue;
|
|
46
|
+
linkEntry(join(sourceDir, name), join(targetDir, name));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** The node_modules directories Node's resolver walks from `dir`, nearest first. */
|
|
50
|
+
function moduleDirectoriesFrom(dir) {
|
|
51
|
+
const directories = [];
|
|
52
|
+
for (let current = dir;; current = dirname(current)) {
|
|
53
|
+
if (basename(current) !== "node_modules") {
|
|
54
|
+
const candidate = join(current, "node_modules");
|
|
55
|
+
if (existsSync(candidate))
|
|
56
|
+
directories.push(candidate);
|
|
57
|
+
}
|
|
58
|
+
if (dirname(current) === current)
|
|
59
|
+
return directories;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* One node_modules that resolves every package name the way the install does: the union of the
|
|
64
|
+
* install's resolution path, nearest directory first, so hoisted and nested layouts both hold.
|
|
65
|
+
*/
|
|
66
|
+
function linkModules(packageDir, target) {
|
|
67
|
+
mkdirSync(target, { recursive: true });
|
|
68
|
+
for (const source of moduleDirectoriesFrom(packageDir)) {
|
|
69
|
+
for (const name of readdirSync(source)) {
|
|
70
|
+
if (name === ".bin")
|
|
71
|
+
continue;
|
|
72
|
+
const scoped = name.startsWith("@") && statSync(join(source, name)).isDirectory();
|
|
73
|
+
if (!scoped) {
|
|
74
|
+
if (!occupied(join(target, name)))
|
|
75
|
+
linkEntry(join(source, name), join(target, name));
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
mkdirSync(join(target, name), { recursive: true });
|
|
79
|
+
linkChildren(join(source, name), join(target, name), new Set());
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function packageRootFrom(dir, packageName) {
|
|
84
|
+
for (const modules of moduleDirectoriesFrom(dir)) {
|
|
85
|
+
const root = join(modules, packageName);
|
|
86
|
+
if (existsSync(join(root, "package.json")))
|
|
87
|
+
return realpathSync(root);
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
function verifyExternals(packageDir, snapshotBundleDir, externals) {
|
|
92
|
+
for (const name of externals) {
|
|
93
|
+
const expected = packageRootFrom(packageDir, name);
|
|
94
|
+
if (expected !== undefined && packageRootFrom(snapshotBundleDir, name) !== expected) {
|
|
95
|
+
throw new RuntimeSnapshotLayoutError(name);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Builds `target` as a copy of the package that no reinstall can touch: `dist/bundle` and
|
|
101
|
+
* `package.json` are copied, every other entry is linked back to the install. Built beside the
|
|
102
|
+
* target and renamed into place, so a crash never leaves a half-built snapshot under its name.
|
|
103
|
+
*/
|
|
104
|
+
export function materializeRuntimeSnapshot(packageDir, target, manifest) {
|
|
105
|
+
const staging = join(dirname(target), `.tmp-${basename(target)}-${process.pid}`);
|
|
106
|
+
rmSync(staging, { recursive: true, force: true });
|
|
107
|
+
try {
|
|
108
|
+
const snapshotBundleDir = join(staging, "dist", "bundle");
|
|
109
|
+
mkdirSync(join(staging, "dist"), { recursive: true });
|
|
110
|
+
cpSync(join(packageDir, "dist", "bundle"), snapshotBundleDir, { recursive: true });
|
|
111
|
+
copyFileSync(join(packageDir, "package.json"), join(staging, "package.json"));
|
|
112
|
+
linkChildren(packageDir, staging, new Set(["dist", "package.json", "node_modules"]));
|
|
113
|
+
linkChildren(join(packageDir, "dist"), join(staging, "dist"), new Set(["bundle"]));
|
|
114
|
+
linkModules(packageDir, join(staging, "node_modules"));
|
|
115
|
+
verifyExternals(packageDir, join(snapshotBundleDir, "chunks"), manifest.externals);
|
|
116
|
+
const marker = { buildId: manifest.buildId, installPackageDir: realpathSync(packageDir) };
|
|
117
|
+
writeFileSync(join(staging, RUNTIME_SNAPSHOT_MARKER), `${JSON.stringify(marker)}\n`);
|
|
118
|
+
rmSync(target, { recursive: true, force: true });
|
|
119
|
+
renameSync(staging, target);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
rmSync(staging, { recursive: true, force: true });
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/runtime-snapshot/layout.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tcopyFileSync,\n\tcpSync,\n\texistsSync,\n\tlstatSync,\n\tmkdirSync,\n\treaddirSync,\n\trealpathSync,\n\trenameSync,\n\trmSync,\n\tstatSync,\n\tsymlinkSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\nimport { RUNTIME_SNAPSHOT_MARKER, type RuntimeSnapshotMarker } from \"./marker.ts\";\n\nexport interface RuntimeManifest {\n\treadonly buildId: string;\n\treadonly externals: readonly string[];\n}\n\nexport class RuntimeSnapshotLayoutError extends Error {\n\treadonly packageName: string;\n\n\tconstructor(packageName: string) {\n\t\tsuper(`runtime snapshot resolves ${packageName} differently from the install`);\n\t\tthis.packageName = packageName;\n\t}\n}\n\nfunction isMissing(error: unknown): boolean {\n\treturn error instanceof Error && \"code\" in error && (error.code === \"ENOENT\" || error.code === \"ENOTDIR\");\n}\n\nfunction occupied(path: string): boolean {\n\ttry {\n\t\tlstatSync(path);\n\t\treturn true;\n\t} catch (error) {\n\t\tif (isMissing(error)) return false;\n\t\tthrow error;\n\t}\n}\n\nfunction linkEntry(source: string, target: string): void {\n\tlet isDirectory: boolean;\n\ttry {\n\t\tisDirectory = statSync(source).isDirectory();\n\t} catch (error) {\n\t\t// A dangling link in the install stays unresolvable from the snapshot too.\n\t\tif (isMissing(error)) return;\n\t\tthrow error;\n\t}\n\t// Windows file symlinks need a privilege; the files involved are small, so copy them.\n\tif (process.platform === \"win32\" && !isDirectory) {\n\t\tcopyFileSync(source, target);\n\t\treturn;\n\t}\n\tsymlinkSync(source, target, isDirectory ? \"junction\" : \"file\");\n}\n\nfunction linkChildren(sourceDir: string, targetDir: string, skip: ReadonlySet<string>): void {\n\tfor (const name of readdirSync(sourceDir)) {\n\t\tif (skip.has(name) || occupied(join(targetDir, name))) continue;\n\t\tlinkEntry(join(sourceDir, name), join(targetDir, name));\n\t}\n}\n\n/** The node_modules directories Node's resolver walks from `dir`, nearest first. */\nfunction moduleDirectoriesFrom(dir: string): string[] {\n\tconst directories: string[] = [];\n\tfor (let current = dir; ; current = dirname(current)) {\n\t\tif (basename(current) !== \"node_modules\") {\n\t\t\tconst candidate = join(current, \"node_modules\");\n\t\t\tif (existsSync(candidate)) directories.push(candidate);\n\t\t}\n\t\tif (dirname(current) === current) return directories;\n\t}\n}\n\n/**\n * One node_modules that resolves every package name the way the install does: the union of the\n * install's resolution path, nearest directory first, so hoisted and nested layouts both hold.\n */\nfunction linkModules(packageDir: string, target: string): void {\n\tmkdirSync(target, { recursive: true });\n\tfor (const source of moduleDirectoriesFrom(packageDir)) {\n\t\tfor (const name of readdirSync(source)) {\n\t\t\tif (name === \".bin\") continue;\n\t\t\tconst scoped = name.startsWith(\"@\") && statSync(join(source, name)).isDirectory();\n\t\t\tif (!scoped) {\n\t\t\t\tif (!occupied(join(target, name))) linkEntry(join(source, name), join(target, name));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmkdirSync(join(target, name), { recursive: true });\n\t\t\tlinkChildren(join(source, name), join(target, name), new Set());\n\t\t}\n\t}\n}\n\nfunction packageRootFrom(dir: string, packageName: string): string | undefined {\n\tfor (const modules of moduleDirectoriesFrom(dir)) {\n\t\tconst root = join(modules, packageName);\n\t\tif (existsSync(join(root, \"package.json\"))) return realpathSync(root);\n\t}\n\treturn undefined;\n}\n\nfunction verifyExternals(packageDir: string, snapshotBundleDir: string, externals: readonly string[]): void {\n\tfor (const name of externals) {\n\t\tconst expected = packageRootFrom(packageDir, name);\n\t\tif (expected !== undefined && packageRootFrom(snapshotBundleDir, name) !== expected) {\n\t\t\tthrow new RuntimeSnapshotLayoutError(name);\n\t\t}\n\t}\n}\n\n/**\n * Builds `target` as a copy of the package that no reinstall can touch: `dist/bundle` and\n * `package.json` are copied, every other entry is linked back to the install. Built beside the\n * target and renamed into place, so a crash never leaves a half-built snapshot under its name.\n */\nexport function materializeRuntimeSnapshot(packageDir: string, target: string, manifest: RuntimeManifest): void {\n\tconst staging = join(dirname(target), `.tmp-${basename(target)}-${process.pid}`);\n\trmSync(staging, { recursive: true, force: true });\n\ttry {\n\t\tconst snapshotBundleDir = join(staging, \"dist\", \"bundle\");\n\t\tmkdirSync(join(staging, \"dist\"), { recursive: true });\n\t\tcpSync(join(packageDir, \"dist\", \"bundle\"), snapshotBundleDir, { recursive: true });\n\t\tcopyFileSync(join(packageDir, \"package.json\"), join(staging, \"package.json\"));\n\t\tlinkChildren(packageDir, staging, new Set([\"dist\", \"package.json\", \"node_modules\"]));\n\t\tlinkChildren(join(packageDir, \"dist\"), join(staging, \"dist\"), new Set([\"bundle\"]));\n\t\tlinkModules(packageDir, join(staging, \"node_modules\"));\n\t\tverifyExternals(packageDir, join(snapshotBundleDir, \"chunks\"), manifest.externals);\n\t\tconst marker: RuntimeSnapshotMarker = { buildId: manifest.buildId, installPackageDir: realpathSync(packageDir) };\n\t\twriteFileSync(join(staging, RUNTIME_SNAPSHOT_MARKER), `${JSON.stringify(marker)}\\n`);\n\t\trmSync(target, { recursive: true, force: true });\n\t\trenameSync(staging, target);\n\t} catch (error) {\n\t\trmSync(staging, { recursive: true, force: true });\n\t\tthrow error;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const RUNTIME_SNAPSHOT_MARKER = "runtime-snapshot.json";
|
|
2
|
+
export interface RuntimeSnapshotMarker {
|
|
3
|
+
readonly buildId: string;
|
|
4
|
+
readonly installPackageDir: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function readRuntimeSnapshotMarker(packageRoot: string): RuntimeSnapshotMarker | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Maps a path inside a runtime snapshot to the same path inside the install it was taken from.
|
|
9
|
+
* Install-method detection, self-update and quarantine logic reason about where the package
|
|
10
|
+
* manager put the package, which a process running from its snapshot would otherwise misread.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveInstallPath(path: string, packageRoot: string): string;
|
|
13
|
+
//# sourceMappingURL=marker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/runtime-snapshot/marker.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACnC;AAED,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAsBhG;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAM5E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join, relative } from "node:path";
|
|
3
|
+
export const RUNTIME_SNAPSHOT_MARKER = "runtime-snapshot.json";
|
|
4
|
+
export function readRuntimeSnapshotMarker(packageRoot) {
|
|
5
|
+
let text;
|
|
6
|
+
try {
|
|
7
|
+
text = readFileSync(join(packageRoot, RUNTIME_SNAPSHOT_MARKER), "utf8");
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
if (error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
const parsed = JSON.parse(text);
|
|
16
|
+
if (typeof parsed === "object" &&
|
|
17
|
+
parsed !== null &&
|
|
18
|
+
"buildId" in parsed &&
|
|
19
|
+
typeof parsed.buildId === "string" &&
|
|
20
|
+
"installPackageDir" in parsed &&
|
|
21
|
+
typeof parsed.installPackageDir === "string") {
|
|
22
|
+
return { buildId: parsed.buildId, installPackageDir: parsed.installPackageDir };
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Maps a path inside a runtime snapshot to the same path inside the install it was taken from.
|
|
28
|
+
* Install-method detection, self-update and quarantine logic reason about where the package
|
|
29
|
+
* manager put the package, which a process running from its snapshot would otherwise misread.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveInstallPath(path, packageRoot) {
|
|
32
|
+
const marker = readRuntimeSnapshotMarker(packageRoot);
|
|
33
|
+
if (!marker)
|
|
34
|
+
return path;
|
|
35
|
+
const inside = relative(packageRoot, path);
|
|
36
|
+
if (inside.startsWith("..") || isAbsolute(inside))
|
|
37
|
+
return path;
|
|
38
|
+
return join(marker.installPackageDir, inside);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=marker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marker.js","sourceRoot":"","sources":["../../src/runtime-snapshot/marker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEvD,MAAM,CAAC,MAAM,uBAAuB,GAAG,uBAAuB,CAAC;AAO/D,MAAM,UAAU,yBAAyB,CAAC,WAAmB;IAC5D,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACJ,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,MAAM,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE,CAAC;YACxG,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,CAAC;IACb,CAAC;IACD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzC,IACC,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,KAAK,IAAI;QACf,SAAS,IAAI,MAAM;QACnB,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ;QAClC,mBAAmB,IAAI,MAAM;QAC7B,OAAO,MAAM,CAAC,iBAAiB,KAAK,QAAQ,EAC3C,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,CAAC;IACjF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,WAAmB;IACnE,MAAM,MAAM,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC3C,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,OAAO,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { isAbsolute, join, relative } from \"node:path\";\n\nexport const RUNTIME_SNAPSHOT_MARKER = \"runtime-snapshot.json\";\n\nexport interface RuntimeSnapshotMarker {\n\treadonly buildId: string;\n\treadonly installPackageDir: string;\n}\n\nexport function readRuntimeSnapshotMarker(packageRoot: string): RuntimeSnapshotMarker | undefined {\n\tlet text: string;\n\ttry {\n\t\ttext = readFileSync(join(packageRoot, RUNTIME_SNAPSHOT_MARKER), \"utf8\");\n\t} catch (error) {\n\t\tif (error instanceof Error && \"code\" in error && (error.code === \"ENOENT\" || error.code === \"ENOTDIR\")) {\n\t\t\treturn undefined;\n\t\t}\n\t\tthrow error;\n\t}\n\tconst parsed: unknown = JSON.parse(text);\n\tif (\n\t\ttypeof parsed === \"object\" &&\n\t\tparsed !== null &&\n\t\t\"buildId\" in parsed &&\n\t\ttypeof parsed.buildId === \"string\" &&\n\t\t\"installPackageDir\" in parsed &&\n\t\ttypeof parsed.installPackageDir === \"string\"\n\t) {\n\t\treturn { buildId: parsed.buildId, installPackageDir: parsed.installPackageDir };\n\t}\n\treturn undefined;\n}\n\n/**\n * Maps a path inside a runtime snapshot to the same path inside the install it was taken from.\n * Install-method detection, self-update and quarantine logic reason about where the package\n * manager put the package, which a process running from its snapshot would otherwise misread.\n */\nexport function resolveInstallPath(path: string, packageRoot: string): string {\n\tconst marker = readRuntimeSnapshotMarker(packageRoot);\n\tif (!marker) return path;\n\tconst inside = relative(packageRoot, path);\n\tif (inside.startsWith(\"..\") || isAbsolute(inside)) return path;\n\treturn join(marker.installPackageDir, inside);\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const UNUSED_SNAPSHOT_GRACE_MS: number;
|
|
2
|
+
/**
|
|
3
|
+
* Runs `task` while holding the runtime root's lock; undefined when the lock stays busy.
|
|
4
|
+
* The lock is a directory, so creating it is atomic on every platform and filesystem.
|
|
5
|
+
*/
|
|
6
|
+
export declare function withRuntimeLock<T>(root: string, task: () => T): T | undefined;
|
|
7
|
+
export declare function isProcessAlive(pid: number): boolean;
|
|
8
|
+
export declare function claimRuntimeSnapshot(snapshotDir: string, pid: number): void;
|
|
9
|
+
/**
|
|
10
|
+
* Removes snapshots no live process claims and nobody used within the grace period, plus
|
|
11
|
+
* staging and trash leftovers of crashed launches. `keep` is the snapshot this launch runs.
|
|
12
|
+
*/
|
|
13
|
+
export declare function pruneRuntimeSnapshots(root: string, keep: string, now: number, isAlive?: (pid: number) => boolean): void;
|
|
14
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/runtime-snapshot/registry.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,wBAAwB,QAAc,CAAC;AAoBpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAwB7E;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQnD;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAK3E;AAsBD;;;GAGG;AACH,wBAAgB,qBAAqB,CACpC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAwB,GAChD,IAAI,CAgBN"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { mkdirSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, utimesSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { RUNTIME_SNAPSHOT_MARKER } from "./marker.js";
|
|
4
|
+
const LOCK_NAME = ".lock";
|
|
5
|
+
const CLAIMS_DIR = "claims";
|
|
6
|
+
const STALE_LOCK_MS = 30_000;
|
|
7
|
+
const LOCK_WAIT_MS = 5_000;
|
|
8
|
+
const LOCK_RETRY_MS = 25;
|
|
9
|
+
export const UNUSED_SNAPSHOT_GRACE_MS = 10 * 60_000;
|
|
10
|
+
const LEFTOVER_MS = 60 * 60_000;
|
|
11
|
+
function errorCode(error) {
|
|
12
|
+
return error instanceof Error && "code" in error ? error.code : undefined;
|
|
13
|
+
}
|
|
14
|
+
function ageMs(path, now) {
|
|
15
|
+
try {
|
|
16
|
+
return now - statSync(path).mtimeMs;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (errorCode(error) === "ENOENT")
|
|
20
|
+
return Number.POSITIVE_INFINITY;
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function sleepSync(ms) {
|
|
25
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Runs `task` while holding the runtime root's lock; undefined when the lock stays busy.
|
|
29
|
+
* The lock is a directory, so creating it is atomic on every platform and filesystem.
|
|
30
|
+
*/
|
|
31
|
+
export function withRuntimeLock(root, task) {
|
|
32
|
+
mkdirSync(root, { recursive: true });
|
|
33
|
+
const lock = join(root, LOCK_NAME);
|
|
34
|
+
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
35
|
+
for (;;) {
|
|
36
|
+
try {
|
|
37
|
+
mkdirSync(lock);
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (errorCode(error) !== "EEXIST")
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
if (ageMs(lock, Date.now()) > STALE_LOCK_MS) {
|
|
45
|
+
rmSync(lock, { recursive: true, force: true });
|
|
46
|
+
}
|
|
47
|
+
else if (Date.now() > deadline) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
sleepSync(LOCK_RETRY_MS);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
return task();
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
rmSync(lock, { recursive: true, force: true });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function isProcessAlive(pid) {
|
|
62
|
+
try {
|
|
63
|
+
process.kill(pid, 0);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
// EPERM: alive, owned by someone else. Anything but "no such process" keeps the snapshot.
|
|
68
|
+
return errorCode(error) !== "ESRCH";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function claimRuntimeSnapshot(snapshotDir, pid) {
|
|
72
|
+
mkdirSync(join(snapshotDir, CLAIMS_DIR), { recursive: true });
|
|
73
|
+
writeFileSync(join(snapshotDir, CLAIMS_DIR, String(pid)), "");
|
|
74
|
+
const now = new Date();
|
|
75
|
+
utimesSync(join(snapshotDir, RUNTIME_SNAPSHOT_MARKER), now, now);
|
|
76
|
+
}
|
|
77
|
+
function reapClaims(snapshotDir, isAlive) {
|
|
78
|
+
let names;
|
|
79
|
+
try {
|
|
80
|
+
names = readdirSync(join(snapshotDir, CLAIMS_DIR));
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (errorCode(error) === "ENOENT")
|
|
84
|
+
return 0;
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
let live = 0;
|
|
88
|
+
for (const name of names) {
|
|
89
|
+
const pid = Number(name);
|
|
90
|
+
if (Number.isSafeInteger(pid) && pid > 0 && isAlive(pid)) {
|
|
91
|
+
live += 1;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
unlinkSync(join(snapshotDir, CLAIMS_DIR, name));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return live;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Removes snapshots no live process claims and nobody used within the grace period, plus
|
|
101
|
+
* staging and trash leftovers of crashed launches. `keep` is the snapshot this launch runs.
|
|
102
|
+
*/
|
|
103
|
+
export function pruneRuntimeSnapshots(root, keep, now, isAlive = isProcessAlive) {
|
|
104
|
+
reapClaims(join(root, keep), isAlive);
|
|
105
|
+
for (const name of readdirSync(root)) {
|
|
106
|
+
if (name === LOCK_NAME || name === keep)
|
|
107
|
+
continue;
|
|
108
|
+
const path = join(root, name);
|
|
109
|
+
if (name.startsWith(".")) {
|
|
110
|
+
if (ageMs(path, now) > LEFTOVER_MS)
|
|
111
|
+
rmSync(path, { recursive: true, force: true });
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (reapClaims(path, isAlive) > 0)
|
|
115
|
+
continue;
|
|
116
|
+
if (ageMs(join(path, RUNTIME_SNAPSHOT_MARKER), now) <= UNUSED_SNAPSHOT_GRACE_MS)
|
|
117
|
+
continue;
|
|
118
|
+
// Rename first: a half-deleted snapshot must never keep a name a launch could pick up.
|
|
119
|
+
const trash = join(root, `.trash-${name}-${process.pid}`);
|
|
120
|
+
renameSync(path, trash);
|
|
121
|
+
rmSync(trash, { recursive: true, force: true });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/runtime-snapshot/registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, utimesSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { RUNTIME_SNAPSHOT_MARKER } from \"./marker.ts\";\n\nconst LOCK_NAME = \".lock\";\nconst CLAIMS_DIR = \"claims\";\nconst STALE_LOCK_MS = 30_000;\nconst LOCK_WAIT_MS = 5_000;\nconst LOCK_RETRY_MS = 25;\nexport const UNUSED_SNAPSHOT_GRACE_MS = 10 * 60_000;\nconst LEFTOVER_MS = 60 * 60_000;\n\nfunction errorCode(error: unknown): unknown {\n\treturn error instanceof Error && \"code\" in error ? error.code : undefined;\n}\n\nfunction ageMs(path: string, now: number): number {\n\ttry {\n\t\treturn now - statSync(path).mtimeMs;\n\t} catch (error) {\n\t\tif (errorCode(error) === \"ENOENT\") return Number.POSITIVE_INFINITY;\n\t\tthrow error;\n\t}\n}\n\nfunction sleepSync(ms: number): void {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\n/**\n * Runs `task` while holding the runtime root's lock; undefined when the lock stays busy.\n * The lock is a directory, so creating it is atomic on every platform and filesystem.\n */\nexport function withRuntimeLock<T>(root: string, task: () => T): T | undefined {\n\tmkdirSync(root, { recursive: true });\n\tconst lock = join(root, LOCK_NAME);\n\tconst deadline = Date.now() + LOCK_WAIT_MS;\n\tfor (;;) {\n\t\ttry {\n\t\t\tmkdirSync(lock);\n\t\t\tbreak;\n\t\t} catch (error) {\n\t\t\tif (errorCode(error) !== \"EEXIST\") throw error;\n\t\t}\n\t\tif (ageMs(lock, Date.now()) > STALE_LOCK_MS) {\n\t\t\trmSync(lock, { recursive: true, force: true });\n\t\t} else if (Date.now() > deadline) {\n\t\t\treturn undefined;\n\t\t} else {\n\t\t\tsleepSync(LOCK_RETRY_MS);\n\t\t}\n\t}\n\ttry {\n\t\treturn task();\n\t} finally {\n\t\trmSync(lock, { recursive: true, force: true });\n\t}\n}\n\nexport function isProcessAlive(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (error) {\n\t\t// EPERM: alive, owned by someone else. Anything but \"no such process\" keeps the snapshot.\n\t\treturn errorCode(error) !== \"ESRCH\";\n\t}\n}\n\nexport function claimRuntimeSnapshot(snapshotDir: string, pid: number): void {\n\tmkdirSync(join(snapshotDir, CLAIMS_DIR), { recursive: true });\n\twriteFileSync(join(snapshotDir, CLAIMS_DIR, String(pid)), \"\");\n\tconst now = new Date();\n\tutimesSync(join(snapshotDir, RUNTIME_SNAPSHOT_MARKER), now, now);\n}\n\nfunction reapClaims(snapshotDir: string, isAlive: (pid: number) => boolean): number {\n\tlet names: string[];\n\ttry {\n\t\tnames = readdirSync(join(snapshotDir, CLAIMS_DIR));\n\t} catch (error) {\n\t\tif (errorCode(error) === \"ENOENT\") return 0;\n\t\tthrow error;\n\t}\n\tlet live = 0;\n\tfor (const name of names) {\n\t\tconst pid = Number(name);\n\t\tif (Number.isSafeInteger(pid) && pid > 0 && isAlive(pid)) {\n\t\t\tlive += 1;\n\t\t} else {\n\t\t\tunlinkSync(join(snapshotDir, CLAIMS_DIR, name));\n\t\t}\n\t}\n\treturn live;\n}\n\n/**\n * Removes snapshots no live process claims and nobody used within the grace period, plus\n * staging and trash leftovers of crashed launches. `keep` is the snapshot this launch runs.\n */\nexport function pruneRuntimeSnapshots(\n\troot: string,\n\tkeep: string,\n\tnow: number,\n\tisAlive: (pid: number) => boolean = isProcessAlive,\n): void {\n\treapClaims(join(root, keep), isAlive);\n\tfor (const name of readdirSync(root)) {\n\t\tif (name === LOCK_NAME || name === keep) continue;\n\t\tconst path = join(root, name);\n\t\tif (name.startsWith(\".\")) {\n\t\t\tif (ageMs(path, now) > LEFTOVER_MS) rmSync(path, { recursive: true, force: true });\n\t\t\tcontinue;\n\t\t}\n\t\tif (reapClaims(path, isAlive) > 0) continue;\n\t\tif (ageMs(join(path, RUNTIME_SNAPSHOT_MARKER), now) <= UNUSED_SNAPSHOT_GRACE_MS) continue;\n\t\t// Rename first: a half-deleted snapshot must never keep a name a launch could pick up.\n\t\tconst trash = join(root, `.trash-${name}-${process.pid}`);\n\t\trenameSync(path, trash);\n\t\trmSync(trash, { recursive: true, force: true });\n\t}\n}\n"]}
|
package/dist/senpi
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
3
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
4
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
5
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
return path;
|
|
9
|
+
};
|
|
2
10
|
import "./valid-cwd.js";
|
|
3
11
|
import { spawn, spawnSync } from "node:child_process";
|
|
4
12
|
import { existsSync, realpathSync } from "node:fs";
|
|
5
|
-
import { join } from "node:path";
|
|
13
|
+
import { dirname, join } from "node:path";
|
|
6
14
|
import { fileURLToPath } from "node:url";
|
|
7
15
|
import { processBunRuntimeOptions, resolveBunReexec } from "./bun-runtime.js";
|
|
8
16
|
import { enableStartupCompileCache } from "./compile-cache.js";
|
|
9
|
-
import { APP_NAME, DISPLAY_VERSION,
|
|
17
|
+
import { APP_NAME, DISPLAY_VERSION, findNodePackageDir, getAgentDir, getInstallPackageDir, isBundledNode, } from "./config.js";
|
|
10
18
|
import { hasInheritedInspectorOption, releaseInheritedInspectorForChild } from "./inspector-policy.js";
|
|
19
|
+
import { prepareRuntimeSnapshot } from "./runtime-snapshot/enter.js";
|
|
11
20
|
import { handleBootstrapSelfUpdate } from "./self-update-bootstrap.js";
|
|
12
21
|
// Upstream's `cli/setup.ts` helper is deliberately not used here: this launcher only decides the
|
|
13
22
|
// runtime and process structure, and `cli-main.ts` performs the equivalent process/title/env/http
|
|
@@ -142,7 +151,7 @@ if (isRootCommand(args) && args.some((arg) => arg === "--help" || arg === "-h"))
|
|
|
142
151
|
process.exit();
|
|
143
152
|
}
|
|
144
153
|
}
|
|
145
|
-
if (isMissingBundledWorkspaceDependencies(
|
|
154
|
+
if (isMissingBundledWorkspaceDependencies(getInstallPackageDir())) {
|
|
146
155
|
if (await handleBootstrapSelfUpdate(args)) {
|
|
147
156
|
process.exit();
|
|
148
157
|
}
|
|
@@ -155,6 +164,17 @@ else {
|
|
|
155
164
|
// `process.exitCode` and any `process.exit()` of its own, so importing it here IS the run - there
|
|
156
165
|
// is no result to forward. It has to be a dynamic import: a static one would evaluate the whole
|
|
157
166
|
// engine graph before the `--version` and bootstrap-repair paths above, which answer without it.
|
|
158
|
-
|
|
167
|
+
// A bundled install hands the run to its runtime snapshot's own copy of this entry instead, so
|
|
168
|
+
// an upgrade that rewrites the install cannot remove chunks this session imports later (#2358).
|
|
169
|
+
const entryPath = fileURLToPath(import.meta.url);
|
|
170
|
+
const snapshot = isBundledNode
|
|
171
|
+
? prepareRuntimeSnapshot(entryPath, findNodePackageDir(dirname(entryPath)), getAgentDir())
|
|
172
|
+
: undefined;
|
|
173
|
+
if (snapshot?.kind === "hand-off") {
|
|
174
|
+
await import(__rewriteRelativeImportExtension(snapshot.entryUrl));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
await import("./cli-main.js");
|
|
178
|
+
}
|
|
159
179
|
}
|
|
160
180
|
//# sourceMappingURL=cli.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/senpi-codemode",
|
|
3
|
-
"version": "2026.9.29-
|
|
3
|
+
"version": "2026.9.29-3",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Source-only senpi extension package for codemode evaluation tools",
|
|
6
6
|
"type": "module",
|
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@babel/parser": "8.0.4",
|
|
34
|
-
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.29-
|
|
34
|
+
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.29-3",
|
|
35
35
|
"typebox": "1.3.34"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@code-yeongyu/senpi": "2026.9.29-
|
|
38
|
+
"@code-yeongyu/senpi": "2026.9.29-3"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@code-yeongyu/senpi": "2026.9.29-
|
|
41
|
+
"@code-yeongyu/senpi": "2026.9.29-3"
|
|
42
42
|
},
|
|
43
43
|
"keywords": [
|
|
44
44
|
"senpi",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-agent-core",
|
|
3
|
-
"version": "2026.9.29-
|
|
3
|
+
"version": "2026.9.29-3",
|
|
4
4
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@earendil-works/chord": "0.85.1",
|
|
60
|
-
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.29-
|
|
61
|
-
"@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.9.29-
|
|
60
|
+
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.29-3",
|
|
61
|
+
"@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.9.29-3",
|
|
62
62
|
"diff": "9.0.0",
|
|
63
63
|
"ignore": "7.0.9",
|
|
64
64
|
"typebox": "1.3.34",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../src/api/lazy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAoB,qBAAqB,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../src/api/lazy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAoB,qBAAqB,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AA8DvE;;;;GAIG;AACH,wBAAgB,UAAU,CACzB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,KAAK,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC,GACxD,2BAA2B,CAqB7B;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,EAAE,YAAY,CAAC,EAAE,mBAAmB,GAAG,eAAe,CAyBjH"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
2
|
+
import { describeReplacedInstall } from "../utils/provider-failure-description.js";
|
|
2
3
|
function createSetupErrorMessage(model, error) {
|
|
3
4
|
return {
|
|
4
5
|
role: "assistant",
|
|
@@ -15,7 +16,7 @@ function createSetupErrorMessage(model, error) {
|
|
|
15
16
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
16
17
|
},
|
|
17
18
|
stopReason: "error",
|
|
18
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
19
|
+
errorMessage: describeReplacedInstall(error) ?? (error instanceof Error ? error.message : String(error)),
|
|
19
20
|
timestamp: Date.now(),
|
|
20
21
|
};
|
|
21
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../src/api/lazy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../src/api/lazy.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, AssistantMessage, AssistantMessageEvent, Model, ProviderStreams } from \"../types.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { describeReplacedInstall } from \"../utils/provider-failure-description.ts\";\n\nfunction createSetupErrorMessage(model: Model<Api>, error: unknown): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotalTokens: 0,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t\tstopReason: \"error\",\n\t\terrorMessage: describeReplacedInstall(error) ?? (error instanceof Error ? error.message : String(error)),\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction hasResult(\n\tsource: AsyncIterable<AssistantMessageEvent>,\n): source is AsyncIterable<AssistantMessageEvent> & { result(): Promise<AssistantMessage> } {\n\treturn typeof (source as { result?: unknown }).result === \"function\";\n}\n\nclass LazyAssistantMessageEventStream extends AssistantMessageEventStream {\n\tprivate cancellationHandler: (() => Promise<void>) | undefined;\n\n\tsetCancellationHandler(handler: () => Promise<void>): void {\n\t\tthis.cancellationHandler = handler;\n\t}\n\n\toverride [Symbol.asyncIterator](): AsyncIterator<AssistantMessageEvent> {\n\t\tconst iterator = super[Symbol.asyncIterator]();\n\t\treturn {\n\t\t\tnext: () => iterator.next(),\n\t\t\treturn: async () => {\n\t\t\t\tawait this.cancellationHandler?.();\n\t\t\t\treturn { value: undefined, done: true };\n\t\t\t},\n\t\t};\n\t}\n}\n\nasync function forwardStream(\n\ttarget: AssistantMessageEventStream,\n\tsource: AsyncIterable<AssistantMessageEvent>,\n\titerator: AsyncIterator<AssistantMessageEvent>,\n): Promise<void> {\n\tfor (;;) {\n\t\tconst event = await iterator.next();\n\t\tif (event.done) break;\n\t\ttarget.push(event.value);\n\t}\n\ttarget.end(hasResult(source) ? await source.result() : undefined);\n}\n\n/**\n * Returns a stream synchronously while running async setup (auth resolution,\n * lazy module loading) behind it. Setup failures terminate the stream with an\n * error event.\n */\nexport function lazyStream(\n\tmodel: Model<Api>,\n\tsetup: () => Promise<AsyncIterable<AssistantMessageEvent>>,\n): AssistantMessageEventStream {\n\tconst outer = new LazyAssistantMessageEventStream();\n\tconst inner = setup();\n\tconst iterator = inner.then((source) => source[Symbol.asyncIterator]());\n\tlet cancellation: Promise<void> | undefined;\n\touter.setCancellationHandler(() => {\n\t\tcancellation ??= iterator.then(async (sourceIterator) => {\n\t\t\tawait sourceIterator.return?.();\n\t\t});\n\t\treturn cancellation;\n\t});\n\n\tPromise.all([inner, iterator])\n\t\t.then(([source, sourceIterator]) => forwardStream(outer, source, sourceIterator))\n\t\t.catch((error) => {\n\t\t\tconst message = createSetupErrorMessage(model, error);\n\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\touter.end(message);\n\t\t});\n\n\treturn outer;\n}\n\n/**\n * Wraps a dynamically imported API implementation module as `ProviderStreams`.\n * The module loads on first stream call; the host's import cache deduplicates\n * loads. Load failures terminate the returned stream with an error event.\n */\nexport interface LazyApiCapabilities {\n\tfetchDeferred?: boolean;\n\tcancelDeferred?: boolean;\n}\n\nexport function lazyApi(load: () => Promise<ProviderStreams>, capabilities?: LazyApiCapabilities): ProviderStreams {\n\tconst api: ProviderStreams = {\n\t\tstream: (model, context, options) =>\n\t\t\tlazyStream(model, async () => (await load()).stream(model, context, options)),\n\t\tstreamSimple: (model, context, options) =>\n\t\t\tlazyStream(model, async () => (await load()).streamSimple(model, context, options)),\n\t};\n\n\tif (capabilities?.fetchDeferred) {\n\t\tapi.fetchDeferred = (model, handle, options) =>\n\t\t\tlazyStream(model, async () => {\n\t\t\t\tconst implementation = await load();\n\t\t\t\tif (!implementation.fetchDeferred) throw new Error(\"API does not support deferred responses\");\n\t\t\t\treturn implementation.fetchDeferred(model, handle, options);\n\t\t\t});\n\t}\n\tif (capabilities?.cancelDeferred) {\n\t\tapi.cancelDeferred = async (model, handle, options) => {\n\t\t\tconst implementation = await load();\n\t\t\tif (!implementation.cancelDeferred) throw new Error(\"API cannot cancel deferred responses\");\n\t\t\tawait implementation.cancelDeferred(model, handle, options);\n\t\t};\n\t}\n\n\treturn api;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"schemaVersion":3,"generatedAt":"2026-09-
|
|
1
|
+
{"schemaVersion":3,"generatedAt":"2026-09-29T10:20:37.605Z","structureHash":"52fb19fe93ffd2fbc624a306411fc8895d903b50b8a3aa559d55a3eb8242a7ce","files":{"alibaba-token-plan.json":"3a9c1be76d47459371e9fa2feeffc31e7edbbfec65fa9cc41236988efc4cf6d9","amazon-bedrock.json":"06ff88f6ea0ddadeb0dedb4e2534664113d67abe162a22fbfde56b61270f5f60","ant-ling.json":"4979fe79d99ed97382d7ce40170c6132e932e77906de1eb54464c042e7d63633","anthropic.json":"bcea362f1b202fe30210102bc44248b9068d7570cfad714959b5d7bdd5cbdbed","azure-openai-responses.json":"d97b98b63595dd30c138a5bcba724017f5c09c489b56be254828a298cfa087e1","bai.json":"2b12b15bd43462e60711944dd7283db8676611d9d76c82c2a01f64913e16a67e","baseten.json":"d155c434294b5167244cffb6dea6793f9669e91e8ab65b564f9510d81b330e37","cerebras.json":"3be228c613905c215c9da3d0b3535e10cc594ff2351b05390744c7c34de89b6c","chatgpt-subscription.json":"421c6ad932de4259c8f0c08589da278bed99ec80c042f2490d8ffd2a86f4da99","cloudflare-ai-gateway.json":"9cbdb4ce62fd5ee10f5471a3061103f00c0f9dbc641df64a9b9cc4e579913390","cloudflare-workers-ai.json":"6012eb769382a5a9fa96ec5f429f6744848e377327c9063573a15006ef0652ce","deepseek.json":"b5f9693ec641e9a957dc5f7a22042b3bb928bac3d7268406619b6f18e21c4b83","fireworks.json":"bbb8149854a2658f221afa47ae8e2617e6b58a8e2784aa822faaf54f0c0f18c3","github-copilot.json":"3f992fcc309cb882f5a0391fd61b8a80e9534e2d932bd480519d01b74fafeb52","google-vertex.json":"97d80ac909d256cc1bf19ac54d9d8131c492e7c0c102ad89f68ade528544e0ad","google.json":"68f6cf6283cc0d69b77b0fa79e9c94774e96524f61ebba616319f05d5c9db56c","groq.json":"e4728fd72e358cd8f25e9a518e9b49a521ef44523d3debe38a7db9e0663c4077","huggingface.json":"2f93082144a7b2a1cbf79148244ce7559e0428d6310c5eb0648bca89b15a8b4b","minimax-cn.json":"4f636b47b28a507ad33b5eaba33fc4889e5956504d10f2a0d9c61167ae01ff1d","minimax.json":"9fd1764ffeefebded8579039cf0c48854a43e4c5b724f62361fc2ac54f705aa1","mistral.json":"9da97430d9b86ad7f606b0fc088694e7a04c38bfa8963a33e1205b3141c917eb","moonshotai-cn.json":"326de79b46f6fdbf0879f005b3040d1b14049e81fa678de407b73ed1bd3bce9c","moonshotai.json":"4b917a375e9c880b903927cf5fe1ae1052c74b64d5027a007bb1e67ad0410755","nvidia.json":"6493e09b5db8b8fe9c8fae5bc15dc287645f37f83a4ed3a1ad1181e5830b5ff7","openai.json":"1856254ecf9b016193c34c9081e2fd87b95bfb837d9ee6dbf6c0e30c94044fd5","opencode-go.json":"d8bb59f10e2ba10fe6f1e36828fecbbfd92804352e89f28506ee468e69657f78","opencode.json":"2f032f74395a11d8cc65d77657f2e061ce157788b4166e5f8227394c1c911e87","opengateway.json":"8970a8cf8ad029099f4955d7d5ec656e797add94ffb38f1d041445eea3050153","openrouter.json":"087bcc7adf444528db871ebf2b48dd9e0512a47b5143562899aa8aff99a7eb05","qwen-token-plan-cn.json":"4bf520ed38e5c3045680d2ec2816fa8a69079dbe97f7b929767a63172288da6b","qwen-token-plan-individual.json":"eb040e78595853e980011308b1bf9caacae6dc8a91abbac5ffebd402515dd2a6","qwen-token-plan.json":"a5c67213745329ec3ba79f712f31c1c32a781d7ffb8c04f9819f36c27672531f","together.json":"b4971d293e5be6b9acaf7b5d9aa588e6374e5317c116e98437128197c39a2fac","venice.json":"3ac1c1b310e4a58a9871385911be5d5706da4fb27c875d4f6d91cf727087ffff","vercel-ai-gateway.json":"2fe131cadebe7da3d552bab71b49c6440b3b4d003a22a617e22a497110d29342","xai.json":"9b23faa5218e966a17108c05d2498a617ade1eae9b0d0684284c77d67949a3f1","xiaomi-token-plan-ams.json":"7df74a255259fc1d5be8e682c3ffb0908eaaf0af711f6433dedcf345ce3e8393","xiaomi-token-plan-cn.json":"7dc672723d5b37e5b92605752f74f46f44eba10be2b0cb959790260b9e0c2a4e","xiaomi-token-plan-sgp.json":"69b333b158be038459a511a673f4536a5b03d4931c3119339f1ac741bc03d502","xiaomi.json":"333299657f211ad9edac0f3d4298b7e5776626914c9c80e22305a87533f23966","zai-coding-cn.json":"69c572aa75104f16ccbddbaace60c267f4bcc74f86d34891ca43110d312fb1ad","zai.json":"15c8182a88e58bdc1b1c3eb0603c690475342c8a826ceddfe9af1b36b28345ee"}}
|