@elpapi42/pi-fleet 0.1.0-beta.6 → 0.1.0-beta.9
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 +48 -0
- package/README.md +12 -5
- package/dist/cli-meta.json +6 -6
- package/dist/cli.mjs +13 -8
- package/dist/cli.mjs.map +2 -2
- package/dist/installer-meta.json +5 -5
- package/dist/installer.mjs +1 -24
- package/dist/installer.mjs.map +2 -2
- package/dist/runtime-manifest.json +19 -19
- package/dist/runtime-meta.json +6 -6
- package/dist/runtime.mjs +50 -3
- package/dist/runtime.mjs.map +2 -2
- package/package.json +3 -2
package/dist/installer-meta.json
CHANGED
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
"format": "esm"
|
|
107
107
|
},
|
|
108
108
|
"src/entry/installer.ts": {
|
|
109
|
-
"bytes":
|
|
109
|
+
"bytes": 2122,
|
|
110
110
|
"imports": [
|
|
111
111
|
{
|
|
112
112
|
"path": "node:child_process",
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
"imports": [],
|
|
153
153
|
"exports": [],
|
|
154
154
|
"inputs": {},
|
|
155
|
-
"bytes":
|
|
155
|
+
"bytes": 46371
|
|
156
156
|
},
|
|
157
157
|
"dist/installer.mjs": {
|
|
158
158
|
"imports": [
|
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
"entryPoint": "src/entry/installer.ts",
|
|
251
251
|
"inputs": {
|
|
252
252
|
"src/entry/installer.ts": {
|
|
253
|
-
"bytesInOutput":
|
|
253
|
+
"bytesInOutput": 1706
|
|
254
254
|
},
|
|
255
255
|
"src/platform/install/service-installer.ts": {
|
|
256
256
|
"bytesInOutput": 4151
|
|
@@ -265,10 +265,10 @@
|
|
|
265
265
|
"bytesInOutput": 2193
|
|
266
266
|
},
|
|
267
267
|
"src/platform/shared/paths.ts": {
|
|
268
|
-
"bytesInOutput":
|
|
268
|
+
"bytesInOutput": 404
|
|
269
269
|
}
|
|
270
270
|
},
|
|
271
|
-
"bytes":
|
|
271
|
+
"bytes": 24492
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
}
|
package/dist/installer.mjs
CHANGED
|
@@ -517,29 +517,6 @@ import { join as join4, resolve as resolve3 } from "node:path";
|
|
|
517
517
|
function resolveApplicationRoot(env = process.env) {
|
|
518
518
|
return env.PIFLEET_APPLICATION_ROOT ?? (process.platform === "darwin" ? join4(homedir2(), "Library", "Application Support", "Pi Fleet", "runtime") : join4(env.XDG_DATA_HOME ?? join4(homedir2(), ".local", "share"), "pi-fleet"));
|
|
519
519
|
}
|
|
520
|
-
function resolveFleetPaths(env = process.env) {
|
|
521
|
-
const explicitRoot = env.PIFLEET_STATE_ROOT;
|
|
522
|
-
if (explicitRoot !== void 0) {
|
|
523
|
-
const root = resolve3(explicitRoot);
|
|
524
|
-
return {
|
|
525
|
-
runtimeRoot: root,
|
|
526
|
-
stateRoot: root,
|
|
527
|
-
socketPath: join4(root, "control.sock"),
|
|
528
|
-
databasePath: join4(root, "fleet.sqlite")
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
const runtimeRoot = join4(
|
|
532
|
-
env.XDG_RUNTIME_DIR ?? tmpdir(),
|
|
533
|
-
`pifleet-${process.getuid?.() ?? "user"}`
|
|
534
|
-
);
|
|
535
|
-
const stateRoot = process.platform === "darwin" ? join4(homedir2(), "Library", "Application Support", "Pi Fleet") : join4(env.XDG_STATE_HOME ?? join4(homedir2(), ".local", "state"), "pi-fleet");
|
|
536
|
-
return {
|
|
537
|
-
runtimeRoot,
|
|
538
|
-
stateRoot,
|
|
539
|
-
socketPath: join4(runtimeRoot, "control.sock"),
|
|
540
|
-
databasePath: join4(stateRoot, "fleet.sqlite")
|
|
541
|
-
};
|
|
542
|
-
}
|
|
543
520
|
|
|
544
521
|
// src/entry/installer.ts
|
|
545
522
|
var executor = {
|
|
@@ -548,7 +525,7 @@ var executor = {
|
|
|
548
525
|
}
|
|
549
526
|
};
|
|
550
527
|
async function installRuntimeService() {
|
|
551
|
-
return installMaterializedService(
|
|
528
|
+
return installMaterializedService(process.env.PIFLEET_STATE_ROOT);
|
|
552
529
|
}
|
|
553
530
|
async function repairRuntimeService() {
|
|
554
531
|
return installMaterializedService(process.env.PIFLEET_STATE_ROOT);
|
package/dist/installer.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/entry/installer.ts", "../src/platform/install/service-installer.ts", "../src/platform/install/service-definition.ts", "../src/platform/install/runtime-release.ts", "../src/platform/install/tree-integrity.ts", "../src/platform/shared/paths.ts"],
|
|
4
|
-
"sourcesContent": ["import { execFile } from \"node:child_process\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { promisify } from \"node:util\";\n\nimport {\n installUserService,\n uninstallUserService,\n type CommandExecutor,\n} from \"../platform/install/service-installer.js\";\nimport { materializeRuntime } from \"../platform/install/runtime-release.js\";\nimport { resolveApplicationRoot, resolveFleetPaths } from \"../platform/shared/paths.js\";\n\nconst executor: CommandExecutor = {\n async run(command, args) {\n await promisify(execFile)(command, [...args]);\n },\n};\n\nexport async function installRuntimeService(): Promise<string> {\n return installMaterializedService(resolveFleetPaths().stateRoot);\n}\n\nexport async function repairRuntimeService(): Promise<string> {\n return installMaterializedService(process.env.PIFLEET_STATE_ROOT);\n}\n\nasync function installMaterializedService(stateRoot: string | undefined): Promise<string> {\n const sourceRoot = dirname(dirname(fileURLToPath(import.meta.url)));\n const release = await materializeRuntime({\n sourceRoot,\n applicationRoot: resolveApplicationRoot(),\n });\n return installUserService({\n platform: process.platform,\n definition: {\n nodePath: process.execPath,\n runtimePath: join(release, \"bin\", \"pifleet-runtime.mjs\"),\n ...(stateRoot === undefined ? {} : { stateRoot }),\n },\n executor,\n });\n}\n\nexport async function uninstallRuntimeService(): Promise<void> {\n await uninstallUserService({ platform: process.platform, executor });\n}\n\nasync function main(): Promise<void> {\n const command = process.argv[2];\n if (command === \"install\") {\n process.stdout.write(`${await installRuntimeService()}\\n`);\n return;\n }\n if (command === \"repair\") {\n process.stdout.write(`${await repairRuntimeService()}\\n`);\n return;\n }\n if (command === \"uninstall\") {\n await uninstallRuntimeService();\n return;\n }\n throw new Error(\"Usage: node dist/installer.mjs <install|repair|uninstall>\");\n}\n\nif (process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href) {\n await main();\n}\n", "import { constants } from \"node:fs\";\nimport { access, chmod, mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n launchdAgentPlist,\n systemdUserUnit,\n type ServiceDefinitionOptions,\n} from \"./service-definition.js\";\n\nexport interface CommandExecutor {\n run(command: string, args: readonly string[]): Promise<void>;\n}\n\nexport async function installUserService(options: {\n readonly platform: NodeJS.Platform;\n readonly definition: ServiceDefinitionOptions;\n readonly executor: CommandExecutor;\n readonly home?: string;\n readonly uid?: number;\n}): Promise<string> {\n const home = options.home ?? homedir();\n if (options.platform === \"linux\") {\n const path = join(home, \".config\", \"systemd\", \"user\", \"pi-fleet.service\");\n const effectiveDefinition = await preserveInstalledStateRoot(path, options.definition, \"linux\");\n const definition = systemdUserUnit(effectiveDefinition);\n const needsRepair = await serviceDefinitionNeedsRepair(path, definition, effectiveDefinition);\n if (needsRepair) {\n await atomicWrite(path, definition);\n await options.executor.run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n }\n await options.executor.run(\"systemctl\", [\"--user\", \"enable\", \"--now\", \"pi-fleet.service\"]);\n if (needsRepair) {\n await options.executor.run(\"systemctl\", [\"--user\", \"restart\", \"pi-fleet.service\"]);\n }\n return path;\n }\n if (options.platform === \"darwin\") {\n const path = join(home, \"Library\", \"LaunchAgents\", \"works.elpapi.pifleet.plist\");\n const effectiveDefinition = await preserveInstalledStateRoot(\n path,\n options.definition,\n \"darwin\",\n );\n await atomicWrite(path, launchdAgentPlist(effectiveDefinition));\n const domain = `gui/${options.uid ?? process.getuid?.() ?? 0}`;\n await options.executor.run(\"launchctl\", [\"bootout\", domain, path]).catch(() => undefined);\n await options.executor.run(\"launchctl\", [\"bootstrap\", domain, path]);\n await options.executor.run(\"launchctl\", [\"kickstart\", `${domain}/works.elpapi.pifleet`]);\n return path;\n }\n throw new Error(`Native Pi Fleet supervision is unsupported on ${options.platform}`);\n}\n\nexport async function uninstallUserService(options: {\n readonly platform: NodeJS.Platform;\n readonly executor: CommandExecutor;\n readonly home?: string;\n readonly uid?: number;\n}): Promise<void> {\n const home = options.home ?? homedir();\n if (options.platform === \"linux\") {\n const path = join(home, \".config\", \"systemd\", \"user\", \"pi-fleet.service\");\n await options.executor.run(\"systemctl\", [\"--user\", \"disable\", \"--now\", \"pi-fleet.service\"]);\n await rm(path, { force: true });\n await options.executor.run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n return;\n }\n if (options.platform === \"darwin\") {\n const path = join(home, \"Library\", \"LaunchAgents\", \"works.elpapi.pifleet.plist\");\n const domain = `gui/${options.uid ?? process.getuid?.() ?? 0}`;\n await options.executor.run(\"launchctl\", [\"bootout\", domain, path]).catch(() => undefined);\n await rm(path, { force: true });\n return;\n }\n throw new Error(`Native Pi Fleet supervision is unsupported on ${options.platform}`);\n}\n\nexport async function serviceDefinitionNeedsRepair(\n path: string,\n expectedContents: string,\n definition: ServiceDefinitionOptions,\n): Promise<boolean> {\n const current = await readFile(path, \"utf8\").catch((error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return null;\n throw error;\n });\n if (current !== expectedContents) return true;\n try {\n await access(definition.nodePath, constants.X_OK);\n await access(definition.runtimePath, constants.R_OK);\n return false;\n } catch {\n return true;\n }\n}\n\nasync function preserveInstalledStateRoot(\n path: string,\n definition: ServiceDefinitionOptions,\n platform: \"linux\" | \"darwin\",\n): Promise<ServiceDefinitionOptions> {\n if (definition.stateRoot !== undefined) return definition;\n const current = await readFile(path, \"utf8\").catch((error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return null;\n throw error;\n });\n if (current === null) return definition;\n const encoded =\n platform === \"linux\"\n ? /^Environment=PIFLEET_STATE_ROOT=(.+)$/m.exec(current)?.[1]\n : /<key>PIFLEET_STATE_ROOT<\\/key><string>([^<]+)<\\/string>/.exec(current)?.[1];\n if (encoded === undefined) return definition;\n const stateRoot =\n platform === \"linux\"\n ? encoded\n : encoded\n .replaceAll(\"'\", \"'\")\n .replaceAll(\""\", '\"')\n .replaceAll(\">\", \">\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\"&\", \"&\");\n return { ...definition, stateRoot };\n}\n\nasync function atomicWrite(path: string, contents: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true, mode: 0o700 });\n const temporary = `${path}.tmp-${process.pid}`;\n await writeFile(temporary, contents, { mode: 0o600 });\n await chmod(temporary, 0o600);\n await rename(temporary, path);\n}\n", "import { isAbsolute } from \"node:path\";\n\nexport interface ServiceDefinitionOptions {\n readonly nodePath: string;\n readonly runtimePath: string;\n readonly stateRoot?: string;\n}\n\nexport function systemdUserUnit(options: ServiceDefinitionOptions): string {\n validate(options);\n const environment =\n options.stateRoot === undefined\n ? \"\"\n : `Environment=PIFLEET_STATE_ROOT=${systemdEscape(options.stateRoot)}\\n`;\n return `[Unit]\nDescription=Pi Fleet user runtime\nAfter=default.target\n\n[Service]\nType=simple\nExecStart=${systemdEscape(options.nodePath)} ${systemdEscape(options.runtimePath)}\n${environment}Restart=on-failure\nRestartSec=1\nTimeoutStopSec=10\nUMask=0077\nKillMode=control-group\n\n[Install]\nWantedBy=default.target\n`;\n}\n\nexport function launchdAgentPlist(options: ServiceDefinitionOptions): string {\n validate(options);\n const environment =\n options.stateRoot === undefined\n ? \"\"\n : ` <key>EnvironmentVariables</key>\n <dict><key>PIFLEET_STATE_ROOT</key><string>${xmlEscape(options.stateRoot)}</string></dict>\n`;\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key><string>works.elpapi.pifleet</string>\n <key>ProgramArguments</key>\n <array>\n <string>${xmlEscape(options.nodePath)}</string>\n <string>${xmlEscape(options.runtimePath)}</string>\n </array>\n${environment} <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>\n <key>ProcessType</key><string>Background</string>\n</dict>\n</plist>\n`;\n}\n\nfunction validate(options: ServiceDefinitionOptions): void {\n if (!isAbsolute(options.nodePath) || !isAbsolute(options.runtimePath)) {\n throw new Error(\"Service executables must use absolute paths\");\n }\n}\n\nfunction systemdEscape(value: string): string {\n if (!/^[A-Za-z0-9_./:@-]+$/.test(value)) throw new Error(`Unsafe systemd path ${value}`);\n return value;\n}\n\nfunction xmlEscape(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n}\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport { chmod, cp, lstat, mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { join, posix, resolve, sep } from \"node:path\";\n\nimport { hashDirectoryTree, type TreeIntegrity } from \"./tree-integrity.js\";\n\ninterface RuntimeManifestFile {\n readonly path: string;\n readonly bytes: number;\n readonly sha256: string;\n}\n\ninterface RuntimeDependency {\n readonly path: string;\n readonly name: string;\n readonly version: string;\n}\n\ninterface RuntimeClosure {\n readonly sourceManifestSha256: string;\n readonly tree: TreeIntegrity;\n}\n\ninterface RuntimeManifest {\n readonly schemaVersion: 3;\n readonly package: { readonly name: string; readonly version: string };\n readonly managedPi: string;\n readonly files: readonly RuntimeManifestFile[];\n readonly dependencies: readonly RuntimeDependency[];\n readonly closure?: RuntimeClosure;\n}\n\ninterface PackageMetadata {\n readonly name: string;\n readonly version: string;\n readonly dependencies: Readonly<Record<string, string>>;\n}\n\nconst requiredRuntimeArtifacts = new Set([\n \"package.json\",\n \"bin/pifleet.mjs\",\n \"bin/pifleet-runtime.mjs\",\n \"dist/cli.mjs\",\n \"dist/runtime.mjs\",\n \"dist/sqlite-worker.mjs\",\n]);\nconst dependencyTreePath = \"node_modules\";\n\nexport async function materializeRuntime(options: {\n readonly sourceRoot: string;\n readonly applicationRoot: string;\n readonly hooks?: {\n readonly afterDependencyCopy?: () => Promise<void>;\n };\n}): Promise<string> {\n const sourceRoot = resolve(options.sourceRoot);\n const manifestBytes = await readFile(join(sourceRoot, \"dist\", \"runtime-manifest.json\"));\n const sourceManifest = await parseRuntimeManifest(manifestBytes, sourceRoot);\n if (sourceManifest.closure !== undefined) {\n await verifyRuntime(sourceRoot);\n return sourceRoot;\n }\n await verifyRuntimeFiles(sourceRoot, sourceManifest);\n await verifyDependencyIdentities(sourceRoot, sourceManifest.dependencies);\n\n const sourceTreeRoot = resolveInside(sourceRoot, dependencyTreePath);\n const sourceTreeBefore = await hashDirectoryTree(sourceTreeRoot, dependencyTreePath);\n const sourceManifestSha256 = createHash(\"sha256\").update(manifestBytes).digest(\"hex\");\n const materializedManifest: RuntimeManifest = {\n ...sourceManifest,\n closure: { sourceManifestSha256, tree: sourceTreeBefore },\n };\n const materializedManifestBytes = serializeManifest(materializedManifest);\n const closureHash = createHash(\"sha256\")\n .update(sourceManifestSha256)\n .update(\"\\0\")\n .update(JSON.stringify(sourceTreeBefore))\n .digest(\"hex\")\n .slice(0, 16);\n\n const applicationRoot = resolve(options.applicationRoot);\n await ensurePrivateDirectory(applicationRoot);\n const releasesRoot = join(applicationRoot, \"releases\");\n await ensurePrivateDirectory(releasesRoot);\n const destination = join(releasesRoot, `${sourceManifest.package.version}-${closureHash}`);\n\n if (await pathExists(destination)) {\n await verifyExpectedRuntime(destination, materializedManifest, materializedManifestBytes);\n return destination;\n }\n\n const staging = join(releasesRoot, `.staging-${randomUUID()}`);\n await mkdir(staging, { mode: 0o700 });\n try {\n await cp(join(sourceRoot, \"dist\"), join(staging, \"dist\"), {\n recursive: true,\n dereference: true,\n });\n await cp(join(sourceRoot, \"bin\"), join(staging, \"bin\"), {\n recursive: true,\n dereference: true,\n });\n await cp(join(sourceRoot, \"package.json\"), join(staging, \"package.json\"));\n await cp(sourceTreeRoot, join(staging, dependencyTreePath), {\n recursive: true,\n dereference: true,\n });\n await options.hooks?.afterDependencyCopy?.();\n\n const stagedTree = await hashDirectoryTree(\n join(staging, dependencyTreePath),\n dependencyTreePath,\n );\n assertSameTree(sourceTreeBefore, stagedTree, \"copied dependency closure\");\n const sourceTreeAfter = await hashDirectoryTree(sourceTreeRoot, dependencyTreePath);\n assertSameTree(sourceTreeBefore, sourceTreeAfter, \"source dependency closure\");\n\n await writeFile(join(staging, \"dist\", \"runtime-manifest.json\"), materializedManifestBytes);\n await verifyExpectedRuntime(staging, materializedManifest, materializedManifestBytes);\n await chmod(staging, 0o700);\n try {\n await rename(staging, destination);\n } catch (error: unknown) {\n if (!isDestinationRace(error) || !(await pathExists(destination))) throw error;\n await verifyExpectedRuntime(destination, materializedManifest, materializedManifestBytes);\n }\n return destination;\n } finally {\n await rm(staging, { recursive: true, force: true });\n }\n}\n\nexport async function verifyRuntime(root: string): Promise<void> {\n const resolvedRoot = resolve(root);\n const manifestBytes = await readFile(join(resolvedRoot, \"dist\", \"runtime-manifest.json\"));\n const manifest = await parseRuntimeManifest(manifestBytes, resolvedRoot);\n if (manifest.closure === undefined) {\n throw new Error(\"Runtime release manifest is missing its materialized closure\");\n }\n await verifyRuntimeFiles(resolvedRoot, manifest);\n await verifyDependencyIdentities(resolvedRoot, manifest.dependencies);\n const actualTree = await hashDirectoryTree(\n resolveInside(resolvedRoot, dependencyTreePath),\n dependencyTreePath,\n );\n assertSameTree(manifest.closure.tree, actualTree, \"materialized dependency closure\");\n}\n\nasync function verifyExpectedRuntime(\n root: string,\n expected: RuntimeManifest,\n expectedBytes: Buffer,\n): Promise<void> {\n const manifestPath = join(root, \"dist\", \"runtime-manifest.json\");\n const actualBytes = await readFile(manifestPath);\n if (!actualBytes.equals(expectedBytes)) {\n throw new Error(\"Materialized runtime manifest does not match the expected closure\");\n }\n const actual = await parseRuntimeManifest(actualBytes, root);\n if (actual.closure === undefined || expected.closure === undefined) {\n throw new Error(\"Materialized runtime manifest is missing its closure\");\n }\n await verifyRuntimeFiles(root, actual);\n await verifyDependencyIdentities(root, actual.dependencies);\n const actualTree = await hashDirectoryTree(\n resolveInside(root, dependencyTreePath),\n dependencyTreePath,\n );\n assertSameTree(expected.closure.tree, actualTree, \"materialized dependency closure\");\n}\n\nasync function verifyRuntimeFiles(root: string, manifest: RuntimeManifest): Promise<void> {\n for (const file of manifest.files) {\n const path = resolveInside(root, file.path);\n const info = await lstat(path);\n if (info.isSymbolicLink()) {\n throw new Error(`Runtime artifact ${file.path} must not be a symbolic link`);\n }\n if (!info.isFile() || info.size !== file.bytes) {\n throw new Error(`Runtime artifact ${file.path} has changed`);\n }\n const hash = createHash(\"sha256\")\n .update(await readFile(path))\n .digest(\"hex\");\n if (hash !== file.sha256) {\n throw new Error(`Runtime artifact ${file.path} failed verification`);\n }\n }\n}\n\nasync function verifyDependencyIdentities(\n root: string,\n dependencies: readonly RuntimeDependency[],\n): Promise<void> {\n const nodeModules = resolveInside(root, dependencyTreePath);\n const modulesInfo = await lstat(nodeModules);\n if (!modulesInfo.isDirectory() || modulesInfo.isSymbolicLink()) {\n throw new Error(\"Runtime dependency closure must be a regular directory\");\n }\n for (const dependency of dependencies) {\n const packageRoot = resolveInside(root, dependency.path);\n const packageInfo = await lstat(packageRoot);\n if (!packageInfo.isDirectory() || packageInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency ${dependency.name} must be a regular directory`);\n }\n const packageJsonPath = join(packageRoot, \"package.json\");\n const packageJsonInfo = await lstat(packageJsonPath);\n if (!packageJsonInfo.isFile() || packageJsonInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency ${dependency.name} has an unsafe package.json`);\n }\n const identity = await readPackageMetadata(packageRoot);\n if (identity.name !== dependency.name || identity.version !== dependency.version) {\n throw new Error(`Runtime dependency ${dependency.name} has an unexpected identity`);\n }\n }\n}\n\nasync function parseRuntimeManifest(bytes: Buffer, root: string): Promise<RuntimeManifest> {\n let candidate: unknown;\n try {\n candidate = JSON.parse(bytes.toString(\"utf8\"));\n } catch {\n throw new Error(\"Runtime manifest is not valid JSON\");\n }\n await validateRuntimeManifest(candidate, root);\n return candidate as RuntimeManifest;\n}\n\nasync function validateRuntimeManifest(candidate: unknown, root: string): Promise<void> {\n if (!isRecord(candidate) || candidate.schemaVersion !== 3) {\n throw new Error(\"Runtime manifest has an unsupported schema version\");\n }\n if (\n !isRecord(candidate.package) ||\n typeof candidate.package.name !== \"string\" ||\n typeof candidate.package.version !== \"string\" ||\n typeof candidate.managedPi !== \"string\"\n ) {\n throw new Error(\"Runtime manifest has an invalid package identity\");\n }\n const packageMetadata = await readPackageMetadata(root);\n if (\n candidate.package.name !== packageMetadata.name ||\n candidate.package.version !== packageMetadata.version\n ) {\n throw new Error(\"Runtime manifest package identity does not match package.json\");\n }\n if (!Array.isArray(candidate.files) || !Array.isArray(candidate.dependencies)) {\n throw new Error(\"Runtime manifest has invalid artifact lists\");\n }\n\n const filePaths = new Set<string>();\n for (const file of candidate.files) {\n if (\n !isRecord(file) ||\n !isManifestPath(file.path) ||\n !isValidSize(file.bytes) ||\n !isSha256(file.sha256)\n ) {\n throw new Error(\"Runtime manifest contains an invalid artifact\");\n }\n if (filePaths.has(file.path)) {\n throw new Error(`Runtime manifest has duplicate path ${file.path}`);\n }\n filePaths.add(file.path);\n }\n for (const required of requiredRuntimeArtifacts) {\n if (!filePaths.has(required)) {\n throw new Error(`Runtime manifest is missing required artifact ${required}`);\n }\n }\n\n const dependencyPaths = new Set<string>();\n const dependencyNames = new Set<string>();\n for (const dependency of candidate.dependencies) {\n if (\n !isRecord(dependency) ||\n !isManifestPath(dependency.path) ||\n typeof dependency.name !== \"string\" ||\n dependency.name.length === 0 ||\n typeof dependency.version !== \"string\" ||\n dependency.version.length === 0 ||\n dependency.path !== `node_modules/${dependency.name}`\n ) {\n throw new Error(\"Runtime manifest contains an invalid dependency declaration\");\n }\n if (dependencyPaths.has(dependency.path) || dependencyNames.has(dependency.name)) {\n throw new Error(`Runtime manifest has duplicate dependency ${dependency.name}`);\n }\n dependencyPaths.add(dependency.path);\n dependencyNames.add(dependency.name);\n }\n const expectedDependencies = packageMetadata.dependencies;\n if (\n dependencyNames.size !== Object.keys(expectedDependencies).length ||\n [...dependencyNames].some(\n (name) =>\n expectedDependencies[name] !==\n (candidate.dependencies as Array<Record<string, unknown>>).find(\n (dependency) => dependency.name === name,\n )?.version,\n )\n ) {\n throw new Error(\"Runtime manifest dependencies do not match package.json\");\n }\n\n for (const filePath of filePaths) {\n for (const dependencyPath of dependencyPaths) {\n if (\n filePath === dependencyPath ||\n filePath.startsWith(`${dependencyPath}/`) ||\n dependencyPath.startsWith(`${filePath}/`)\n ) {\n throw new Error(`Runtime manifest has overlapping paths ${filePath} and ${dependencyPath}`);\n }\n }\n }\n\n if (candidate.closure !== undefined) {\n if (\n !isRecord(candidate.closure) ||\n !isSha256(candidate.closure.sourceManifestSha256) ||\n !isTreeIntegrity(candidate.closure.tree) ||\n candidate.closure.tree.path !== dependencyTreePath\n ) {\n throw new Error(\"Runtime manifest contains an invalid materialized closure\");\n }\n }\n}\n\nasync function readPackageMetadata(root: string): Promise<PackageMetadata> {\n let candidate: unknown;\n try {\n candidate = JSON.parse(await readFile(join(root, \"package.json\"), \"utf8\"));\n } catch {\n throw new Error(\"Runtime package.json is not valid JSON\");\n }\n if (\n !isRecord(candidate) ||\n typeof candidate.name !== \"string\" ||\n typeof candidate.version !== \"string\" ||\n (candidate.dependencies !== undefined && !isRecord(candidate.dependencies)) ||\n (isRecord(candidate.dependencies) &&\n Object.values(candidate.dependencies).some((version) => typeof version !== \"string\"))\n ) {\n throw new Error(\"Runtime package.json has invalid package metadata\");\n }\n return {\n name: candidate.name,\n version: candidate.version,\n dependencies: isRecord(candidate.dependencies)\n ? (candidate.dependencies as Record<string, string>)\n : {},\n };\n}\n\nfunction serializeManifest(manifest: RuntimeManifest): Buffer {\n return Buffer.from(`${JSON.stringify(manifest, null, 2)}\\n`);\n}\n\nfunction assertSameTree(expected: TreeIntegrity, actual: TreeIntegrity, label: string): void {\n if (\n expected.path !== actual.path ||\n expected.files !== actual.files ||\n expected.bytes !== actual.bytes ||\n expected.sha256 !== actual.sha256\n ) {\n throw new Error(`Runtime ${label} changed during materialization`);\n }\n}\n\nfunction resolveInside(root: string, path: string): string {\n if (!isManifestPath(path)) throw new Error(`Runtime manifest contains an unsafe path ${path}`);\n const resolved = resolve(root, path);\n if (!resolved.startsWith(`${root}${sep}`)) {\n throw new Error(`Runtime manifest contains an unsafe path ${path}`);\n }\n return resolved;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isManifestPath(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n value.length > 0 &&\n !value.includes(\"\\\\\") &&\n !value.startsWith(\"/\") &&\n posix.normalize(value) === value &&\n value.split(\"/\").every((part) => part.length > 0 && part !== \".\" && part !== \"..\")\n );\n}\n\nfunction isValidSize(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction isSha256(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-f0-9]{64}$/.test(value);\n}\n\nfunction isTreeIntegrity(value: unknown): value is TreeIntegrity {\n return (\n isRecord(value) &&\n isManifestPath(value.path) &&\n isValidSize(value.files) &&\n isValidSize(value.bytes) &&\n isSha256(value.sha256)\n );\n}\n\nfunction isDestinationRace(error: unknown): boolean {\n const code = (error as NodeJS.ErrnoException).code;\n return code === \"EEXIST\" || code === \"ENOTEMPTY\";\n}\n\nasync function ensurePrivateDirectory(path: string): Promise<void> {\n await mkdir(path, { recursive: true, mode: 0o700 });\n const info = await lstat(path);\n if (!info.isDirectory() || info.isSymbolicLink()) {\n throw new Error(`Refusing unsafe runtime release path ${path}`);\n }\n if (typeof process.getuid === \"function\" && info.uid !== process.getuid()) {\n throw new Error(`Runtime release path ${path} is not owned by the current user`);\n }\n await chmod(path, 0o700);\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await lstat(path);\n return true;\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw error;\n }\n}\n", "import { createHash } from \"node:crypto\";\nimport { lstat, readFile, readdir, realpath, stat } from \"node:fs/promises\";\nimport { join, relative, resolve, sep } from \"node:path\";\n\nexport interface TreeIntegrity {\n readonly path: string;\n readonly files: number;\n readonly bytes: number;\n readonly sha256: string;\n}\n\nexport async function hashDirectoryTree(\n root: string,\n manifestPath: string,\n): Promise<TreeIntegrity> {\n const resolvedRoot = resolve(root);\n const entries = await collectFiles(resolvedRoot, resolvedRoot);\n const hash = createHash(\"sha256\");\n let bytes = 0;\n for (const entry of entries) {\n const contents = await readFile(entry.absolutePath);\n bytes += contents.length;\n hash.update(entry.relativePath);\n hash.update(\"\\0\");\n hash.update(String(contents.length));\n hash.update(\"\\0\");\n hash.update(contents);\n hash.update(\"\\0\");\n }\n return {\n path: manifestPath,\n files: entries.length,\n bytes,\n sha256: hash.digest(\"hex\"),\n };\n}\n\nasync function collectFiles(\n root: string,\n directory: string,\n): Promise<Array<{ readonly absolutePath: string; readonly relativePath: string }>> {\n const output: Array<{ absolutePath: string; relativePath: string }> = [];\n for (const name of (await readdir(directory)).sort()) {\n const absolutePath = join(directory, name);\n const linkInfo = await lstat(absolutePath);\n const info = linkInfo.isSymbolicLink() ? await stat(absolutePath) : linkInfo;\n if (info.isDirectory()) {\n if (linkInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency tree contains a directory symlink: ${absolutePath}`);\n }\n output.push(...(await collectFiles(root, absolutePath)));\n continue;\n }\n if (!info.isFile()) {\n throw new Error(`Runtime dependency tree contains an unsupported entry: ${absolutePath}`);\n }\n if (linkInfo.isSymbolicLink()) {\n const target = await realpath(absolutePath);\n if (target !== root && !target.startsWith(`${root}${sep}`)) {\n throw new Error(\n `Runtime dependency tree contains an external file symlink: ${absolutePath}`,\n );\n }\n }\n const relativePath = relative(root, absolutePath).split(sep).join(\"/\");\n if (relativePath.length === 0 || relativePath.startsWith(\"../\")) {\n throw new Error(`Runtime dependency path escapes its root: ${absolutePath}`);\n }\n output.push({ absolutePath, relativePath });\n }\n return output.sort((left, right) => left.relativePath.localeCompare(right.relativePath));\n}\n", "import { homedir, tmpdir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nexport interface FleetPaths {\n readonly runtimeRoot: string;\n readonly stateRoot: string;\n readonly socketPath: string;\n readonly databasePath: string;\n}\n\nexport function resolveApplicationRoot(env: NodeJS.ProcessEnv = process.env): string {\n return (\n env.PIFLEET_APPLICATION_ROOT ??\n (process.platform === \"darwin\"\n ? join(homedir(), \"Library\", \"Application Support\", \"Pi Fleet\", \"runtime\")\n : join(env.XDG_DATA_HOME ?? join(homedir(), \".local\", \"share\"), \"pi-fleet\"))\n );\n}\n\nexport function resolveFleetPaths(env: NodeJS.ProcessEnv = process.env): FleetPaths {\n const explicitRoot = env.PIFLEET_STATE_ROOT;\n if (explicitRoot !== undefined) {\n const root = resolve(explicitRoot);\n return {\n runtimeRoot: root,\n stateRoot: root,\n socketPath: join(root, \"control.sock\"),\n databasePath: join(root, \"fleet.sqlite\"),\n };\n }\n\n const runtimeRoot = join(\n env.XDG_RUNTIME_DIR ?? tmpdir(),\n `pifleet-${process.getuid?.() ?? \"user\"}`,\n );\n const stateRoot =\n process.platform === \"darwin\"\n ? join(homedir(), \"Library\", \"Application Support\", \"Pi Fleet\")\n : join(env.XDG_STATE_HOME ?? join(homedir(), \".local\", \"state\"), \"pi-fleet\");\n return {\n runtimeRoot,\n stateRoot,\n socketPath: join(runtimeRoot, \"control.sock\"),\n databasePath: join(stateRoot, \"fleet.sqlite\"),\n };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { execFile } from \"node:child_process\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { promisify } from \"node:util\";\n\nimport {\n installUserService,\n uninstallUserService,\n type CommandExecutor,\n} from \"../platform/install/service-installer.js\";\nimport { materializeRuntime } from \"../platform/install/runtime-release.js\";\nimport { resolveApplicationRoot } from \"../platform/shared/paths.js\";\n\nconst executor: CommandExecutor = {\n async run(command, args) {\n await promisify(execFile)(command, [...args]);\n },\n};\n\nexport async function installRuntimeService(): Promise<string> {\n return installMaterializedService(process.env.PIFLEET_STATE_ROOT);\n}\n\nexport async function repairRuntimeService(): Promise<string> {\n return installMaterializedService(process.env.PIFLEET_STATE_ROOT);\n}\n\nasync function installMaterializedService(stateRoot: string | undefined): Promise<string> {\n const sourceRoot = dirname(dirname(fileURLToPath(import.meta.url)));\n const release = await materializeRuntime({\n sourceRoot,\n applicationRoot: resolveApplicationRoot(),\n });\n return installUserService({\n platform: process.platform,\n definition: {\n nodePath: process.execPath,\n runtimePath: join(release, \"bin\", \"pifleet-runtime.mjs\"),\n ...(stateRoot === undefined ? {} : { stateRoot }),\n },\n executor,\n });\n}\n\nexport async function uninstallRuntimeService(): Promise<void> {\n await uninstallUserService({ platform: process.platform, executor });\n}\n\nasync function main(): Promise<void> {\n const command = process.argv[2];\n if (command === \"install\") {\n process.stdout.write(`${await installRuntimeService()}\\n`);\n return;\n }\n if (command === \"repair\") {\n process.stdout.write(`${await repairRuntimeService()}\\n`);\n return;\n }\n if (command === \"uninstall\") {\n await uninstallRuntimeService();\n return;\n }\n throw new Error(\"Usage: node dist/installer.mjs <install|repair|uninstall>\");\n}\n\nif (process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href) {\n await main();\n}\n", "import { constants } from \"node:fs\";\nimport { access, chmod, mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n launchdAgentPlist,\n systemdUserUnit,\n type ServiceDefinitionOptions,\n} from \"./service-definition.js\";\n\nexport interface CommandExecutor {\n run(command: string, args: readonly string[]): Promise<void>;\n}\n\nexport async function installUserService(options: {\n readonly platform: NodeJS.Platform;\n readonly definition: ServiceDefinitionOptions;\n readonly executor: CommandExecutor;\n readonly home?: string;\n readonly uid?: number;\n}): Promise<string> {\n const home = options.home ?? homedir();\n if (options.platform === \"linux\") {\n const path = join(home, \".config\", \"systemd\", \"user\", \"pi-fleet.service\");\n const effectiveDefinition = await preserveInstalledStateRoot(path, options.definition, \"linux\");\n const definition = systemdUserUnit(effectiveDefinition);\n const needsRepair = await serviceDefinitionNeedsRepair(path, definition, effectiveDefinition);\n if (needsRepair) {\n await atomicWrite(path, definition);\n await options.executor.run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n }\n await options.executor.run(\"systemctl\", [\"--user\", \"enable\", \"--now\", \"pi-fleet.service\"]);\n if (needsRepair) {\n await options.executor.run(\"systemctl\", [\"--user\", \"restart\", \"pi-fleet.service\"]);\n }\n return path;\n }\n if (options.platform === \"darwin\") {\n const path = join(home, \"Library\", \"LaunchAgents\", \"works.elpapi.pifleet.plist\");\n const effectiveDefinition = await preserveInstalledStateRoot(\n path,\n options.definition,\n \"darwin\",\n );\n await atomicWrite(path, launchdAgentPlist(effectiveDefinition));\n const domain = `gui/${options.uid ?? process.getuid?.() ?? 0}`;\n await options.executor.run(\"launchctl\", [\"bootout\", domain, path]).catch(() => undefined);\n await options.executor.run(\"launchctl\", [\"bootstrap\", domain, path]);\n await options.executor.run(\"launchctl\", [\"kickstart\", `${domain}/works.elpapi.pifleet`]);\n return path;\n }\n throw new Error(`Native Pi Fleet supervision is unsupported on ${options.platform}`);\n}\n\nexport async function uninstallUserService(options: {\n readonly platform: NodeJS.Platform;\n readonly executor: CommandExecutor;\n readonly home?: string;\n readonly uid?: number;\n}): Promise<void> {\n const home = options.home ?? homedir();\n if (options.platform === \"linux\") {\n const path = join(home, \".config\", \"systemd\", \"user\", \"pi-fleet.service\");\n await options.executor.run(\"systemctl\", [\"--user\", \"disable\", \"--now\", \"pi-fleet.service\"]);\n await rm(path, { force: true });\n await options.executor.run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n return;\n }\n if (options.platform === \"darwin\") {\n const path = join(home, \"Library\", \"LaunchAgents\", \"works.elpapi.pifleet.plist\");\n const domain = `gui/${options.uid ?? process.getuid?.() ?? 0}`;\n await options.executor.run(\"launchctl\", [\"bootout\", domain, path]).catch(() => undefined);\n await rm(path, { force: true });\n return;\n }\n throw new Error(`Native Pi Fleet supervision is unsupported on ${options.platform}`);\n}\n\nexport async function serviceDefinitionNeedsRepair(\n path: string,\n expectedContents: string,\n definition: ServiceDefinitionOptions,\n): Promise<boolean> {\n const current = await readFile(path, \"utf8\").catch((error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return null;\n throw error;\n });\n if (current !== expectedContents) return true;\n try {\n await access(definition.nodePath, constants.X_OK);\n await access(definition.runtimePath, constants.R_OK);\n return false;\n } catch {\n return true;\n }\n}\n\nasync function preserveInstalledStateRoot(\n path: string,\n definition: ServiceDefinitionOptions,\n platform: \"linux\" | \"darwin\",\n): Promise<ServiceDefinitionOptions> {\n if (definition.stateRoot !== undefined) return definition;\n const current = await readFile(path, \"utf8\").catch((error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return null;\n throw error;\n });\n if (current === null) return definition;\n const encoded =\n platform === \"linux\"\n ? /^Environment=PIFLEET_STATE_ROOT=(.+)$/m.exec(current)?.[1]\n : /<key>PIFLEET_STATE_ROOT<\\/key><string>([^<]+)<\\/string>/.exec(current)?.[1];\n if (encoded === undefined) return definition;\n const stateRoot =\n platform === \"linux\"\n ? encoded\n : encoded\n .replaceAll(\"'\", \"'\")\n .replaceAll(\""\", '\"')\n .replaceAll(\">\", \">\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\"&\", \"&\");\n return { ...definition, stateRoot };\n}\n\nasync function atomicWrite(path: string, contents: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true, mode: 0o700 });\n const temporary = `${path}.tmp-${process.pid}`;\n await writeFile(temporary, contents, { mode: 0o600 });\n await chmod(temporary, 0o600);\n await rename(temporary, path);\n}\n", "import { isAbsolute } from \"node:path\";\n\nexport interface ServiceDefinitionOptions {\n readonly nodePath: string;\n readonly runtimePath: string;\n readonly stateRoot?: string;\n}\n\nexport function systemdUserUnit(options: ServiceDefinitionOptions): string {\n validate(options);\n const environment =\n options.stateRoot === undefined\n ? \"\"\n : `Environment=PIFLEET_STATE_ROOT=${systemdEscape(options.stateRoot)}\\n`;\n return `[Unit]\nDescription=Pi Fleet user runtime\nAfter=default.target\n\n[Service]\nType=simple\nExecStart=${systemdEscape(options.nodePath)} ${systemdEscape(options.runtimePath)}\n${environment}Restart=on-failure\nRestartSec=1\nTimeoutStopSec=10\nUMask=0077\nKillMode=control-group\n\n[Install]\nWantedBy=default.target\n`;\n}\n\nexport function launchdAgentPlist(options: ServiceDefinitionOptions): string {\n validate(options);\n const environment =\n options.stateRoot === undefined\n ? \"\"\n : ` <key>EnvironmentVariables</key>\n <dict><key>PIFLEET_STATE_ROOT</key><string>${xmlEscape(options.stateRoot)}</string></dict>\n`;\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key><string>works.elpapi.pifleet</string>\n <key>ProgramArguments</key>\n <array>\n <string>${xmlEscape(options.nodePath)}</string>\n <string>${xmlEscape(options.runtimePath)}</string>\n </array>\n${environment} <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>\n <key>ProcessType</key><string>Background</string>\n</dict>\n</plist>\n`;\n}\n\nfunction validate(options: ServiceDefinitionOptions): void {\n if (!isAbsolute(options.nodePath) || !isAbsolute(options.runtimePath)) {\n throw new Error(\"Service executables must use absolute paths\");\n }\n}\n\nfunction systemdEscape(value: string): string {\n if (!/^[A-Za-z0-9_./:@-]+$/.test(value)) throw new Error(`Unsafe systemd path ${value}`);\n return value;\n}\n\nfunction xmlEscape(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n}\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport { chmod, cp, lstat, mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { join, posix, resolve, sep } from \"node:path\";\n\nimport { hashDirectoryTree, type TreeIntegrity } from \"./tree-integrity.js\";\n\ninterface RuntimeManifestFile {\n readonly path: string;\n readonly bytes: number;\n readonly sha256: string;\n}\n\ninterface RuntimeDependency {\n readonly path: string;\n readonly name: string;\n readonly version: string;\n}\n\ninterface RuntimeClosure {\n readonly sourceManifestSha256: string;\n readonly tree: TreeIntegrity;\n}\n\ninterface RuntimeManifest {\n readonly schemaVersion: 3;\n readonly package: { readonly name: string; readonly version: string };\n readonly managedPi: string;\n readonly files: readonly RuntimeManifestFile[];\n readonly dependencies: readonly RuntimeDependency[];\n readonly closure?: RuntimeClosure;\n}\n\ninterface PackageMetadata {\n readonly name: string;\n readonly version: string;\n readonly dependencies: Readonly<Record<string, string>>;\n}\n\nconst requiredRuntimeArtifacts = new Set([\n \"package.json\",\n \"bin/pifleet.mjs\",\n \"bin/pifleet-runtime.mjs\",\n \"dist/cli.mjs\",\n \"dist/runtime.mjs\",\n \"dist/sqlite-worker.mjs\",\n]);\nconst dependencyTreePath = \"node_modules\";\n\nexport async function materializeRuntime(options: {\n readonly sourceRoot: string;\n readonly applicationRoot: string;\n readonly hooks?: {\n readonly afterDependencyCopy?: () => Promise<void>;\n };\n}): Promise<string> {\n const sourceRoot = resolve(options.sourceRoot);\n const manifestBytes = await readFile(join(sourceRoot, \"dist\", \"runtime-manifest.json\"));\n const sourceManifest = await parseRuntimeManifest(manifestBytes, sourceRoot);\n if (sourceManifest.closure !== undefined) {\n await verifyRuntime(sourceRoot);\n return sourceRoot;\n }\n await verifyRuntimeFiles(sourceRoot, sourceManifest);\n await verifyDependencyIdentities(sourceRoot, sourceManifest.dependencies);\n\n const sourceTreeRoot = resolveInside(sourceRoot, dependencyTreePath);\n const sourceTreeBefore = await hashDirectoryTree(sourceTreeRoot, dependencyTreePath);\n const sourceManifestSha256 = createHash(\"sha256\").update(manifestBytes).digest(\"hex\");\n const materializedManifest: RuntimeManifest = {\n ...sourceManifest,\n closure: { sourceManifestSha256, tree: sourceTreeBefore },\n };\n const materializedManifestBytes = serializeManifest(materializedManifest);\n const closureHash = createHash(\"sha256\")\n .update(sourceManifestSha256)\n .update(\"\\0\")\n .update(JSON.stringify(sourceTreeBefore))\n .digest(\"hex\")\n .slice(0, 16);\n\n const applicationRoot = resolve(options.applicationRoot);\n await ensurePrivateDirectory(applicationRoot);\n const releasesRoot = join(applicationRoot, \"releases\");\n await ensurePrivateDirectory(releasesRoot);\n const destination = join(releasesRoot, `${sourceManifest.package.version}-${closureHash}`);\n\n if (await pathExists(destination)) {\n await verifyExpectedRuntime(destination, materializedManifest, materializedManifestBytes);\n return destination;\n }\n\n const staging = join(releasesRoot, `.staging-${randomUUID()}`);\n await mkdir(staging, { mode: 0o700 });\n try {\n await cp(join(sourceRoot, \"dist\"), join(staging, \"dist\"), {\n recursive: true,\n dereference: true,\n });\n await cp(join(sourceRoot, \"bin\"), join(staging, \"bin\"), {\n recursive: true,\n dereference: true,\n });\n await cp(join(sourceRoot, \"package.json\"), join(staging, \"package.json\"));\n await cp(sourceTreeRoot, join(staging, dependencyTreePath), {\n recursive: true,\n dereference: true,\n });\n await options.hooks?.afterDependencyCopy?.();\n\n const stagedTree = await hashDirectoryTree(\n join(staging, dependencyTreePath),\n dependencyTreePath,\n );\n assertSameTree(sourceTreeBefore, stagedTree, \"copied dependency closure\");\n const sourceTreeAfter = await hashDirectoryTree(sourceTreeRoot, dependencyTreePath);\n assertSameTree(sourceTreeBefore, sourceTreeAfter, \"source dependency closure\");\n\n await writeFile(join(staging, \"dist\", \"runtime-manifest.json\"), materializedManifestBytes);\n await verifyExpectedRuntime(staging, materializedManifest, materializedManifestBytes);\n await chmod(staging, 0o700);\n try {\n await rename(staging, destination);\n } catch (error: unknown) {\n if (!isDestinationRace(error) || !(await pathExists(destination))) throw error;\n await verifyExpectedRuntime(destination, materializedManifest, materializedManifestBytes);\n }\n return destination;\n } finally {\n await rm(staging, { recursive: true, force: true });\n }\n}\n\nexport async function verifyRuntime(root: string): Promise<void> {\n const resolvedRoot = resolve(root);\n const manifestBytes = await readFile(join(resolvedRoot, \"dist\", \"runtime-manifest.json\"));\n const manifest = await parseRuntimeManifest(manifestBytes, resolvedRoot);\n if (manifest.closure === undefined) {\n throw new Error(\"Runtime release manifest is missing its materialized closure\");\n }\n await verifyRuntimeFiles(resolvedRoot, manifest);\n await verifyDependencyIdentities(resolvedRoot, manifest.dependencies);\n const actualTree = await hashDirectoryTree(\n resolveInside(resolvedRoot, dependencyTreePath),\n dependencyTreePath,\n );\n assertSameTree(manifest.closure.tree, actualTree, \"materialized dependency closure\");\n}\n\nasync function verifyExpectedRuntime(\n root: string,\n expected: RuntimeManifest,\n expectedBytes: Buffer,\n): Promise<void> {\n const manifestPath = join(root, \"dist\", \"runtime-manifest.json\");\n const actualBytes = await readFile(manifestPath);\n if (!actualBytes.equals(expectedBytes)) {\n throw new Error(\"Materialized runtime manifest does not match the expected closure\");\n }\n const actual = await parseRuntimeManifest(actualBytes, root);\n if (actual.closure === undefined || expected.closure === undefined) {\n throw new Error(\"Materialized runtime manifest is missing its closure\");\n }\n await verifyRuntimeFiles(root, actual);\n await verifyDependencyIdentities(root, actual.dependencies);\n const actualTree = await hashDirectoryTree(\n resolveInside(root, dependencyTreePath),\n dependencyTreePath,\n );\n assertSameTree(expected.closure.tree, actualTree, \"materialized dependency closure\");\n}\n\nasync function verifyRuntimeFiles(root: string, manifest: RuntimeManifest): Promise<void> {\n for (const file of manifest.files) {\n const path = resolveInside(root, file.path);\n const info = await lstat(path);\n if (info.isSymbolicLink()) {\n throw new Error(`Runtime artifact ${file.path} must not be a symbolic link`);\n }\n if (!info.isFile() || info.size !== file.bytes) {\n throw new Error(`Runtime artifact ${file.path} has changed`);\n }\n const hash = createHash(\"sha256\")\n .update(await readFile(path))\n .digest(\"hex\");\n if (hash !== file.sha256) {\n throw new Error(`Runtime artifact ${file.path} failed verification`);\n }\n }\n}\n\nasync function verifyDependencyIdentities(\n root: string,\n dependencies: readonly RuntimeDependency[],\n): Promise<void> {\n const nodeModules = resolveInside(root, dependencyTreePath);\n const modulesInfo = await lstat(nodeModules);\n if (!modulesInfo.isDirectory() || modulesInfo.isSymbolicLink()) {\n throw new Error(\"Runtime dependency closure must be a regular directory\");\n }\n for (const dependency of dependencies) {\n const packageRoot = resolveInside(root, dependency.path);\n const packageInfo = await lstat(packageRoot);\n if (!packageInfo.isDirectory() || packageInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency ${dependency.name} must be a regular directory`);\n }\n const packageJsonPath = join(packageRoot, \"package.json\");\n const packageJsonInfo = await lstat(packageJsonPath);\n if (!packageJsonInfo.isFile() || packageJsonInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency ${dependency.name} has an unsafe package.json`);\n }\n const identity = await readPackageMetadata(packageRoot);\n if (identity.name !== dependency.name || identity.version !== dependency.version) {\n throw new Error(`Runtime dependency ${dependency.name} has an unexpected identity`);\n }\n }\n}\n\nasync function parseRuntimeManifest(bytes: Buffer, root: string): Promise<RuntimeManifest> {\n let candidate: unknown;\n try {\n candidate = JSON.parse(bytes.toString(\"utf8\"));\n } catch {\n throw new Error(\"Runtime manifest is not valid JSON\");\n }\n await validateRuntimeManifest(candidate, root);\n return candidate as RuntimeManifest;\n}\n\nasync function validateRuntimeManifest(candidate: unknown, root: string): Promise<void> {\n if (!isRecord(candidate) || candidate.schemaVersion !== 3) {\n throw new Error(\"Runtime manifest has an unsupported schema version\");\n }\n if (\n !isRecord(candidate.package) ||\n typeof candidate.package.name !== \"string\" ||\n typeof candidate.package.version !== \"string\" ||\n typeof candidate.managedPi !== \"string\"\n ) {\n throw new Error(\"Runtime manifest has an invalid package identity\");\n }\n const packageMetadata = await readPackageMetadata(root);\n if (\n candidate.package.name !== packageMetadata.name ||\n candidate.package.version !== packageMetadata.version\n ) {\n throw new Error(\"Runtime manifest package identity does not match package.json\");\n }\n if (!Array.isArray(candidate.files) || !Array.isArray(candidate.dependencies)) {\n throw new Error(\"Runtime manifest has invalid artifact lists\");\n }\n\n const filePaths = new Set<string>();\n for (const file of candidate.files) {\n if (\n !isRecord(file) ||\n !isManifestPath(file.path) ||\n !isValidSize(file.bytes) ||\n !isSha256(file.sha256)\n ) {\n throw new Error(\"Runtime manifest contains an invalid artifact\");\n }\n if (filePaths.has(file.path)) {\n throw new Error(`Runtime manifest has duplicate path ${file.path}`);\n }\n filePaths.add(file.path);\n }\n for (const required of requiredRuntimeArtifacts) {\n if (!filePaths.has(required)) {\n throw new Error(`Runtime manifest is missing required artifact ${required}`);\n }\n }\n\n const dependencyPaths = new Set<string>();\n const dependencyNames = new Set<string>();\n for (const dependency of candidate.dependencies) {\n if (\n !isRecord(dependency) ||\n !isManifestPath(dependency.path) ||\n typeof dependency.name !== \"string\" ||\n dependency.name.length === 0 ||\n typeof dependency.version !== \"string\" ||\n dependency.version.length === 0 ||\n dependency.path !== `node_modules/${dependency.name}`\n ) {\n throw new Error(\"Runtime manifest contains an invalid dependency declaration\");\n }\n if (dependencyPaths.has(dependency.path) || dependencyNames.has(dependency.name)) {\n throw new Error(`Runtime manifest has duplicate dependency ${dependency.name}`);\n }\n dependencyPaths.add(dependency.path);\n dependencyNames.add(dependency.name);\n }\n const expectedDependencies = packageMetadata.dependencies;\n if (\n dependencyNames.size !== Object.keys(expectedDependencies).length ||\n [...dependencyNames].some(\n (name) =>\n expectedDependencies[name] !==\n (candidate.dependencies as Array<Record<string, unknown>>).find(\n (dependency) => dependency.name === name,\n )?.version,\n )\n ) {\n throw new Error(\"Runtime manifest dependencies do not match package.json\");\n }\n\n for (const filePath of filePaths) {\n for (const dependencyPath of dependencyPaths) {\n if (\n filePath === dependencyPath ||\n filePath.startsWith(`${dependencyPath}/`) ||\n dependencyPath.startsWith(`${filePath}/`)\n ) {\n throw new Error(`Runtime manifest has overlapping paths ${filePath} and ${dependencyPath}`);\n }\n }\n }\n\n if (candidate.closure !== undefined) {\n if (\n !isRecord(candidate.closure) ||\n !isSha256(candidate.closure.sourceManifestSha256) ||\n !isTreeIntegrity(candidate.closure.tree) ||\n candidate.closure.tree.path !== dependencyTreePath\n ) {\n throw new Error(\"Runtime manifest contains an invalid materialized closure\");\n }\n }\n}\n\nasync function readPackageMetadata(root: string): Promise<PackageMetadata> {\n let candidate: unknown;\n try {\n candidate = JSON.parse(await readFile(join(root, \"package.json\"), \"utf8\"));\n } catch {\n throw new Error(\"Runtime package.json is not valid JSON\");\n }\n if (\n !isRecord(candidate) ||\n typeof candidate.name !== \"string\" ||\n typeof candidate.version !== \"string\" ||\n (candidate.dependencies !== undefined && !isRecord(candidate.dependencies)) ||\n (isRecord(candidate.dependencies) &&\n Object.values(candidate.dependencies).some((version) => typeof version !== \"string\"))\n ) {\n throw new Error(\"Runtime package.json has invalid package metadata\");\n }\n return {\n name: candidate.name,\n version: candidate.version,\n dependencies: isRecord(candidate.dependencies)\n ? (candidate.dependencies as Record<string, string>)\n : {},\n };\n}\n\nfunction serializeManifest(manifest: RuntimeManifest): Buffer {\n return Buffer.from(`${JSON.stringify(manifest, null, 2)}\\n`);\n}\n\nfunction assertSameTree(expected: TreeIntegrity, actual: TreeIntegrity, label: string): void {\n if (\n expected.path !== actual.path ||\n expected.files !== actual.files ||\n expected.bytes !== actual.bytes ||\n expected.sha256 !== actual.sha256\n ) {\n throw new Error(`Runtime ${label} changed during materialization`);\n }\n}\n\nfunction resolveInside(root: string, path: string): string {\n if (!isManifestPath(path)) throw new Error(`Runtime manifest contains an unsafe path ${path}`);\n const resolved = resolve(root, path);\n if (!resolved.startsWith(`${root}${sep}`)) {\n throw new Error(`Runtime manifest contains an unsafe path ${path}`);\n }\n return resolved;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isManifestPath(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n value.length > 0 &&\n !value.includes(\"\\\\\") &&\n !value.startsWith(\"/\") &&\n posix.normalize(value) === value &&\n value.split(\"/\").every((part) => part.length > 0 && part !== \".\" && part !== \"..\")\n );\n}\n\nfunction isValidSize(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction isSha256(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-f0-9]{64}$/.test(value);\n}\n\nfunction isTreeIntegrity(value: unknown): value is TreeIntegrity {\n return (\n isRecord(value) &&\n isManifestPath(value.path) &&\n isValidSize(value.files) &&\n isValidSize(value.bytes) &&\n isSha256(value.sha256)\n );\n}\n\nfunction isDestinationRace(error: unknown): boolean {\n const code = (error as NodeJS.ErrnoException).code;\n return code === \"EEXIST\" || code === \"ENOTEMPTY\";\n}\n\nasync function ensurePrivateDirectory(path: string): Promise<void> {\n await mkdir(path, { recursive: true, mode: 0o700 });\n const info = await lstat(path);\n if (!info.isDirectory() || info.isSymbolicLink()) {\n throw new Error(`Refusing unsafe runtime release path ${path}`);\n }\n if (typeof process.getuid === \"function\" && info.uid !== process.getuid()) {\n throw new Error(`Runtime release path ${path} is not owned by the current user`);\n }\n await chmod(path, 0o700);\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await lstat(path);\n return true;\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw error;\n }\n}\n", "import { createHash } from \"node:crypto\";\nimport { lstat, readFile, readdir, realpath, stat } from \"node:fs/promises\";\nimport { join, relative, resolve, sep } from \"node:path\";\n\nexport interface TreeIntegrity {\n readonly path: string;\n readonly files: number;\n readonly bytes: number;\n readonly sha256: string;\n}\n\nexport async function hashDirectoryTree(\n root: string,\n manifestPath: string,\n): Promise<TreeIntegrity> {\n const resolvedRoot = resolve(root);\n const entries = await collectFiles(resolvedRoot, resolvedRoot);\n const hash = createHash(\"sha256\");\n let bytes = 0;\n for (const entry of entries) {\n const contents = await readFile(entry.absolutePath);\n bytes += contents.length;\n hash.update(entry.relativePath);\n hash.update(\"\\0\");\n hash.update(String(contents.length));\n hash.update(\"\\0\");\n hash.update(contents);\n hash.update(\"\\0\");\n }\n return {\n path: manifestPath,\n files: entries.length,\n bytes,\n sha256: hash.digest(\"hex\"),\n };\n}\n\nasync function collectFiles(\n root: string,\n directory: string,\n): Promise<Array<{ readonly absolutePath: string; readonly relativePath: string }>> {\n const output: Array<{ absolutePath: string; relativePath: string }> = [];\n for (const name of (await readdir(directory)).sort()) {\n const absolutePath = join(directory, name);\n const linkInfo = await lstat(absolutePath);\n const info = linkInfo.isSymbolicLink() ? await stat(absolutePath) : linkInfo;\n if (info.isDirectory()) {\n if (linkInfo.isSymbolicLink()) {\n throw new Error(`Runtime dependency tree contains a directory symlink: ${absolutePath}`);\n }\n output.push(...(await collectFiles(root, absolutePath)));\n continue;\n }\n if (!info.isFile()) {\n throw new Error(`Runtime dependency tree contains an unsupported entry: ${absolutePath}`);\n }\n if (linkInfo.isSymbolicLink()) {\n const target = await realpath(absolutePath);\n if (target !== root && !target.startsWith(`${root}${sep}`)) {\n throw new Error(\n `Runtime dependency tree contains an external file symlink: ${absolutePath}`,\n );\n }\n }\n const relativePath = relative(root, absolutePath).split(sep).join(\"/\");\n if (relativePath.length === 0 || relativePath.startsWith(\"../\")) {\n throw new Error(`Runtime dependency path escapes its root: ${absolutePath}`);\n }\n output.push({ absolutePath, relativePath });\n }\n return output.sort((left, right) => left.relativePath.localeCompare(right.relativePath));\n}\n", "import { homedir, tmpdir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nexport interface FleetPaths {\n readonly runtimeRoot: string;\n readonly stateRoot: string;\n readonly socketPath: string;\n readonly databasePath: string;\n}\n\nexport function resolveApplicationRoot(env: NodeJS.ProcessEnv = process.env): string {\n return (\n env.PIFLEET_APPLICATION_ROOT ??\n (process.platform === \"darwin\"\n ? join(homedir(), \"Library\", \"Application Support\", \"Pi Fleet\", \"runtime\")\n : join(env.XDG_DATA_HOME ?? join(homedir(), \".local\", \"share\"), \"pi-fleet\"))\n );\n}\n\nexport function resolveFleetPaths(env: NodeJS.ProcessEnv = process.env): FleetPaths {\n const explicitRoot = env.PIFLEET_STATE_ROOT;\n if (explicitRoot !== undefined) {\n const root = resolve(explicitRoot);\n return {\n runtimeRoot: root,\n stateRoot: root,\n socketPath: join(root, \"control.sock\"),\n databasePath: join(root, \"fleet.sqlite\"),\n };\n }\n\n const runtimeRoot = join(\n env.XDG_RUNTIME_DIR ?? tmpdir(),\n `pifleet-${process.getuid?.() ?? \"user\"}`,\n );\n const stateRoot =\n process.platform === \"darwin\"\n ? join(homedir(), \"Library\", \"Application Support\", \"Pi Fleet\")\n : join(env.XDG_STATE_HOME ?? join(homedir(), \".local\", \"state\"), \"pi-fleet\");\n return {\n runtimeRoot,\n stateRoot,\n socketPath: join(runtimeRoot, \"control.sock\"),\n databasePath: join(stateRoot, \"fleet.sqlite\"),\n };\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,gBAAgB;AACzB,SAAS,WAAAA,UAAS,QAAAC,aAAY;AAC9B,SAAS,eAAe,qBAAqB;AAC7C,SAAS,iBAAiB;;;ACH1B,SAAS,iBAAiB;AAC1B,SAAS,QAAQ,OAAO,OAAO,UAAU,QAAQ,IAAI,iBAAiB;AACtE,SAAS,eAAe;AACxB,SAAS,SAAS,YAAY;;;ACH9B,SAAS,kBAAkB;AAQpB,SAAS,gBAAgB,SAA2C;AACzE,WAAS,OAAO;AAChB,QAAM,cACJ,QAAQ,cAAc,SAClB,KACA,kCAAkC,cAAc,QAAQ,SAAS,CAAC;AAAA;AACxE,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAMG,cAAc,QAAQ,QAAQ,CAAC,IAAI,cAAc,QAAQ,WAAW,CAAC;AAAA,EAC/E,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASb;AAEO,SAAS,kBAAkB,SAA2C;AAC3E,WAAS,OAAO;AAChB,QAAM,cACJ,QAAQ,cAAc,SAClB,KACA;AAAA,iDACyC,UAAU,QAAQ,SAAS,CAAC;AAAA;AAE3E,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAOS,UAAU,QAAQ,QAAQ,CAAC;AAAA,kBAC3B,UAAU,QAAQ,WAAW,CAAC;AAAA;AAAA,EAE9C,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAMb;AAEA,SAAS,SAAS,SAAyC;AACzD,MAAI,CAAC,WAAW,QAAQ,QAAQ,KAAK,CAAC,WAAW,QAAQ,WAAW,GAAG;AACrE,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACF;AAEA,SAAS,cAAc,OAAuB;AAC5C,MAAI,CAAC,uBAAuB,KAAK,KAAK,EAAG,OAAM,IAAI,MAAM,uBAAuB,KAAK,EAAE;AACvF,SAAO;AACT;AAEA,SAAS,UAAU,OAAuB;AACxC,SAAO,MACJ,WAAW,KAAK,OAAO,EACvB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,QAAQ,EACxB,WAAW,KAAK,QAAQ;AAC7B;;;AD7DA,eAAsB,mBAAmB,SAMrB;AAClB,QAAM,OAAO,QAAQ,QAAQ,QAAQ;AACrC,MAAI,QAAQ,aAAa,SAAS;AAChC,UAAM,OAAO,KAAK,MAAM,WAAW,WAAW,QAAQ,kBAAkB;AACxE,UAAM,sBAAsB,MAAM,2BAA2B,MAAM,QAAQ,YAAY,OAAO;AAC9F,UAAM,aAAa,gBAAgB,mBAAmB;AACtD,UAAM,cAAc,MAAM,6BAA6B,MAAM,YAAY,mBAAmB;AAC5F,QAAI,aAAa;AACf,YAAM,YAAY,MAAM,UAAU;AAClC,YAAM,QAAQ,SAAS,IAAI,aAAa,CAAC,UAAU,eAAe,CAAC;AAAA,IACrE;AACA,UAAM,QAAQ,SAAS,IAAI,aAAa,CAAC,UAAU,UAAU,SAAS,kBAAkB,CAAC;AACzF,QAAI,aAAa;AACf,YAAM,QAAQ,SAAS,IAAI,aAAa,CAAC,UAAU,WAAW,kBAAkB,CAAC;AAAA,IACnF;AACA,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,aAAa,UAAU;AACjC,UAAM,OAAO,KAAK,MAAM,WAAW,gBAAgB,4BAA4B;AAC/E,UAAM,sBAAsB,MAAM;AAAA,MAChC;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF;AACA,UAAM,YAAY,MAAM,kBAAkB,mBAAmB,CAAC;AAC9D,UAAM,SAAS,OAAO,QAAQ,OAAO,QAAQ,SAAS,KAAK,CAAC;AAC5D,UAAM,QAAQ,SAAS,IAAI,aAAa,CAAC,WAAW,QAAQ,IAAI,CAAC,EAAE,MAAM,MAAM,MAAS;AACxF,UAAM,QAAQ,SAAS,IAAI,aAAa,CAAC,aAAa,QAAQ,IAAI,CAAC;AACnE,UAAM,QAAQ,SAAS,IAAI,aAAa,CAAC,aAAa,GAAG,MAAM,uBAAuB,CAAC;AACvF,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,iDAAiD,QAAQ,QAAQ,EAAE;AACrF;AAEA,eAAsB,qBAAqB,SAKzB;AAChB,QAAM,OAAO,QAAQ,QAAQ,QAAQ;AACrC,MAAI,QAAQ,aAAa,SAAS;AAChC,UAAM,OAAO,KAAK,MAAM,WAAW,WAAW,QAAQ,kBAAkB;AACxE,UAAM,QAAQ,SAAS,IAAI,aAAa,CAAC,UAAU,WAAW,SAAS,kBAAkB,CAAC;AAC1F,UAAM,GAAG,MAAM,EAAE,OAAO,KAAK,CAAC;AAC9B,UAAM,QAAQ,SAAS,IAAI,aAAa,CAAC,UAAU,eAAe,CAAC;AACnE;AAAA,EACF;AACA,MAAI,QAAQ,aAAa,UAAU;AACjC,UAAM,OAAO,KAAK,MAAM,WAAW,gBAAgB,4BAA4B;AAC/E,UAAM,SAAS,OAAO,QAAQ,OAAO,QAAQ,SAAS,KAAK,CAAC;AAC5D,UAAM,QAAQ,SAAS,IAAI,aAAa,CAAC,WAAW,QAAQ,IAAI,CAAC,EAAE,MAAM,MAAM,MAAS;AACxF,UAAM,GAAG,MAAM,EAAE,OAAO,KAAK,CAAC;AAC9B;AAAA,EACF;AACA,QAAM,IAAI,MAAM,iDAAiD,QAAQ,QAAQ,EAAE;AACrF;AAEA,eAAsB,6BACpB,MACA,kBACA,YACkB;AAClB,QAAM,UAAU,MAAM,SAAS,MAAM,MAAM,EAAE,MAAM,CAAC,UAAiC;AACnF,QAAI,MAAM,SAAS,SAAU,QAAO;AACpC,UAAM;AAAA,EACR,CAAC;AACD,MAAI,YAAY,iBAAkB,QAAO;AACzC,MAAI;AACF,UAAM,OAAO,WAAW,UAAU,UAAU,IAAI;AAChD,UAAM,OAAO,WAAW,aAAa,UAAU,IAAI;AACnD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,2BACb,MACA,YACA,UACmC;AACnC,MAAI,WAAW,cAAc,OAAW,QAAO;AAC/C,QAAM,UAAU,MAAM,SAAS,MAAM,MAAM,EAAE,MAAM,CAAC,UAAiC;AACnF,QAAI,MAAM,SAAS,SAAU,QAAO;AACpC,UAAM;AAAA,EACR,CAAC;AACD,MAAI,YAAY,KAAM,QAAO;AAC7B,QAAM,UACJ,aAAa,UACT,yCAAyC,KAAK,OAAO,IAAI,CAAC,IAC1D,0DAA0D,KAAK,OAAO,IAAI,CAAC;AACjF,MAAI,YAAY,OAAW,QAAO;AAClC,QAAM,YACJ,aAAa,UACT,UACA,QACG,WAAW,UAAU,GAAG,EACxB,WAAW,UAAU,GAAG,EACxB,WAAW,QAAQ,GAAG,EACtB,WAAW,QAAQ,GAAG,EACtB,WAAW,SAAS,GAAG;AAChC,SAAO,EAAE,GAAG,YAAY,UAAU;AACpC;AAEA,eAAe,YAAY,MAAc,UAAiC;AACxE,QAAM,MAAM,QAAQ,IAAI,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC3D,QAAM,YAAY,GAAG,IAAI,QAAQ,QAAQ,GAAG;AAC5C,QAAM,UAAU,WAAW,UAAU,EAAE,MAAM,IAAM,CAAC;AACpD,QAAM,MAAM,WAAW,GAAK;AAC5B,QAAM,OAAO,WAAW,IAAI;AAC9B;;;AEpIA,SAAS,cAAAC,aAAY,kBAAkB;AACvC,SAAS,SAAAC,QAAO,IAAI,SAAAC,QAAO,SAAAC,QAAO,YAAAC,WAAU,UAAAC,SAAQ,MAAAC,KAAI,aAAAC,kBAAiB;AACzE,SAAS,QAAAC,OAAM,OAAO,WAAAC,UAAS,OAAAC,YAAW;;;ACF1C,SAAS,kBAAkB;AAC3B,SAAS,OAAO,YAAAC,WAAU,SAAS,UAAU,YAAY;AACzD,SAAS,QAAAC,OAAM,UAAU,SAAS,WAAW;AAS7C,eAAsB,kBACpB,MACA,cACwB;AACxB,QAAM,eAAe,QAAQ,IAAI;AACjC,QAAM,UAAU,MAAM,aAAa,cAAc,YAAY;AAC7D,QAAM,OAAO,WAAW,QAAQ;AAChC,MAAI,QAAQ;AACZ,aAAW,SAAS,SAAS;AAC3B,UAAM,WAAW,MAAMD,UAAS,MAAM,YAAY;AAClD,aAAS,SAAS;AAClB,SAAK,OAAO,MAAM,YAAY;AAC9B,SAAK,OAAO,IAAI;AAChB,SAAK,OAAO,OAAO,SAAS,MAAM,CAAC;AACnC,SAAK,OAAO,IAAI;AAChB,SAAK,OAAO,QAAQ;AACpB,SAAK,OAAO,IAAI;AAAA,EAClB;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO,QAAQ;AAAA,IACf;AAAA,IACA,QAAQ,KAAK,OAAO,KAAK;AAAA,EAC3B;AACF;AAEA,eAAe,aACb,MACA,WACkF;AAClF,QAAM,SAAgE,CAAC;AACvE,aAAW,SAAS,MAAM,QAAQ,SAAS,GAAG,KAAK,GAAG;AACpD,UAAM,eAAeC,MAAK,WAAW,IAAI;AACzC,UAAM,WAAW,MAAM,MAAM,YAAY;AACzC,UAAM,OAAO,SAAS,eAAe,IAAI,MAAM,KAAK,YAAY,IAAI;AACpE,QAAI,KAAK,YAAY,GAAG;AACtB,UAAI,SAAS,eAAe,GAAG;AAC7B,cAAM,IAAI,MAAM,yDAAyD,YAAY,EAAE;AAAA,MACzF;AACA,aAAO,KAAK,GAAI,MAAM,aAAa,MAAM,YAAY,CAAE;AACvD;AAAA,IACF;AACA,QAAI,CAAC,KAAK,OAAO,GAAG;AAClB,YAAM,IAAI,MAAM,0DAA0D,YAAY,EAAE;AAAA,IAC1F;AACA,QAAI,SAAS,eAAe,GAAG;AAC7B,YAAM,SAAS,MAAM,SAAS,YAAY;AAC1C,UAAI,WAAW,QAAQ,CAAC,OAAO,WAAW,GAAG,IAAI,GAAG,GAAG,EAAE,GAAG;AAC1D,cAAM,IAAI;AAAA,UACR,8DAA8D,YAAY;AAAA,QAC5E;AAAA,MACF;AAAA,IACF;AACA,UAAM,eAAe,SAAS,MAAM,YAAY,EAAE,MAAM,GAAG,EAAE,KAAK,GAAG;AACrE,QAAI,aAAa,WAAW,KAAK,aAAa,WAAW,KAAK,GAAG;AAC/D,YAAM,IAAI,MAAM,6CAA6C,YAAY,EAAE;AAAA,IAC7E;AACA,WAAO,KAAK,EAAE,cAAc,aAAa,CAAC;AAAA,EAC5C;AACA,SAAO,OAAO,KAAK,CAAC,MAAM,UAAU,KAAK,aAAa,cAAc,MAAM,YAAY,CAAC;AACzF;;;ADjCA,IAAM,2BAA2B,oBAAI,IAAI;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,qBAAqB;AAE3B,eAAsB,mBAAmB,SAMrB;AAClB,QAAM,aAAaC,SAAQ,QAAQ,UAAU;AAC7C,QAAM,gBAAgB,MAAMC,UAASC,MAAK,YAAY,QAAQ,uBAAuB,CAAC;AACtF,QAAM,iBAAiB,MAAM,qBAAqB,eAAe,UAAU;AAC3E,MAAI,eAAe,YAAY,QAAW;AACxC,UAAM,cAAc,UAAU;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,mBAAmB,YAAY,cAAc;AACnD,QAAM,2BAA2B,YAAY,eAAe,YAAY;AAExE,QAAM,iBAAiB,cAAc,YAAY,kBAAkB;AACnE,QAAM,mBAAmB,MAAM,kBAAkB,gBAAgB,kBAAkB;AACnF,QAAM,uBAAuBC,YAAW,QAAQ,EAAE,OAAO,aAAa,EAAE,OAAO,KAAK;AACpF,QAAM,uBAAwC;AAAA,IAC5C,GAAG;AAAA,IACH,SAAS,EAAE,sBAAsB,MAAM,iBAAiB;AAAA,EAC1D;AACA,QAAM,4BAA4B,kBAAkB,oBAAoB;AACxE,QAAM,cAAcA,YAAW,QAAQ,EACpC,OAAO,oBAAoB,EAC3B,OAAO,IAAI,EACX,OAAO,KAAK,UAAU,gBAAgB,CAAC,EACvC,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AAEd,QAAM,kBAAkBH,SAAQ,QAAQ,eAAe;AACvD,QAAM,uBAAuB,eAAe;AAC5C,QAAM,eAAeE,MAAK,iBAAiB,UAAU;AACrD,QAAM,uBAAuB,YAAY;AACzC,QAAM,cAAcA,MAAK,cAAc,GAAG,eAAe,QAAQ,OAAO,IAAI,WAAW,EAAE;AAEzF,MAAI,MAAM,WAAW,WAAW,GAAG;AACjC,UAAM,sBAAsB,aAAa,sBAAsB,yBAAyB;AACxF,WAAO;AAAA,EACT;AAEA,QAAM,UAAUA,MAAK,cAAc,YAAY,WAAW,CAAC,EAAE;AAC7D,QAAME,OAAM,SAAS,EAAE,MAAM,IAAM,CAAC;AACpC,MAAI;AACF,UAAM,GAAGF,MAAK,YAAY,MAAM,GAAGA,MAAK,SAAS,MAAM,GAAG;AAAA,MACxD,WAAW;AAAA,MACX,aAAa;AAAA,IACf,CAAC;AACD,UAAM,GAAGA,MAAK,YAAY,KAAK,GAAGA,MAAK,SAAS,KAAK,GAAG;AAAA,MACtD,WAAW;AAAA,MACX,aAAa;AAAA,IACf,CAAC;AACD,UAAM,GAAGA,MAAK,YAAY,cAAc,GAAGA,MAAK,SAAS,cAAc,CAAC;AACxE,UAAM,GAAG,gBAAgBA,MAAK,SAAS,kBAAkB,GAAG;AAAA,MAC1D,WAAW;AAAA,MACX,aAAa;AAAA,IACf,CAAC;AACD,UAAM,QAAQ,OAAO,sBAAsB;AAE3C,UAAM,aAAa,MAAM;AAAA,MACvBA,MAAK,SAAS,kBAAkB;AAAA,MAChC;AAAA,IACF;AACA,mBAAe,kBAAkB,YAAY,2BAA2B;AACxE,UAAM,kBAAkB,MAAM,kBAAkB,gBAAgB,kBAAkB;AAClF,mBAAe,kBAAkB,iBAAiB,2BAA2B;AAE7E,UAAMG,WAAUH,MAAK,SAAS,QAAQ,uBAAuB,GAAG,yBAAyB;AACzF,UAAM,sBAAsB,SAAS,sBAAsB,yBAAyB;AACpF,UAAMI,OAAM,SAAS,GAAK;AAC1B,QAAI;AACF,YAAMC,QAAO,SAAS,WAAW;AAAA,IACnC,SAAS,OAAgB;AACvB,UAAI,CAAC,kBAAkB,KAAK,KAAK,CAAE,MAAM,WAAW,WAAW,EAAI,OAAM;AACzE,YAAM,sBAAsB,aAAa,sBAAsB,yBAAyB;AAAA,IAC1F;AACA,WAAO;AAAA,EACT,UAAE;AACA,UAAMC,IAAG,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACpD;AACF;AAEA,eAAsB,cAAc,MAA6B;AAC/D,QAAM,eAAeR,SAAQ,IAAI;AACjC,QAAM,gBAAgB,MAAMC,UAASC,MAAK,cAAc,QAAQ,uBAAuB,CAAC;AACxF,QAAM,WAAW,MAAM,qBAAqB,eAAe,YAAY;AACvE,MAAI,SAAS,YAAY,QAAW;AAClC,UAAM,IAAI,MAAM,8DAA8D;AAAA,EAChF;AACA,QAAM,mBAAmB,cAAc,QAAQ;AAC/C,QAAM,2BAA2B,cAAc,SAAS,YAAY;AACpE,QAAM,aAAa,MAAM;AAAA,IACvB,cAAc,cAAc,kBAAkB;AAAA,IAC9C;AAAA,EACF;AACA,iBAAe,SAAS,QAAQ,MAAM,YAAY,iCAAiC;AACrF;AAEA,eAAe,sBACb,MACA,UACA,eACe;AACf,QAAM,eAAeA,MAAK,MAAM,QAAQ,uBAAuB;AAC/D,QAAM,cAAc,MAAMD,UAAS,YAAY;AAC/C,MAAI,CAAC,YAAY,OAAO,aAAa,GAAG;AACtC,UAAM,IAAI,MAAM,mEAAmE;AAAA,EACrF;AACA,QAAM,SAAS,MAAM,qBAAqB,aAAa,IAAI;AAC3D,MAAI,OAAO,YAAY,UAAa,SAAS,YAAY,QAAW;AAClE,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AACA,QAAM,mBAAmB,MAAM,MAAM;AACrC,QAAM,2BAA2B,MAAM,OAAO,YAAY;AAC1D,QAAM,aAAa,MAAM;AAAA,IACvB,cAAc,MAAM,kBAAkB;AAAA,IACtC;AAAA,EACF;AACA,iBAAe,SAAS,QAAQ,MAAM,YAAY,iCAAiC;AACrF;AAEA,eAAe,mBAAmB,MAAc,UAA0C;AACxF,aAAW,QAAQ,SAAS,OAAO;AACjC,UAAM,OAAO,cAAc,MAAM,KAAK,IAAI;AAC1C,UAAM,OAAO,MAAMQ,OAAM,IAAI;AAC7B,QAAI,KAAK,eAAe,GAAG;AACzB,YAAM,IAAI,MAAM,oBAAoB,KAAK,IAAI,8BAA8B;AAAA,IAC7E;AACA,QAAI,CAAC,KAAK,OAAO,KAAK,KAAK,SAAS,KAAK,OAAO;AAC9C,YAAM,IAAI,MAAM,oBAAoB,KAAK,IAAI,cAAc;AAAA,IAC7D;AACA,UAAM,OAAON,YAAW,QAAQ,EAC7B,OAAO,MAAMF,UAAS,IAAI,CAAC,EAC3B,OAAO,KAAK;AACf,QAAI,SAAS,KAAK,QAAQ;AACxB,YAAM,IAAI,MAAM,oBAAoB,KAAK,IAAI,sBAAsB;AAAA,IACrE;AAAA,EACF;AACF;AAEA,eAAe,2BACb,MACA,cACe;AACf,QAAM,cAAc,cAAc,MAAM,kBAAkB;AAC1D,QAAM,cAAc,MAAMQ,OAAM,WAAW;AAC3C,MAAI,CAAC,YAAY,YAAY,KAAK,YAAY,eAAe,GAAG;AAC9D,UAAM,IAAI,MAAM,wDAAwD;AAAA,EAC1E;AACA,aAAW,cAAc,cAAc;AACrC,UAAM,cAAc,cAAc,MAAM,WAAW,IAAI;AACvD,UAAM,cAAc,MAAMA,OAAM,WAAW;AAC3C,QAAI,CAAC,YAAY,YAAY,KAAK,YAAY,eAAe,GAAG;AAC9D,YAAM,IAAI,MAAM,sBAAsB,WAAW,IAAI,8BAA8B;AAAA,IACrF;AACA,UAAM,kBAAkBP,MAAK,aAAa,cAAc;AACxD,UAAM,kBAAkB,MAAMO,OAAM,eAAe;AACnD,QAAI,CAAC,gBAAgB,OAAO,KAAK,gBAAgB,eAAe,GAAG;AACjE,YAAM,IAAI,MAAM,sBAAsB,WAAW,IAAI,6BAA6B;AAAA,IACpF;AACA,UAAM,WAAW,MAAM,oBAAoB,WAAW;AACtD,QAAI,SAAS,SAAS,WAAW,QAAQ,SAAS,YAAY,WAAW,SAAS;AAChF,YAAM,IAAI,MAAM,sBAAsB,WAAW,IAAI,6BAA6B;AAAA,IACpF;AAAA,EACF;AACF;AAEA,eAAe,qBAAqB,OAAe,MAAwC;AACzF,MAAI;AACJ,MAAI;AACF,gBAAY,KAAK,MAAM,MAAM,SAAS,MAAM,CAAC;AAAA,EAC/C,QAAQ;AACN,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AACA,QAAM,wBAAwB,WAAW,IAAI;AAC7C,SAAO;AACT;AAEA,eAAe,wBAAwB,WAAoB,MAA6B;AACtF,MAAI,CAAC,SAAS,SAAS,KAAK,UAAU,kBAAkB,GAAG;AACzD,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AACA,MACE,CAAC,SAAS,UAAU,OAAO,KAC3B,OAAO,UAAU,QAAQ,SAAS,YAClC,OAAO,UAAU,QAAQ,YAAY,YACrC,OAAO,UAAU,cAAc,UAC/B;AACA,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,QAAM,kBAAkB,MAAM,oBAAoB,IAAI;AACtD,MACE,UAAU,QAAQ,SAAS,gBAAgB,QAC3C,UAAU,QAAQ,YAAY,gBAAgB,SAC9C;AACA,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACA,MAAI,CAAC,MAAM,QAAQ,UAAU,KAAK,KAAK,CAAC,MAAM,QAAQ,UAAU,YAAY,GAAG;AAC7E,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AAEA,QAAM,YAAY,oBAAI,IAAY;AAClC,aAAW,QAAQ,UAAU,OAAO;AAClC,QACE,CAAC,SAAS,IAAI,KACd,CAAC,eAAe,KAAK,IAAI,KACzB,CAAC,YAAY,KAAK,KAAK,KACvB,CAAC,SAAS,KAAK,MAAM,GACrB;AACA,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AACA,QAAI,UAAU,IAAI,KAAK,IAAI,GAAG;AAC5B,YAAM,IAAI,MAAM,uCAAuC,KAAK,IAAI,EAAE;AAAA,IACpE;AACA,cAAU,IAAI,KAAK,IAAI;AAAA,EACzB;AACA,aAAW,YAAY,0BAA0B;AAC/C,QAAI,CAAC,UAAU,IAAI,QAAQ,GAAG;AAC5B,YAAM,IAAI,MAAM,iDAAiD,QAAQ,EAAE;AAAA,IAC7E;AAAA,EACF;AAEA,QAAM,kBAAkB,oBAAI,IAAY;AACxC,QAAM,kBAAkB,oBAAI,IAAY;AACxC,aAAW,cAAc,UAAU,cAAc;AAC/C,QACE,CAAC,SAAS,UAAU,KACpB,CAAC,eAAe,WAAW,IAAI,KAC/B,OAAO,WAAW,SAAS,YAC3B,WAAW,KAAK,WAAW,KAC3B,OAAO,WAAW,YAAY,YAC9B,WAAW,QAAQ,WAAW,KAC9B,WAAW,SAAS,gBAAgB,WAAW,IAAI,IACnD;AACA,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AACA,QAAI,gBAAgB,IAAI,WAAW,IAAI,KAAK,gBAAgB,IAAI,WAAW,IAAI,GAAG;AAChF,YAAM,IAAI,MAAM,6CAA6C,WAAW,IAAI,EAAE;AAAA,IAChF;AACA,oBAAgB,IAAI,WAAW,IAAI;AACnC,oBAAgB,IAAI,WAAW,IAAI;AAAA,EACrC;AACA,QAAM,uBAAuB,gBAAgB;AAC7C,MACE,gBAAgB,SAAS,OAAO,KAAK,oBAAoB,EAAE,UAC3D,CAAC,GAAG,eAAe,EAAE;AAAA,IACnB,CAAC,SACC,qBAAqB,IAAI,MACxB,UAAU,aAAgD;AAAA,MACzD,CAAC,eAAe,WAAW,SAAS;AAAA,IACtC,GAAG;AAAA,EACP,GACA;AACA,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AAEA,aAAW,YAAY,WAAW;AAChC,eAAW,kBAAkB,iBAAiB;AAC5C,UACE,aAAa,kBACb,SAAS,WAAW,GAAG,cAAc,GAAG,KACxC,eAAe,WAAW,GAAG,QAAQ,GAAG,GACxC;AACA,cAAM,IAAI,MAAM,0CAA0C,QAAQ,QAAQ,cAAc,EAAE;AAAA,MAC5F;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU,YAAY,QAAW;AACnC,QACE,CAAC,SAAS,UAAU,OAAO,KAC3B,CAAC,SAAS,UAAU,QAAQ,oBAAoB,KAChD,CAAC,gBAAgB,UAAU,QAAQ,IAAI,KACvC,UAAU,QAAQ,KAAK,SAAS,oBAChC;AACA,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC7E;AAAA,EACF;AACF;AAEA,eAAe,oBAAoB,MAAwC;AACzE,MAAI;AACJ,MAAI;AACF,gBAAY,KAAK,MAAM,MAAMR,UAASC,MAAK,MAAM,cAAc,GAAG,MAAM,CAAC;AAAA,EAC3E,QAAQ;AACN,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,MACE,CAAC,SAAS,SAAS,KACnB,OAAO,UAAU,SAAS,YAC1B,OAAO,UAAU,YAAY,YAC5B,UAAU,iBAAiB,UAAa,CAAC,SAAS,UAAU,YAAY,KACxE,SAAS,UAAU,YAAY,KAC9B,OAAO,OAAO,UAAU,YAAY,EAAE,KAAK,CAAC,YAAY,OAAO,YAAY,QAAQ,GACrF;AACA,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AACA,SAAO;AAAA,IACL,MAAM,UAAU;AAAA,IAChB,SAAS,UAAU;AAAA,IACnB,cAAc,SAAS,UAAU,YAAY,IACxC,UAAU,eACX,CAAC;AAAA,EACP;AACF;AAEA,SAAS,kBAAkB,UAAmC;AAC5D,SAAO,OAAO,KAAK,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,CAAI;AAC7D;AAEA,SAAS,eAAe,UAAyB,QAAuB,OAAqB;AAC3F,MACE,SAAS,SAAS,OAAO,QACzB,SAAS,UAAU,OAAO,SAC1B,SAAS,UAAU,OAAO,SAC1B,SAAS,WAAW,OAAO,QAC3B;AACA,UAAM,IAAI,MAAM,WAAW,KAAK,iCAAiC;AAAA,EACnE;AACF;AAEA,SAAS,cAAc,MAAc,MAAsB;AACzD,MAAI,CAAC,eAAe,IAAI,EAAG,OAAM,IAAI,MAAM,4CAA4C,IAAI,EAAE;AAC7F,QAAM,WAAWF,SAAQ,MAAM,IAAI;AACnC,MAAI,CAAC,SAAS,WAAW,GAAG,IAAI,GAAGU,IAAG,EAAE,GAAG;AACzC,UAAM,IAAI,MAAM,4CAA4C,IAAI,EAAE;AAAA,EACpE;AACA,SAAO;AACT;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,eAAe,OAAiC;AACvD,SACE,OAAO,UAAU,YACjB,MAAM,SAAS,KACf,CAAC,MAAM,SAAS,IAAI,KACpB,CAAC,MAAM,WAAW,GAAG,KACrB,MAAM,UAAU,KAAK,MAAM,SAC3B,MAAM,MAAM,GAAG,EAAE,MAAM,CAAC,SAAS,KAAK,SAAS,KAAK,SAAS,OAAO,SAAS,IAAI;AAErF;AAEA,SAAS,YAAY,OAAiC;AACpD,SAAO,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK,KAAK,SAAS;AAC9E;AAEA,SAAS,SAAS,OAAiC;AACjD,SAAO,OAAO,UAAU,YAAY,iBAAiB,KAAK,KAAK;AACjE;AAEA,SAAS,gBAAgB,OAAwC;AAC/D,SACE,SAAS,KAAK,KACd,eAAe,MAAM,IAAI,KACzB,YAAY,MAAM,KAAK,KACvB,YAAY,MAAM,KAAK,KACvB,SAAS,MAAM,MAAM;AAEzB;AAEA,SAAS,kBAAkB,OAAyB;AAClD,QAAM,OAAQ,MAAgC;AAC9C,SAAO,SAAS,YAAY,SAAS;AACvC;AAEA,eAAe,uBAAuB,MAA6B;AACjE,QAAMN,OAAM,MAAM,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAClD,QAAM,OAAO,MAAMK,OAAM,IAAI;AAC7B,MAAI,CAAC,KAAK,YAAY,KAAK,KAAK,eAAe,GAAG;AAChD,UAAM,IAAI,MAAM,wCAAwC,IAAI,EAAE;AAAA,EAChE;AACA,MAAI,OAAO,QAAQ,WAAW,cAAc,KAAK,QAAQ,QAAQ,OAAO,GAAG;AACzE,UAAM,IAAI,MAAM,wBAAwB,IAAI,mCAAmC;AAAA,EACjF;AACA,QAAMH,OAAM,MAAM,GAAK;AACzB;AAEA,eAAe,WAAW,MAAgC;AACxD,MAAI;AACF,UAAMG,OAAM,IAAI;AAChB,WAAO;AAAA,EACT,SAAS,OAAgB;AACvB,QAAK,MAAgC,SAAS,SAAU,QAAO;AAC/D,UAAM;AAAA,EACR;AACF;;;AEtbA,SAAS,WAAAE,UAAS,cAAc;AAChC,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AASvB,SAAS,uBAAuB,MAAyB,QAAQ,KAAa;AACnF,SACE,IAAI,6BACH,QAAQ,aAAa,WAClBD,MAAKD,SAAQ,GAAG,WAAW,uBAAuB,YAAY,SAAS,IACvEC,MAAK,IAAI,iBAAiBA,MAAKD,SAAQ,GAAG,UAAU,OAAO,GAAG,UAAU;AAEhF;;;ALJA,IAAM,WAA4B;AAAA,EAChC,MAAM,IAAI,SAAS,MAAM;AACvB,UAAM,UAAU,QAAQ,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC;AAAA,EAC9C;AACF;AAEA,eAAsB,wBAAyC;AAC7D,SAAO,2BAA2B,QAAQ,IAAI,kBAAkB;AAClE;AAEA,eAAsB,uBAAwC;AAC5D,SAAO,2BAA2B,QAAQ,IAAI,kBAAkB;AAClE;AAEA,eAAe,2BAA2B,WAAgD;AACxF,QAAM,aAAaG,SAAQA,SAAQ,cAAc,YAAY,GAAG,CAAC,CAAC;AAClE,QAAM,UAAU,MAAM,mBAAmB;AAAA,IACvC;AAAA,IACA,iBAAiB,uBAAuB;AAAA,EAC1C,CAAC;AACD,SAAO,mBAAmB;AAAA,IACxB,UAAU,QAAQ;AAAA,IAClB,YAAY;AAAA,MACV,UAAU,QAAQ;AAAA,MAClB,aAAaC,MAAK,SAAS,OAAO,qBAAqB;AAAA,MACvD,GAAI,cAAc,SAAY,CAAC,IAAI,EAAE,UAAU;AAAA,IACjD;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,0BAAyC;AAC7D,QAAM,qBAAqB,EAAE,UAAU,QAAQ,UAAU,SAAS,CAAC;AACrE;AAEA,eAAe,OAAsB;AACnC,QAAM,UAAU,QAAQ,KAAK,CAAC;AAC9B,MAAI,YAAY,WAAW;AACzB,YAAQ,OAAO,MAAM,GAAG,MAAM,sBAAsB,CAAC;AAAA,CAAI;AACzD;AAAA,EACF;AACA,MAAI,YAAY,UAAU;AACxB,YAAQ,OAAO,MAAM,GAAG,MAAM,qBAAqB,CAAC;AAAA,CAAI;AACxD;AAAA,EACF;AACA,MAAI,YAAY,aAAa;AAC3B,UAAM,wBAAwB;AAC9B;AAAA,EACF;AACA,QAAM,IAAI,MAAM,2DAA2D;AAC7E;AAEA,IAAI,QAAQ,KAAK,CAAC,MAAM,UAAa,YAAY,QAAQ,cAAc,QAAQ,KAAK,CAAC,CAAC,EAAE,MAAM;AAC5F,QAAM,KAAK;AACb;",
|
|
6
6
|
"names": ["dirname", "join", "createHash", "chmod", "lstat", "mkdir", "readFile", "rename", "rm", "writeFile", "join", "resolve", "sep", "readFile", "join", "resolve", "readFile", "join", "createHash", "mkdir", "writeFile", "chmod", "rename", "rm", "lstat", "sep", "homedir", "join", "resolve", "dirname", "join"]
|
|
7
7
|
}
|
|
@@ -2,54 +2,54 @@
|
|
|
2
2
|
"schemaVersion": 3,
|
|
3
3
|
"package": {
|
|
4
4
|
"name": "@elpapi42/pi-fleet",
|
|
5
|
-
"version": "0.1.0-beta.
|
|
5
|
+
"version": "0.1.0-beta.9"
|
|
6
6
|
},
|
|
7
7
|
"managedPi": "@earendil-works/pi-coding-agent@0.80.10",
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "dist/cli-meta.json",
|
|
11
11
|
"bytes": 21248,
|
|
12
|
-
"sha256": "
|
|
12
|
+
"sha256": "93531953b84435cf51067990ec8456793c1469e0039299c3a31a667b94b060ae"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "dist/cli.mjs",
|
|
16
|
-
"bytes":
|
|
17
|
-
"sha256": "
|
|
16
|
+
"bytes": 150475,
|
|
17
|
+
"sha256": "351b3def34b9950356f7bd0f05931bb74c5c25b9fc35db6e9b581defdf5338fb"
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"path": "dist/cli.mjs.map",
|
|
21
|
-
"bytes":
|
|
22
|
-
"sha256": "
|
|
21
|
+
"bytes": 270234,
|
|
22
|
+
"sha256": "66694d9b5f2a93fb2ecef075719f40a9f029f8b6651f29d4f02a8ceafd601c27"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"path": "dist/installer-meta.json",
|
|
26
|
-
"bytes":
|
|
27
|
-
"sha256": "
|
|
26
|
+
"bytes": 6626,
|
|
27
|
+
"sha256": "3b34ec560c58847fa66f50d75582e5926715b265f589c91c675195a68107401f"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"path": "dist/installer.mjs",
|
|
31
|
-
"bytes":
|
|
32
|
-
"sha256": "
|
|
31
|
+
"bytes": 24492,
|
|
32
|
+
"sha256": "3515a9db0aebbc937f848794dd71b2b9d24460077dcfaec9e2bc8b793c92cbcf"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"path": "dist/installer.mjs.map",
|
|
36
|
-
"bytes":
|
|
37
|
-
"sha256": "
|
|
36
|
+
"bytes": 46371,
|
|
37
|
+
"sha256": "18a5c148c511758fffbec4f567165e105061b1a5eda10fd26b9b1561f8a1fecd"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"path": "dist/runtime-meta.json",
|
|
41
41
|
"bytes": 241246,
|
|
42
|
-
"sha256": "
|
|
42
|
+
"sha256": "cc8e685050b7a9a4e87c8d878870e33e20a78a676f706046aa3e30ab91ccd585"
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"path": "dist/runtime.mjs",
|
|
46
|
-
"bytes":
|
|
47
|
-
"sha256": "
|
|
46
|
+
"bytes": 322612,
|
|
47
|
+
"sha256": "78302ddd85c01471cf004cdbe419d5e2260aca67d6a0e3559fd77ee34ce33f28"
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"path": "dist/runtime.mjs.map",
|
|
51
|
-
"bytes":
|
|
52
|
-
"sha256": "
|
|
51
|
+
"bytes": 703823,
|
|
52
|
+
"sha256": "fa0ab3c167d94f7cbd236f86d5e49388cf980adc9bac995929f7460577654a13"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"path": "dist/sqlite-worker-meta.json",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"path": "package.json",
|
|
81
|
-
"bytes":
|
|
82
|
-
"sha256": "
|
|
81
|
+
"bytes": 2442,
|
|
82
|
+
"sha256": "06e7a5f6b9921533744a6e05fa975c5b6ac186d85871fe5a87b7db36271b8658"
|
|
83
83
|
}
|
|
84
84
|
],
|
|
85
85
|
"dependencies": [
|
package/dist/runtime-meta.json
CHANGED
|
@@ -6250,7 +6250,7 @@
|
|
|
6250
6250
|
"format": "esm"
|
|
6251
6251
|
},
|
|
6252
6252
|
"src/runtime/agent-coordinator.ts": {
|
|
6253
|
-
"bytes":
|
|
6253
|
+
"bytes": 8330,
|
|
6254
6254
|
"imports": [
|
|
6255
6255
|
{
|
|
6256
6256
|
"path": "src/platform/runtime/process-tree.ts",
|
|
@@ -6272,7 +6272,7 @@
|
|
|
6272
6272
|
"format": "esm"
|
|
6273
6273
|
},
|
|
6274
6274
|
"src/runtime/fleet-service.ts": {
|
|
6275
|
-
"bytes":
|
|
6275
|
+
"bytes": 36962,
|
|
6276
6276
|
"imports": [
|
|
6277
6277
|
{
|
|
6278
6278
|
"path": "node:crypto",
|
|
@@ -6385,7 +6385,7 @@
|
|
|
6385
6385
|
"imports": [],
|
|
6386
6386
|
"exports": [],
|
|
6387
6387
|
"inputs": {},
|
|
6388
|
-
"bytes":
|
|
6388
|
+
"bytes": 703823
|
|
6389
6389
|
},
|
|
6390
6390
|
"dist/runtime.mjs": {
|
|
6391
6391
|
"imports": [
|
|
@@ -6950,7 +6950,7 @@
|
|
|
6950
6950
|
"bytesInOutput": 108
|
|
6951
6951
|
},
|
|
6952
6952
|
"src/runtime/fleet-service.ts": {
|
|
6953
|
-
"bytesInOutput":
|
|
6953
|
+
"bytesInOutput": 31960
|
|
6954
6954
|
},
|
|
6955
6955
|
"src/pi/session-selector.ts": {
|
|
6956
6956
|
"bytesInOutput": 2113
|
|
@@ -6959,7 +6959,7 @@
|
|
|
6959
6959
|
"bytesInOutput": 2665
|
|
6960
6960
|
},
|
|
6961
6961
|
"src/runtime/agent-coordinator.ts": {
|
|
6962
|
-
"bytesInOutput":
|
|
6962
|
+
"bytesInOutput": 7280
|
|
6963
6963
|
},
|
|
6964
6964
|
"src/runtime/session-tail-subscription.ts": {
|
|
6965
6965
|
"bytesInOutput": 4844
|
|
@@ -6968,7 +6968,7 @@
|
|
|
6968
6968
|
"bytesInOutput": 3543
|
|
6969
6969
|
}
|
|
6970
6970
|
},
|
|
6971
|
-
"bytes":
|
|
6971
|
+
"bytes": 322612
|
|
6972
6972
|
}
|
|
6973
6973
|
}
|
|
6974
6974
|
}
|
package/dist/runtime.mjs
CHANGED
|
@@ -7124,7 +7124,7 @@ var AgentCoordinator = class {
|
|
|
7124
7124
|
}
|
|
7125
7125
|
const wasActive = this.agent.summary.state === "working" || this.agent.summary.state === "restoring";
|
|
7126
7126
|
const destroyed = this.#stopReason === "destroy";
|
|
7127
|
-
const interrupted = error !== null || wasActive && this.#stopReason !== "destroy";
|
|
7127
|
+
const interrupted = error !== null && this.#stopReason === null || wasActive && this.#stopReason !== "destroy";
|
|
7128
7128
|
const state = destroyed ? "destroying" : interrupted ? "failed" : "idle";
|
|
7129
7129
|
this.agent = {
|
|
7130
7130
|
...this.agent,
|
|
@@ -7829,6 +7829,8 @@ var FleetService = class {
|
|
|
7829
7829
|
async #dispatchSend(input, operationId, acceptedAt, initialAgent, ordinal) {
|
|
7830
7830
|
let agent = initialAgent;
|
|
7831
7831
|
let incarnationId = null;
|
|
7832
|
+
let startingProcess = null;
|
|
7833
|
+
let restoring = false;
|
|
7832
7834
|
try {
|
|
7833
7835
|
let coordinator = this.#coordinators.get(input.name);
|
|
7834
7836
|
if (this.#launcher !== void 0 && coordinator === void 0) {
|
|
@@ -7853,6 +7855,7 @@ var FleetService = class {
|
|
|
7853
7855
|
message: `Pi Fleet has reached its ${String(this.#limits.maxResidentProcesses)} process limit.`
|
|
7854
7856
|
});
|
|
7855
7857
|
} else {
|
|
7858
|
+
restoring = true;
|
|
7856
7859
|
agent = await this.#markRestoring(agent);
|
|
7857
7860
|
incarnationId = randomUUID2();
|
|
7858
7861
|
await this.store.putIncarnation({
|
|
@@ -7861,7 +7864,7 @@ var FleetService = class {
|
|
|
7861
7864
|
pid: null,
|
|
7862
7865
|
state: "starting"
|
|
7863
7866
|
});
|
|
7864
|
-
|
|
7867
|
+
startingProcess = await this.#launcher.start(agent.launch, true, async (pid) => {
|
|
7865
7868
|
await this.store.putIncarnation({
|
|
7866
7869
|
incarnationId,
|
|
7867
7870
|
agentName: input.name,
|
|
@@ -7869,6 +7872,7 @@ var FleetService = class {
|
|
|
7869
7872
|
state: "starting"
|
|
7870
7873
|
});
|
|
7871
7874
|
});
|
|
7875
|
+
const process2 = startingProcess;
|
|
7872
7876
|
await this.store.putIncarnation({
|
|
7873
7877
|
incarnationId,
|
|
7874
7878
|
agentName: input.name,
|
|
@@ -7893,6 +7897,7 @@ var FleetService = class {
|
|
|
7893
7897
|
};
|
|
7894
7898
|
await this.store.putAgent(agent);
|
|
7895
7899
|
coordinator = this.#attachCoordinator(agent, process2, incarnationId);
|
|
7900
|
+
restoring = false;
|
|
7896
7901
|
}
|
|
7897
7902
|
}
|
|
7898
7903
|
await this.store.putSend({
|
|
@@ -7926,7 +7931,49 @@ var FleetService = class {
|
|
|
7926
7931
|
agent: { id: agent.summary.id, name: agent.summary.name },
|
|
7927
7932
|
acceptedAt
|
|
7928
7933
|
});
|
|
7929
|
-
} catch {
|
|
7934
|
+
} catch (error) {
|
|
7935
|
+
if (restoring && incarnationId !== null) {
|
|
7936
|
+
let cleanupUncertain = error instanceof PiCleanupUncertainError;
|
|
7937
|
+
let cleanupPid = error instanceof PiCleanupUncertainError ? error.pid : null;
|
|
7938
|
+
if (startingProcess !== null) {
|
|
7939
|
+
cleanupPid = startingProcess.pid;
|
|
7940
|
+
try {
|
|
7941
|
+
await startingProcess.stop();
|
|
7942
|
+
} catch {
|
|
7943
|
+
cleanupUncertain = true;
|
|
7944
|
+
}
|
|
7945
|
+
}
|
|
7946
|
+
const code = cleanupUncertain ? "incarnation_cleanup_uncertain" : "pi_start_failed";
|
|
7947
|
+
agent = {
|
|
7948
|
+
...agent,
|
|
7949
|
+
summary: {
|
|
7950
|
+
...agent.summary,
|
|
7951
|
+
state: "failed",
|
|
7952
|
+
process: { state: cleanupUncertain ? "cleanup_uncertain" : "absent" },
|
|
7953
|
+
error: { code }
|
|
7954
|
+
}
|
|
7955
|
+
};
|
|
7956
|
+
await this.store.putAgent(agent);
|
|
7957
|
+
await this.store.putIncarnation({
|
|
7958
|
+
incarnationId,
|
|
7959
|
+
agentName: input.name,
|
|
7960
|
+
pid: cleanupPid,
|
|
7961
|
+
state: cleanupUncertain ? "cleanup_uncertain" : "gone"
|
|
7962
|
+
});
|
|
7963
|
+
await this.store.putSend({
|
|
7964
|
+
sendId: operationId,
|
|
7965
|
+
agentName: input.name,
|
|
7966
|
+
ordinal,
|
|
7967
|
+
message: input.message,
|
|
7968
|
+
state: "failed",
|
|
7969
|
+
acceptedAt
|
|
7970
|
+
});
|
|
7971
|
+
if (!cleanupUncertain) this.#releaseProcessSlot(input.name);
|
|
7972
|
+
return err({
|
|
7973
|
+
code,
|
|
7974
|
+
message: cleanupUncertain ? `Fleet could not prove the failed Pi restoration for ${input.name} was removed.` : `Pi failed to restore for ${input.name}; the message was not dispatched.`
|
|
7975
|
+
});
|
|
7976
|
+
}
|
|
7930
7977
|
if (!this.#coordinators.has(input.name)) this.#releaseProcessSlot(input.name);
|
|
7931
7978
|
if (incarnationId !== null && !this.#coordinators.has(input.name)) {
|
|
7932
7979
|
await this.store.putIncarnation({
|