@scopebond/agent 0.5.6 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/agent.d.ts +6 -0
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +10 -3
  4. package/dist/agent.js.map +1 -1
  5. package/dist/apps-entry.d.ts +46 -0
  6. package/dist/apps-entry.d.ts.map +1 -0
  7. package/dist/apps-entry.js +118 -0
  8. package/dist/apps-entry.js.map +1 -0
  9. package/dist/autostart.d.ts +11 -5
  10. package/dist/autostart.d.ts.map +1 -1
  11. package/dist/autostart.js +59 -5
  12. package/dist/autostart.js.map +1 -1
  13. package/dist/awake.d.ts +31 -0
  14. package/dist/awake.d.ts.map +1 -0
  15. package/dist/awake.js +57 -0
  16. package/dist/awake.js.map +1 -0
  17. package/dist/cli-main.d.ts.map +1 -1
  18. package/dist/cli-main.js +28 -1
  19. package/dist/cli-main.js.map +1 -1
  20. package/dist/index.d.ts +12 -7
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +8 -5
  23. package/dist/index.js.map +1 -1
  24. package/dist/ipc.d.ts +6 -2
  25. package/dist/ipc.d.ts.map +1 -1
  26. package/dist/ipc.js +11 -7
  27. package/dist/ipc.js.map +1 -1
  28. package/dist/native-update.d.ts +83 -7
  29. package/dist/native-update.d.ts.map +1 -1
  30. package/dist/native-update.js +230 -33
  31. package/dist/native-update.js.map +1 -1
  32. package/dist/selfcheck.d.ts.map +1 -1
  33. package/dist/selfcheck.js +4 -1
  34. package/dist/selfcheck.js.map +1 -1
  35. package/dist/service.d.ts +20 -3
  36. package/dist/service.d.ts.map +1 -1
  37. package/dist/service.js +141 -44
  38. package/dist/service.js.map +1 -1
  39. package/dist/setup.d.ts +12 -0
  40. package/dist/setup.d.ts.map +1 -1
  41. package/dist/setup.js +41 -12
  42. package/dist/setup.js.map +1 -1
  43. package/dist/tray-model.d.ts +2 -0
  44. package/dist/tray-model.d.ts.map +1 -1
  45. package/dist/tray-model.js +2 -0
  46. package/dist/tray-model.js.map +1 -1
  47. package/dist/update.d.ts +56 -12
  48. package/dist/update.d.ts.map +1 -1
  49. package/dist/update.js +209 -38
  50. package/dist/update.js.map +1 -1
  51. package/dist/upkeep.d.ts +16 -0
  52. package/dist/upkeep.d.ts.map +1 -0
  53. package/dist/upkeep.js +55 -0
  54. package/dist/upkeep.js.map +1 -0
  55. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"update.js","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"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","sourcesContent":["// Updates under the workspace's control (D130). The agent asks the workspace which versions this\n// computer should run; with \"recommended\" it installs the named agent from npm (which brings the\n// matching hook, pinned exactly) and restarts; with \"hold\" it changes nothing. The hook entries in\n// the agent settings are moved to the hook version the agent carries.\n\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n absoluteHookCommand, configuredHookCommands, ensureDurableRuntime, hookCliPath, hookCommandResolves, hookVersion, isScopebondHookCommand, isSingleExecutable,\n nativeHookCommand, userHarnessFile, writeHarnessConfig, type Harness, type HookConnection,\n} from \"@scopebond/hook\";\n\nconst VERSION = /^[0-9]+\\.[0-9]+\\.[0-9]+$/;\n\n/** Set by the single executable's build (esbuild `define`); absent from the npm package. */\ndeclare const __SCOPEBOND_AGENT_VERSION__: string | undefined;\n\nexport function agentVersion(): string {\n if (typeof __SCOPEBOND_AGENT_VERSION__ === \"string\") return __SCOPEBOND_AGENT_VERSION__;\n try {\n const pkg = JSON.parse(readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\")) as { version?: string };\n return typeof pkg.version === \"string\" ? pkg.version : \"0.0.0\";\n } catch { return \"0.0.0\"; }\n}\n\nexport interface ClientVersion { policy: \"recommended\" | \"hold\"; hook: string | null; agent: string | null }\n\nexport async function fetchClientVersion(connection: Pick<HookConnection, \"url\" | \"credential\">, fetchImpl: typeof fetch = fetch, timeoutMs = 10_000): Promise<ClientVersion | null> {\n try {\n const res = await fetchImpl(new URL(\"/v1/client-version\", connection.url).toString(), {\n headers: { authorization: `Bearer ${connection.credential}` }, redirect: \"error\", signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) return null;\n const body = await res.json() as Partial<ClientVersion>;\n const ok = (v: unknown) => typeof v === \"string\" && VERSION.test(v) ? v : null;\n return { policy: body.policy === \"hold\" ? \"hold\" : \"recommended\", hook: ok(body.hook), agent: ok(body.agent) };\n } catch { return null; }\n}\n\n/** Compare x.y.z versions: negative when a < b. */\nexport function compareVersions(a: string, b: string): number {\n const pa = a.split(\".\").map(Number), pb = b.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) if ((pa[i] ?? 0) !== (pb[i] ?? 0)) return (pa[i] ?? 0) - (pb[i] ?? 0);\n return 0;\n}\n\n/** The hook version a settings command runs, when it names one (an `npx` pin or a pinned copy). */\nexport function commandHookVersion(command: string): string | null {\n return /@scopebond\\/hook@([0-9]+\\.[0-9]+\\.[0-9]+)/.exec(command)?.[1]\n ?? /[\\\\/]runtime[\\\\/]([0-9]+\\.[0-9]+\\.[0-9]+)[\\\\/]/.exec(command)?.[1]\n ?? null;\n}\n\n/** The command an agent-maintained settings entry runs: the hook version this agent carries,\n * through npx, so it resolves Node at run time and an agent update never swaps files under it. */\n/** The hook command upkeep writes. The hook this agent carries is pinned by its absolute path (fast,\n * and it needs neither the registry nor npx on the coding tool's PATH); another version, or a pin that\n * cannot be made, falls back to the portable npx form. */\nexport function maintainedHookCommand(harness: Harness, version = hookVersion()): string {\n // The single executable carries its own hook, at the path the installer keeps.\n if (isSingleExecutable()) return nativeHookCommand(harness);\n if (version === hookVersion()) {\n try {\n const pin = ensureDurableRuntime(hookCliPath(), version);\n if (pin.cli) return absoluteHookCommand(pin.cli, harness);\n } catch { /* fall back below */ }\n }\n return `npx -y @scopebond/hook@${version} ${harness}`;\n}\n\n/** This Node's own npm, run directly (no shell, and never another Node's npm first on PATH), or null. */\nexport function ownNpm(): [string, string[]] | null {\n const cli = join(dirname(process.execPath), process.platform === \"win32\" ? \"\" : \"../lib\", \"node_modules\", \"npm\", \"bin\", \"npm-cli.js\");\n return existsSync(cli) ? [process.execPath, [cli]] : null;\n}\n\n/** Bring the user-level Scopebond hook entries to `version`, and repair any that cannot start.\n * Entries of other tools are never touched. Returns the files changed. */\nexport function maintainHookEntries(harnesses: Harness[], version = hookVersion(), moveVersions = true): Array<{ harness: Harness; file: string; reason: string }> {\n const changed: Array<{ harness: Harness; file: string; reason: string }> = [];\n for (const harness of harnesses) {\n const file = userHarnessFile(harness);\n const ours = configuredHookCommands(file).filter((c) => isScopebondHookCommand(c));\n if (!ours.length) continue;\n const broken = ours.some((c) => !hookCommandResolves(c));\n const behind = moveVersions && ours.some((c) => { const v = commandHookVersion(c); return v !== null && compareVersions(v, version) < 0; });\n if (!broken && !behind) continue;\n writeHarnessConfig(file, harness, maintainedHookCommand(harness, version));\n changed.push({ harness, file, reason: broken ? \"the hook command could not start\" : `moved to hook ${version}` });\n }\n return changed;\n}\n\n/** Install `@scopebond/agent@version` globally with this computer's npm. */\nexport function installAgent(version: string, timeoutMs = 5 * 60_000): Promise<{ ok: boolean; output: string }> {\n if (!VERSION.test(version)) return Promise.resolve({ ok: false, output: \"not a version\" });\n return new Promise((resolve) => {\n const win = process.platform === \"win32\";\n const args = [\"install\", \"-g\", `@scopebond/agent@${version}`, \"--no-fund\", \"--no-audit\"];\n // This Node's own npm when it can be found; otherwise npm on PATH (a .cmd on Windows, which Node only\n // starts through a shell; the arguments are fixed and the version is validated).\n const own = ownNpm();\n const child = own ? spawn(own[0], [...own[1], ...args], { windowsHide: true }) : spawn(win ? \"npm.cmd\" : \"npm\", args, { shell: win, windowsHide: true });\n let output = \"\";\n child.stdout?.on(\"data\", (d) => { output += d; });\n child.stderr?.on(\"data\", (d) => { output += d; });\n const timer = setTimeout(() => { child.kill(); resolve({ ok: false, output: output + \"\\ntimed out\" }); }, timeoutMs);\n child.on(\"error\", (error) => { clearTimeout(timer); resolve({ ok: false, output: String(error) }); });\n child.on(\"close\", (code) => { clearTimeout(timer); resolve({ ok: code === 0, output: output.slice(-2000) }); });\n });\n}\n"]}
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"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","sourcesContent":["// Updates under the workspace's control. The agent asks the workspace which versions this computer should run; with\n// \"recommended\" it installs the named agent from npm (which brings the matching hook, pinned exactly) and restarts; with\n// \"hold\" it changes nothing. The hook entries in the agent settings are pinned to the hook version the agent carries.\n//\n// The npm path is hardened: the workspace's answer is bounded (size, strict x.y.z, no more than one major version ahead),\n// the exact version must carry npm provenance from this repository's main branch, npm runs with package scripts off and\n// the public registry pinned, the new program must start and report the version before the old one hands over, and a\n// version that did not start is rolled back and not retried for a day.\n\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n absoluteHookCommand, configuredHookCommands, ensureDurableRuntime, hookCliPath, hookCommandResolves, hookVersion, isScopebondHookCommand, isSingleExecutable,\n nativeHookCommand, userHarnessFile, writeHarnessConfig, type Harness, type HookConnection,\n} from \"@scopebond/hook\";\nimport { agentCliPath } from \"./self.js\";\n\n/** x.y.z with no leading zeros, no tags, and each part of a sane size. */\nconst VERSION = /^(0|[1-9][0-9]{0,3})\\.(0|[1-9][0-9]{0,3})\\.(0|[1-9][0-9]{0,5})$/;\n/** The largest answer to /v1/client-version the agent reads. */\nexport const CLIENT_VERSION_MAX_BYTES = 4096;\n/** The only registry the agent installs from. */\nexport const NPM_REGISTRY = \"https://registry.npmjs.org/\";\n/** The repository and branch an installed agent's npm provenance must name. */\nexport const PROVENANCE_REPOSITORY = \"https://github.com/avouro-com/scopebond\";\nexport const PROVENANCE_REF = \"refs/heads/main\";\n\n/** Set by the single executable's build (esbuild `define`); absent from the npm package. */\ndeclare const __SCOPEBOND_AGENT_VERSION__: string | undefined;\n\nexport function agentVersion(): string {\n if (typeof __SCOPEBOND_AGENT_VERSION__ === \"string\") return __SCOPEBOND_AGENT_VERSION__;\n try {\n const pkg = JSON.parse(readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\")) as { version?: string };\n return typeof pkg.version === \"string\" ? pkg.version : \"0.0.0\";\n } catch { return \"0.0.0\"; }\n}\n\nexport const isVersion = (v: unknown): v is string => typeof v === \"string\" && VERSION.test(v);\n\nexport interface ClientVersion { policy: \"recommended\" | \"hold\"; hook: string | null; agent: string | null }\n\n/** A response body as text, or null when it is larger than `max` bytes. */\nasync function boundedText(res: Response, max: number): Promise<string | null> {\n const declared = Number(res.headers.get(\"content-length\"));\n if (Number.isFinite(declared) && declared > max) return null;\n if (!res.body) return \"\";\n const reader = res.body.getReader();\n const chunks: Uint8Array[] = [];\n let size = 0;\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > max) { void reader.cancel().catch(() => {}); return null; }\n chunks.push(value);\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\n/** Whether `named` is a version this computer may be moved to from `running`: well formed and at most one major ahead. */\nfunction inRange(named: string, running: string): boolean {\n const major = Number(named.split(\".\")[0]);\n const current = Number((isVersion(running) ? running : \"0.0.0\").split(\".\")[0]);\n return major <= current + 1;\n}\n\n/** The versions the workspace names for this computer, or null when there is no usable answer. Anything unexpected — an\n * answer over the size limit, not an object, a policy other than \"recommended\" or \"hold\", a version that is not a strict\n * x.y.z or is more than one major version ahead — refuses the whole answer, so nothing changes. */\nexport async function fetchClientVersion(\n connection: Pick<HookConnection, \"url\" | \"credential\">, fetchImpl: typeof fetch = fetch, timeoutMs = 10_000,\n running: { agent: string; hook: string } = { agent: agentVersion(), hook: hookVersion() },\n): Promise<ClientVersion | null> {\n try {\n const res = await fetchImpl(new URL(\"/v1/client-version\", connection.url).toString(), {\n headers: { authorization: `Bearer ${connection.credential}` }, redirect: \"error\", signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) return null;\n const text = await boundedText(res, CLIENT_VERSION_MAX_BYTES);\n if (text === null) return null;\n const body = JSON.parse(text) as unknown;\n if (!body || typeof body !== \"object\" || Array.isArray(body)) return null;\n const { policy, hook, agent } = body as Record<string, unknown>;\n if (policy !== \"recommended\" && policy !== \"hold\") return null;\n const version = (v: unknown, current: string): string | null | undefined => {\n if (v === null || v === undefined) return null;\n return isVersion(v) && inRange(v, current) ? v : undefined;\n };\n const h = version(hook, running.hook), a = version(agent, running.agent);\n if (h === undefined || a === undefined) return null;\n return { policy, hook: h, agent: a };\n } catch { return null; }\n}\n\n/** Compare x.y.z versions: negative when a < b. */\nexport function compareVersions(a: string, b: string): number {\n const pa = a.split(\".\").map(Number), pb = b.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) if ((pa[i] ?? 0) !== (pb[i] ?? 0)) return (pa[i] ?? 0) - (pb[i] ?? 0);\n return 0;\n}\n\n/** The hook version a settings command runs, when it names one (an `npx` pin or a pinned copy). */\nexport function commandHookVersion(command: string): string | null {\n return /@scopebond\\/hook@([0-9]+\\.[0-9]+\\.[0-9]+)/.exec(command)?.[1]\n ?? /[\\\\/]runtime[\\\\/]([0-9]+\\.[0-9]+\\.[0-9]+)[\\\\/]/.exec(command)?.[1]\n ?? null;\n}\n\nconst isNpxCommand = (command: string) => /(^|\\s)npx(\\.cmd)?\\s/.test(command);\n\n/** The hook command upkeep writes: always the hook this agent carries, by its absolute path (a durable pinned copy when the\n * carried one lives somewhere npm may clear). Never an `npx` form, which would resolve a package from the registry each\n * time the coding tool runs it. */\nexport function maintainedHookCommand(harness: Harness): string {\n // The single executable carries its own hook, at the path the installer keeps.\n if (isSingleExecutable()) return nativeHookCommand(harness);\n const cli = hookCliPath();\n try {\n const pin = ensureDurableRuntime(cli, hookVersion());\n if (pin.cli) return absoluteHookCommand(pin.cli, harness);\n } catch { /* the carried hook's own path below */ }\n return absoluteHookCommand(cli, harness);\n}\n\n/** This Node's own npm, run directly (no shell, and never another Node's npm first on PATH), or null. */\nexport function ownNpm(): [string, string[]] | null {\n const cli = join(dirname(process.execPath), process.platform === \"win32\" ? \"\" : \"../lib\", \"node_modules\", \"npm\", \"bin\", \"npm-cli.js\");\n return existsSync(cli) ? [process.execPath, [cli]] : null;\n}\n\n/** Bring the user-level Scopebond hook entries to the hook this agent carries, and repair any that cannot start. Under\n * \"recommended\" (`moveVersions`) an entry naming an older hook, or any `npx` entry, is pinned to the carried hook; under\n * \"hold\" only broken entries and `npx` entries that name no version or the carried one are (their version does not\n * change). Entries of other tools are never touched. Returns the files changed. */\nexport function maintainHookEntries(harnesses: Harness[], moveVersions = true): Array<{ harness: Harness; file: string; reason: string }> {\n const carried = hookVersion();\n const changed: Array<{ harness: Harness; file: string; reason: string }> = [];\n for (const harness of harnesses) {\n const file = userHarnessFile(harness);\n const ours = configuredHookCommands(file).filter((c) => isScopebondHookCommand(c));\n if (!ours.length) continue;\n const broken = ours.some((c) => !isNpxCommand(c) && !hookCommandResolves(c));\n const npx = ours.some((c) => { if (!isNpxCommand(c)) return false; const v = commandHookVersion(c); return moveVersions || v === null || v === carried; });\n const behind = moveVersions && ours.some((c) => { const v = commandHookVersion(c); return v !== null && compareVersions(v, carried) < 0; });\n if (!broken && !npx && !behind) continue;\n writeHarnessConfig(file, harness, maintainedHookCommand(harness));\n changed.push({ harness, file, reason: broken ? \"the hook command could not start\" : npx ? `pinned to the hook this agent carries (${carried})` : `moved to hook ${carried}` });\n }\n return changed;\n}\n\n/** npm's arguments for a global install of `spec`: package scripts off, the public registry pinned (also for the\n * @scopebond scope, which a scope registry setting would otherwise take over). */\nexport function npmInstallArgs(spec: string): string[] {\n return [\"install\", \"-g\", spec, \"--ignore-scripts\", `--registry=${NPM_REGISTRY}`, `--@scopebond:registry=${NPM_REGISTRY}`, \"--no-fund\", \"--no-audit\"];\n}\n\n/** The environment npm runs with: this process's, without settings that would change the registry or turn scripts back on. */\nexport function npmEnvironment(env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n const out: NodeJS.ProcessEnv = {};\n for (const [key, value] of Object.entries(env)) {\n const k = key.toLowerCase();\n if (k.startsWith(\"npm_config_\") && (k.endsWith(\"registry\") || k.includes(\"ignore_scripts\") || k.includes(\"ignore-scripts\") || k.includes(\"script_shell\") || k.includes(\"script-shell\"))) continue;\n out[key] = value;\n }\n return out;\n}\n\nexport type ProvenanceResult = { ok: true } | { ok: false; reason: string };\n\n/** Check, before installing, that npm's provenance for exactly `@scopebond/agent@version` says it was built by this\n * repository's main branch, for the tarball the registry serves. The statement is the one the registry verified when the\n * package was published; it is read here, not re-verified against Sigstore. */\nexport async function checkProvenance(version: string, fetchImpl: typeof fetch = fetch, timeoutMs = 30_000): Promise<ProvenanceResult> {\n const get = async (url: string, max: number): Promise<unknown> => {\n const res = await fetchImpl(url, { redirect: \"error\", signal: AbortSignal.timeout(timeoutMs), headers: { accept: \"application/json\" } });\n if (!res.ok) throw new Error(`${res.status}`);\n const text = await boundedText(res, max);\n if (text === null) throw new Error(\"too large\");\n return JSON.parse(text);\n };\n try {\n const meta = await get(`${NPM_REGISTRY}@scopebond%2fagent/${version}`, 512 * 1024) as { version?: string; dist?: { integrity?: string; attestations?: { url?: string; provenance?: { predicateType?: string } } } };\n if (meta?.version !== version) return { ok: false, reason: \"the registry did not describe this version\" };\n const integrity = meta.dist?.integrity ?? \"\";\n const att = meta.dist?.attestations;\n if (!att?.url || !att.provenance?.predicateType?.startsWith(\"https://slsa.dev/provenance/\")) return { ok: false, reason: \"this version has no npm provenance\" };\n if (!integrity.startsWith(\"sha512-\")) return { ok: false, reason: \"this version has no sha512 integrity\" };\n const want = Buffer.from(integrity.slice(\"sha512-\".length), \"base64\").toString(\"hex\");\n if (!att.url.startsWith(`${NPM_REGISTRY}-/npm/v1/attestations/`)) return { ok: false, reason: \"the provenance is not on the registry\" };\n const bundle = await get(att.url, 1024 * 1024) as { attestations?: Array<{ predicateType?: string; bundle?: { dsseEnvelope?: { payload?: string } } }> };\n const slsa = bundle?.attestations?.find((a) => a.predicateType?.startsWith(\"https://slsa.dev/provenance/\"));\n if (!slsa?.bundle?.dsseEnvelope?.payload) return { ok: false, reason: \"this version has no npm provenance\" };\n const statement = JSON.parse(Buffer.from(slsa.bundle.dsseEnvelope.payload, \"base64\").toString(\"utf8\")) as {\n subject?: Array<{ name?: string; digest?: { sha512?: string } }>;\n predicate?: { buildDefinition?: { externalParameters?: { workflow?: { repository?: string; ref?: string } } } };\n };\n const subject = statement.subject?.find((s) => s.name === `pkg:npm/%40scopebond/agent@${version}`);\n if (!subject || subject.digest?.sha512 !== want) return { ok: false, reason: \"the provenance is for another tarball\" };\n const workflow = statement.predicate?.buildDefinition?.externalParameters?.workflow;\n if (workflow?.repository !== PROVENANCE_REPOSITORY) return { ok: false, reason: `the provenance names ${workflow?.repository ?? \"no repository\"}, not ${PROVENANCE_REPOSITORY}` };\n if (workflow.ref !== PROVENANCE_REF) return { ok: false, reason: `the provenance names ${workflow.ref ?? \"no branch\"}, not ${PROVENANCE_REF}` };\n return { ok: true };\n } catch (error) { return { ok: false, reason: `the registry could not be asked (${(error as Error).message.slice(0, 80)})` }; }\n}\n\n/** Install `@scopebond/agent@version` globally with this computer's npm: provenance checked first (unless `provenance` is\n * false, for going back to the version already running), package scripts off, the public registry pinned. */\nexport async function installAgent(version: string, o: { timeoutMs?: number; fetchImpl?: typeof fetch; provenance?: boolean } = {}): Promise<{ ok: boolean; output: string }> {\n if (!isVersion(version)) return { ok: false, output: \"not a version\" };\n if (o.provenance !== false) {\n const checked = await checkProvenance(version, o.fetchImpl);\n if (!checked.ok) return { ok: false, output: `npm provenance check failed: ${checked.reason}; nothing was installed` };\n }\n const timeoutMs = o.timeoutMs ?? 5 * 60_000;\n return new Promise((resolve) => {\n const win = process.platform === \"win32\";\n const args = npmInstallArgs(`@scopebond/agent@${version}`);\n const env = npmEnvironment();\n // This Node's own npm when it can be found; otherwise npm on PATH (a .cmd on Windows, which Node only\n // starts through a shell; the arguments are fixed and the version is validated).\n const own = ownNpm();\n const child = own ? spawn(own[0], [...own[1], ...args], { windowsHide: true, env }) : spawn(win ? \"npm.cmd\" : \"npm\", args, { shell: win, windowsHide: true, env });\n let output = \"\";\n child.stdout?.on(\"data\", (d) => { output += d; });\n child.stderr?.on(\"data\", (d) => { output += d; });\n const timer = setTimeout(() => { child.kill(); resolve({ ok: false, output: output + \"\\ntimed out\" }); }, timeoutMs);\n child.on(\"error\", (error) => { clearTimeout(timer); resolve({ ok: false, output: String(error) }); });\n child.on(\"close\", (code) => { clearTimeout(timer); resolve({ ok: code === 0, output: output.slice(-2000) }); });\n });\n}\n\n/** Run the agent program now on disk (`version`) and confirm it starts and reports `version`. */\nexport function startCheck(version: string, cli = agentCliPath(), timeoutMs = 60_000): Promise<{ ok: boolean; output: string }> {\n return new Promise((resolve) => {\n const child = spawn(process.execPath, [\"--disable-warning=ExperimentalWarning\", cli, \"version\"], {\n windowsHide: true, stdio: [\"ignore\", \"pipe\", \"pipe\"], env: { ...process.env, SCOPEBOND_AGENT_TRAY: \"off\" },\n });\n let output = \"\";\n child.stdout?.on(\"data\", (d) => { if (output.length < 4096) output += d; });\n child.stderr?.on(\"data\", (d) => { if (output.length < 4096) output += d; });\n const timer = setTimeout(() => { child.kill(); resolve({ ok: false, output: `${output}\\ntimed out` }); }, timeoutMs);\n child.on(\"error\", (error) => { clearTimeout(timer); resolve({ ok: false, output: String(error) }); });\n child.on(\"close\", (code) => {\n clearTimeout(timer);\n const first = output.trim().split(/\\r?\\n/)[0] ?? \"\";\n resolve({ ok: code === 0 && first.split(/\\s+/)[0] === `agent/${version}`, output: output.trim().slice(-500) });\n });\n });\n}\n\n/** A version that was installed but did not start, kept so it is not installed again for a while. */\nexport const FAILED_UPDATE_FILE = \"update-failed.json\";\nexport const FAILED_UPDATE_RETRY_MS = 24 * 60 * 60 * 1000;\n\nexport function recordFailedUpdate(dir: string, version: string, now = Date.now()): void {\n try { writeFileSync(join(dir, FAILED_UPDATE_FILE), `${JSON.stringify({ version, at: now })}\\n`, { mode: 0o600 }); } catch { /* best effort */ }\n}\n\nexport function recentlyFailedUpdate(dir: string, version: string, now = Date.now()): boolean {\n try {\n const r = JSON.parse(readFileSync(join(dir, FAILED_UPDATE_FILE), \"utf8\")) as { version?: unknown; at?: unknown };\n return r.version === version && typeof r.at === \"number\" && now - r.at >= 0 && now - r.at < FAILED_UPDATE_RETRY_MS;\n } catch { return false; }\n}\n"]}
@@ -0,0 +1,16 @@
1
+ import { runStoreUpkeep } from "@scopebond/hook";
2
+ export type UpkeepReport = ReturnType<typeof runStoreUpkeep>;
3
+ export declare const UPKEEP_BUDGET_MS = 30000;
4
+ /** A pass that has not finished by then is stopped; the next maintenance pass carries on where the file stands. */
5
+ export declare const UPKEEP_TIMEOUT_MS: number;
6
+ /** `scopebond-agent upkeep`: one pass over this home's store, its report as one JSON line (`null` when there is no store). */
7
+ export declare function upkeepCommand(dir: string, args: readonly string[]): void;
8
+ export interface UpkeepApartOptions {
9
+ budgetMs?: number;
10
+ timeoutMs?: number;
11
+ /** The program and arguments to run instead of this agent's own `upkeep` (tests). */
12
+ command?: [string, string[]];
13
+ }
14
+ /** Run one upkeep pass for `dir` in a child process and resolve with its report. Rejects when the pass fails or overruns. */
15
+ export declare function runUpkeepApart(dir: string, options?: UpkeepApartOptions): Promise<UpkeepReport>;
16
+ //# sourceMappingURL=upkeep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upkeep.d.ts","sourceRoot":"","sources":["../src/upkeep.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAE7D,eAAO,MAAM,gBAAgB,QAAS,CAAC;AACvC,mHAAmH;AACnH,eAAO,MAAM,iBAAiB,QAAc,CAAC;AAE7C,8HAA8H;AAC9H,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAKxE;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC9B;AAED,6HAA6H;AAC7H,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CAwBnG"}
package/dist/upkeep.js ADDED
@@ -0,0 +1,55 @@
1
+ // The local store's upkeep in a process of its own (D144). A pass can take up to its budget (30 s), and the first pass over
2
+ // an older file rewrites the whole file; both are synchronous SQLite work. Run inside the agent they kept it from answering
3
+ // the tray and the CLI for as long as they took, so the agent starts `scopebond-agent upkeep` and waits for it without
4
+ // blocking: the tray, `status` and the workspace's requests are answered meanwhile.
5
+ import { spawn } from "node:child_process";
6
+ import { tmpdir } from "node:os";
7
+ import { runStoreUpkeep } from "@scopebond/hook";
8
+ import { agentSelfCommand } from "./self.js";
9
+ export const UPKEEP_BUDGET_MS = 30_000;
10
+ /** A pass that has not finished by then is stopped; the next maintenance pass carries on where the file stands. */
11
+ export const UPKEEP_TIMEOUT_MS = 10 * 60_000;
12
+ /** `scopebond-agent upkeep`: one pass over this home's store, its report as one JSON line (`null` when there is no store). */
13
+ export function upkeepCommand(dir, args) {
14
+ const i = args.indexOf("--budget");
15
+ const budget = i >= 0 ? Number(args[i + 1]) : UPKEEP_BUDGET_MS;
16
+ const report = runStoreUpkeep(dir, { budgetMs: Number.isFinite(budget) && budget > 0 ? budget : UPKEEP_BUDGET_MS, allowFullVacuum: true });
17
+ process.stdout.write(`${JSON.stringify(report)}\n`);
18
+ }
19
+ /** Run one upkeep pass for `dir` in a child process and resolve with its report. Rejects when the pass fails or overruns. */
20
+ export function runUpkeepApart(dir, options = {}) {
21
+ const budget = options.budgetMs ?? UPKEEP_BUDGET_MS;
22
+ const [program, args] = options.command ?? agentSelfCommand(["upkeep", "--budget", String(budget)]);
23
+ return new Promise((resolve, reject) => {
24
+ const child = spawn(program, args, {
25
+ cwd: tmpdir(), env: { ...process.env, SCOPEBOND_HOME: dir }, stdio: ["ignore", "pipe", "pipe"], windowsHide: true,
26
+ });
27
+ let out = "";
28
+ let err = "";
29
+ child.stdout?.setEncoding("utf8").on("data", (chunk) => { if (out.length < 65_536)
30
+ out += chunk; });
31
+ child.stderr?.setEncoding("utf8").on("data", (chunk) => { if (err.length < 8_192)
32
+ err += chunk; });
33
+ const timer = setTimeout(() => {
34
+ child.kill();
35
+ reject(new Error(`the local store upkeep did not finish within ${Math.round((options.timeoutMs ?? UPKEEP_TIMEOUT_MS) / 1000)} s`));
36
+ }, options.timeoutMs ?? UPKEEP_TIMEOUT_MS);
37
+ timer.unref?.();
38
+ child.on("error", (error) => { clearTimeout(timer); reject(error); });
39
+ child.on("close", (code) => {
40
+ clearTimeout(timer);
41
+ if (code !== 0) {
42
+ reject(new Error(`the local store upkeep exited with ${code}: ${err.trim().split(/\r?\n/).pop() ?? ""}`.trim()));
43
+ return;
44
+ }
45
+ const line = out.trim().split(/\r?\n/).pop() ?? "";
46
+ try {
47
+ resolve(JSON.parse(line));
48
+ }
49
+ catch {
50
+ reject(new Error("the local store upkeep gave no report"));
51
+ }
52
+ });
53
+ });
54
+ }
55
+ //# sourceMappingURL=upkeep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upkeep.js","sourceRoot":"","sources":["../src/upkeep.ts"],"names":[],"mappings":"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","sourcesContent":["// The local store's upkeep in a process of its own (D144). A pass can take up to its budget (30 s), and the first pass over\n// an older file rewrites the whole file; both are synchronous SQLite work. Run inside the agent they kept it from answering\n// the tray and the CLI for as long as they took, so the agent starts `scopebond-agent upkeep` and waits for it without\n// blocking: the tray, `status` and the workspace's requests are answered meanwhile.\n\nimport { spawn } from \"node:child_process\";\nimport { tmpdir } from \"node:os\";\nimport { runStoreUpkeep } from \"@scopebond/hook\";\nimport { agentSelfCommand } from \"./self.js\";\n\nexport type UpkeepReport = ReturnType<typeof runStoreUpkeep>;\n\nexport const UPKEEP_BUDGET_MS = 30_000;\n/** A pass that has not finished by then is stopped; the next maintenance pass carries on where the file stands. */\nexport const UPKEEP_TIMEOUT_MS = 10 * 60_000;\n\n/** `scopebond-agent upkeep`: one pass over this home's store, its report as one JSON line (`null` when there is no store). */\nexport function upkeepCommand(dir: string, args: readonly string[]): void {\n const i = args.indexOf(\"--budget\");\n const budget = i >= 0 ? Number(args[i + 1]) : UPKEEP_BUDGET_MS;\n const report = runStoreUpkeep(dir, { budgetMs: Number.isFinite(budget) && budget > 0 ? budget : UPKEEP_BUDGET_MS, allowFullVacuum: true });\n process.stdout.write(`${JSON.stringify(report)}\\n`);\n}\n\nexport interface UpkeepApartOptions {\n budgetMs?: number;\n timeoutMs?: number;\n /** The program and arguments to run instead of this agent's own `upkeep` (tests). */\n command?: [string, string[]];\n}\n\n/** Run one upkeep pass for `dir` in a child process and resolve with its report. Rejects when the pass fails or overruns. */\nexport function runUpkeepApart(dir: string, options: UpkeepApartOptions = {}): Promise<UpkeepReport> {\n const budget = options.budgetMs ?? UPKEEP_BUDGET_MS;\n const [program, args] = options.command ?? agentSelfCommand([\"upkeep\", \"--budget\", String(budget)]);\n return new Promise((resolve, reject) => {\n const child = spawn(program, args, {\n cwd: tmpdir(), env: { ...process.env, SCOPEBOND_HOME: dir }, stdio: [\"ignore\", \"pipe\", \"pipe\"], windowsHide: true,\n });\n let out = \"\";\n let err = \"\";\n child.stdout?.setEncoding(\"utf8\").on(\"data\", (chunk: string) => { if (out.length < 65_536) out += chunk; });\n child.stderr?.setEncoding(\"utf8\").on(\"data\", (chunk: string) => { if (err.length < 8_192) err += chunk; });\n const timer = setTimeout(() => {\n child.kill();\n reject(new Error(`the local store upkeep did not finish within ${Math.round((options.timeoutMs ?? UPKEEP_TIMEOUT_MS) / 1000)} s`));\n }, options.timeoutMs ?? UPKEEP_TIMEOUT_MS);\n timer.unref?.();\n child.on(\"error\", (error) => { clearTimeout(timer); reject(error); });\n child.on(\"close\", (code) => {\n clearTimeout(timer);\n if (code !== 0) { reject(new Error(`the local store upkeep exited with ${code}: ${err.trim().split(/\\r?\\n/).pop() ?? \"\"}`.trim())); return; }\n const line = out.trim().split(/\\r?\\n/).pop() ?? \"\";\n try { resolve(JSON.parse(line) as UpkeepReport); } catch { reject(new Error(\"the local store upkeep gave no report\")); }\n });\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scopebond/agent",
3
- "version": "0.5.6",
3
+ "version": "0.6.0",
4
4
  "description": "Free, open-source Scopebond Agent companion: deliver queued records, maintain rules and connections, and report computer health to the separate proprietary Scopebond Cloud workspace.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Avouro LLC",
@@ -39,8 +39,8 @@
39
39
  "dist"
40
40
  ],
41
41
  "dependencies": {
42
- "@scopebond/gateway": "0.17.3",
43
- "@scopebond/hook": "0.21.5",
42
+ "@scopebond/hook": "0.21.6",
43
+ "@scopebond/gateway": "0.17.4",
44
44
  "@scopebond/sdk": "0.1.6"
45
45
  },
46
46
  "publishConfig": {