openmeld 0.3.229 → 0.3.231

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 (66) hide show
  1. package/dist/{add-me-membership-25sIYCId.js → add-me-membership-0KyMk1wi.js} +2 -2
  2. package/dist/{add-me-membership-25sIYCId.js.map → add-me-membership-0KyMk1wi.js.map} +1 -1
  3. package/dist/{agents-DqhKdgat.js → agents-Bkx6ldpV.js} +7 -7
  4. package/dist/{agents-DqhKdgat.js.map → agents-Bkx6ldpV.js.map} +1 -1
  5. package/dist/{command-BFIRSLTj.js → command-CBWv24uj.js} +9 -9
  6. package/dist/{command-BFIRSLTj.js.map → command-CBWv24uj.js.map} +1 -1
  7. package/dist/{computer-connection-review-C9CKzIdH.js → computer-connection-review-BSPMGVhN.js} +2 -2
  8. package/dist/{computer-connection-review-C9CKzIdH.js.map → computer-connection-review-BSPMGVhN.js.map} +1 -1
  9. package/dist/{computer-disconnect-Cvl_ia32.js → computer-disconnect-BQ_MDeeA.js} +3 -3
  10. package/dist/{computer-disconnect-Cvl_ia32.js.map → computer-disconnect-BQ_MDeeA.js.map} +1 -1
  11. package/dist/{computer-setup-continuation-uFrI9ZaE.js → computer-setup-continuation-Cd293Yzi.js} +2 -2
  12. package/dist/{computer-setup-continuation-uFrI9ZaE.js.map → computer-setup-continuation-Cd293Yzi.js.map} +1 -1
  13. package/dist/{daemon-frame-transport-BQR5LfG2.js → daemon-frame-transport-xQnNyg6E.js} +3 -3
  14. package/dist/daemon-frame-transport-xQnNyg6E.js.map +1 -0
  15. package/dist/{daemon-lifecycle-journal-G_C_pRtu.js → daemon-lifecycle-journal-DrwEygzu.js} +2 -2
  16. package/dist/{daemon-lifecycle-journal-G_C_pRtu.js.map → daemon-lifecycle-journal-DrwEygzu.js.map} +1 -1
  17. package/dist/{daemon-service-runtime-BkVvz7bG.js → daemon-service-runtime-B4nWB2Qx.js} +2 -2
  18. package/dist/{daemon-service-runtime-BkVvz7bG.js.map → daemon-service-runtime-B4nWB2Qx.js.map} +1 -1
  19. package/dist/{daemon-service-update-coordinator-UajkUU66.js → daemon-service-update-coordinator-C8cW7Vn_.js} +16 -11
  20. package/dist/daemon-service-update-coordinator-C8cW7Vn_.js.map +1 -0
  21. package/dist/{elapsed-time-UlhDiZjv.js → elapsed-time-COv3bjEl.js} +4 -4
  22. package/dist/{elapsed-time-UlhDiZjv.js.map → elapsed-time-COv3bjEl.js.map} +1 -1
  23. package/dist/{entry-BotSzkFU.js → entry-DIjUKIep.js} +2 -2
  24. package/dist/{entry-BotSzkFU.js.map → entry-DIjUKIep.js.map} +1 -1
  25. package/dist/{installation-inventory-BgZq7fWv.js → installation-inventory-DllgoKT1.js} +3 -3
  26. package/dist/{installation-inventory-BgZq7fWv.js.map → installation-inventory-DllgoKT1.js.map} +1 -1
  27. package/dist/{installer-DxU4S_WH.js → installer-Sc79LhuA.js} +2 -2
  28. package/dist/{installer-DxU4S_WH.js.map → installer-Sc79LhuA.js.map} +1 -1
  29. package/dist/{meta-api-D0nhhSY7.js → meta-api-CEw8eOeN.js} +10 -7
  30. package/dist/meta-api-CEw8eOeN.js.map +1 -0
  31. package/dist/{openmeld-BWAL_LKY.js → openmeld-BUYFXSyY.js} +22 -22
  32. package/dist/{openmeld-BWAL_LKY.js.map → openmeld-BUYFXSyY.js.map} +1 -1
  33. package/dist/{openmeld-maintenance-worker-DOTHTGQt.js → openmeld-maintenance-worker-Br6WIhhe.js} +9 -9
  34. package/dist/{openmeld-maintenance-worker-DOTHTGQt.js.map → openmeld-maintenance-worker-Br6WIhhe.js.map} +1 -1
  35. package/dist/{openmeld-tools-update-join-DQd7kyjX.js → openmeld-tools-update-join-B1l6RER6.js} +12 -4
  36. package/dist/{openmeld-tools-update-join-DQd7kyjX.js.map → openmeld-tools-update-join-B1l6RER6.js.map} +1 -1
  37. package/dist/openmeld.js +4 -4
  38. package/dist/{prepare-provider-runtime-DDYaeyRp.js → prepare-provider-runtime-DfsSj_N_.js} +3 -3
  39. package/dist/prepare-provider-runtime-DfsSj_N_.js.map +1 -0
  40. package/dist/{prepare-session-executor-C7n9tbr-.js → prepare-session-executor-CrYpWljb.js} +16 -13
  41. package/dist/prepare-session-executor-CrYpWljb.js.map +1 -0
  42. package/dist/{runtime-Cxz_FMWn.js → runtime-ZLBVtFFY.js} +9 -9
  43. package/dist/{runtime-Cxz_FMWn.js.map → runtime-ZLBVtFFY.js.map} +1 -1
  44. package/dist/{runtime-agent-controller-reporting-submission-Ba_cI1hv.js → runtime-agent-controller-reporting-submission-CbaUsNTF.js} +3 -3
  45. package/dist/{runtime-agent-controller-reporting-submission-Ba_cI1hv.js.map → runtime-agent-controller-reporting-submission-CbaUsNTF.js.map} +1 -1
  46. package/dist/{runtime-reporting-health-state-BUX4e4x7.js → runtime-reporting-health-state-DOg9iwwO.js} +4 -4
  47. package/dist/{runtime-reporting-health-state-BUX4e4x7.js.map → runtime-reporting-health-state-DOg9iwwO.js.map} +1 -1
  48. package/dist/{service-BHNAamFv.js → service-B9y1SQlB.js} +9 -9
  49. package/dist/{service-BHNAamFv.js.map → service-B9y1SQlB.js.map} +1 -1
  50. package/dist/{service-account-control-s0OXYGgp.js → service-account-control-DALO1USM.js} +5 -5
  51. package/dist/{service-account-control-s0OXYGgp.js.map → service-account-control-DALO1USM.js.map} +1 -1
  52. package/dist/{service-control-capabilities-LZc_90-g.js → service-control-capabilities-B9ZxDPOJ.js} +1 -1
  53. package/dist/{service-control-capabilities-DrFu2peO.js → service-control-capabilities-CKwU9Er5.js} +3 -3
  54. package/dist/{service-control-capabilities-DrFu2peO.js.map → service-control-capabilities-CKwU9Er5.js.map} +1 -1
  55. package/dist/{state-mQWCO2uD.js → state-CdSbKM0J.js} +2 -2
  56. package/dist/{state-mQWCO2uD.js.map → state-CdSbKM0J.js.map} +1 -1
  57. package/dist/upgrade-BFWUxFpJ.js +4 -0
  58. package/dist/{upgrade-CJn4nMKH.js → upgrade-DLJJlkbf.js} +6 -6
  59. package/dist/{upgrade-CJn4nMKH.js.map → upgrade-DLJJlkbf.js.map} +1 -1
  60. package/package.json +10 -10
  61. package/dist/daemon-frame-transport-BQR5LfG2.js.map +0 -1
  62. package/dist/daemon-service-update-coordinator-UajkUU66.js.map +0 -1
  63. package/dist/meta-api-D0nhhSY7.js.map +0 -1
  64. package/dist/prepare-provider-runtime-DDYaeyRp.js.map +0 -1
  65. package/dist/prepare-session-executor-C7n9tbr-.js.map +0 -1
  66. package/dist/upgrade-BFwP5HXC.js +0 -4
@@ -197,7 +197,7 @@ function runExecutionHost(hostInstanceId) {
197
197
  ownership = verifiedOwnership;
198
198
  session = verified.session;
199
199
  await withAdmittedServiceSession(session, async () => {
200
- const { createExecutionHostRuntime, createExecutionHostResources } = await import("./runtime-Cxz_FMWn.js");
200
+ const { createExecutionHostRuntime, createExecutionHostResources } = await import("./runtime-ZLBVtFFY.js");
201
201
  const runtimePaths = await ensureDaemonRuntimePaths();
202
202
  const presenter = createPresenter(await resolveRuntimeContext({ view: "agent" }));
203
203
  runtime = await createExecutionHostRuntime({
@@ -251,4 +251,4 @@ function runExecutionHost(hostInstanceId) {
251
251
  //#endregion
252
252
  export { runExecutionHost };
253
253
 
254
- //# sourceMappingURL=entry-BotSzkFU.js.map
254
+ //# sourceMappingURL=entry-DIjUKIep.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entry-BotSzkFU.js","names":[],"sources":["../src/local-service/execution-host/identity.ts","../src/local-service/execution-host/ownership.ts","../src/local-service/execution-host/entry.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport type { ServiceExecutionHostIdentity } from \"@openmeld/schemas\";\nimport {\n buildStoredAuthSessionIdentity,\n getAuthSessionState,\n} from \"../../config/auth-session\";\nimport { resolveBaseUrl } from \"../../config/base-url\";\nimport { readDaemonServiceContract } from \"../../config/daemon-service-contract\";\nimport { resolveOpenMeldRootDir } from \"../../config/paths\";\nimport { readProcessStartIdentity } from \"../../system/process-identity\";\nimport { ExecutionHostError } from \"./channel\";\n\nexport async function validateExecutionHostIdentity(\n identity: ServiceExecutionHostIdentity\n) {\n if (\n process.ppid !== identity.parentPid ||\n (process.platform !== \"win32\" &&\n readProcessStartIdentity(process.ppid) !==\n identity.parentProcessStartedAt) ||\n resolve(resolveOpenMeldRootDir()) !== resolve(identity.stateRoot)\n ) {\n throw new ExecutionHostError(\n \"host.identity_mismatch\",\n \"The Host's parent or installation changed.\"\n );\n }\n const [auth, contract, gateway] = await Promise.all([\n getAuthSessionState(),\n readDaemonServiceContract(),\n resolveBaseUrl(),\n ]);\n const session = auth.session;\n if (\n auth.state !== \"valid\" ||\n !session ||\n !contract ||\n session.user?.id !== identity.ownerUserId ||\n buildStoredAuthSessionIdentity(session) !== identity.sessionIdentity ||\n session.authBaseUrl !== identity.authBaseUrl ||\n gateway !== identity.gatewayBaseUrl ||\n contract.gatewayUrl !== identity.gatewayBaseUrl ||\n contract.ownerUserId !== identity.ownerUserId ||\n contract.deviceId !== identity.deviceId ||\n contract.lane !== identity.lane ||\n contract.generation !== identity.serviceContractGeneration\n ) {\n throw new ExecutionHostError(\n \"host.identity_mismatch\",\n \"The Host's account, device or Service generation changed.\"\n );\n }\n return { session, contract };\n}\n","import { execFile } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { serviceExecutionHostOwnerSchema } from \"@openmeld/schemas\";\nimport { z } from \"zod/v4\";\nimport { acquireLock, releaseLock } from \"../../config/lock\";\nimport { systemDir } from \"../../config/paths\";\nimport { ExecutionHostError } from \"./channel\";\n\nconst run = promisify(execFile);\nconst WINDOWS_BOOT_EVENT = /^\\d+:\\d+$/;\nconst DECIMAL = /^\\d+$/;\n\nexport async function readExecutionHostBootIdentity(): Promise<string | null> {\n try {\n return await readBootIdentity();\n } catch {\n // Fresh/quiescent starts do not require reboot evidence. Unknown evidence\n // can never clear an unsafe previous owner, and is not another boot.\n console.warn(\n \"[openmeld.execution_host.boot_unknown] Automatic recovery of unconfirmed work requires operating-system restart evidence.\"\n );\n return null;\n }\n}\n\nasync function readBootIdentity(): Promise<string | null> {\n if (process.platform === \"linux\") {\n const id = z\n .uuid()\n .parse(\n (await readFile(\"/proc/sys/kernel/random/boot_id\", \"utf8\")).trim()\n );\n return `linux:${id.toLowerCase()}`;\n }\n let stdout = \"\";\n if (process.platform === \"darwin\") {\n // XNU's immutable boot-session UUID, not its clock-adjustable boot time.\n ({ stdout } = await run(\n \"/usr/sbin/sysctl\",\n [\"-n\", \"kern.bootsessionuuid\"],\n {\n timeout: 5000,\n }\n ));\n return `darwin:${z.uuid().parse(stdout.trim()).toLowerCase()}`;\n }\n if (process.platform === \"win32\") {\n ({ stdout } = await run(\n \"powershell.exe\",\n [\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-Command\",\n \"$ErrorActionPreference='Stop'; $e=Get-WinEvent -FilterHashtable @{LogName='System';ProviderName='Microsoft-Windows-Kernel-General';Id=12} -MaxEvents 1; if($null -eq $e.RecordId -or $null -eq $e.TimeCreated){throw 'Boot event unavailable'}; [Console]::WriteLine(([string]$e.RecordId)+':'+([string]$e.TimeCreated.ToUniversalTime().Ticks))\",\n ],\n { timeout: 5000, windowsHide: true }\n ));\n if (!WINDOWS_BOOT_EVENT.test(stdout.trim())) {\n throw new Error(\"Invalid Windows boot event\");\n }\n return `win32:${stdout.trim()}`;\n }\n return null;\n}\n\nfunction confirmsNewBoot(\n previous: string | null,\n current: string | null\n): boolean {\n if (!(previous && current) || previous === current) {\n return false;\n }\n const [priorSource, priorId, priorTime] = previous.split(\":\");\n const [source, id, time] = current.split(\":\");\n if (source !== priorSource) {\n return false;\n }\n if (source === \"linux\" || source === \"darwin\") {\n return (\n z.uuid().safeParse(id).success && z.uuid().safeParse(priorId).success\n );\n }\n // Kernel-General 12 records OS startup, not EventLog-service restarts or\n // wall-clock corrections. Require a later retained event in both fields;\n // missing/cleared/rotated evidence cannot authorize replacing unknown work.\n if (\n source !== \"win32\" ||\n !id ||\n !time ||\n !priorId ||\n !priorTime ||\n ![id, time, priorId, priorTime].every((value) => DECIMAL.test(value))\n ) {\n return false;\n }\n return BigInt(id) > BigInt(priorId) && BigInt(time) > BigInt(priorTime);\n}\n\nexport async function acquireExecutionHostOwnership(input: {\n hostInstanceId: string;\n ownerUserId: string;\n deviceId: string;\n lane: \"prod\" | \"dev-local\" | \"canary\";\n stateRoot: string;\n bootIdentity: string | null;\n}) {\n const lock = await acquireLock({\n openMeldProfileId: \"service-execution-host\",\n key: \"process-owner\",\n pathResolution: { env: { ...process.env, OPENMELD_HOME: input.stateRoot } },\n meta: {\n hostInstanceId: input.hostInstanceId,\n ownerUserId: input.ownerUserId,\n },\n });\n const path = join(\n systemDir({ env: { OPENMELD_HOME: input.stateRoot } }),\n \"execution-host-owner.json\"\n );\n try {\n const previous = readOwner(path);\n if (\n previous &&\n !previous.localQuiescent &&\n !confirmsNewBoot(previous.bootIdentity, input.bootIdentity)\n ) {\n throw new ExecutionHostError(\n \"host.previous_work_unconfirmed\",\n \"The previous execution host ended before its local work was confirmed stopped. Restart this Computer, then check its connection. If restart evidence is unavailable, inspect the retained Host diagnostics before recovery. Existing results remain saved; no task will be restarted automatically.\"\n );\n }\n let owner = serviceExecutionHostOwnerSchema.parse({\n schema: \"service-execution-host-owner-v1\",\n hostInstanceId: input.hostInstanceId,\n ownerUserId: input.ownerUserId,\n deviceId: input.deviceId,\n lane: input.lane,\n pid: process.pid,\n bootIdentity: input.bootIdentity,\n localQuiescent: true,\n });\n persist(owner);\n function persist(next: typeof owner) {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n const temporary = `${path}.${randomUUID()}.tmp`;\n writeFileSync(temporary, JSON.stringify(next), {\n mode: 0o600,\n flag: \"wx\",\n });\n renameSync(temporary, path);\n }\n return {\n observeLocalQuiescence(quiescent: boolean) {\n if (owner.localQuiescent === quiescent) {\n return;\n }\n const next = { ...owner, localQuiescent: quiescent };\n // The unsafe transition is durable before any provider operation. A\n // failed write refuses that operation rather than weakening the fence.\n persist(next);\n owner = next;\n },\n release: () => releaseLock(lock),\n };\n } catch (error) {\n await releaseLock(lock);\n throw error;\n }\n}\n\nfunction readOwner(path: string) {\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n const parsed = serviceExecutionHostOwnerSchema.safeParse(JSON.parse(raw));\n if (!parsed.success) {\n throw new ExecutionHostError(\n \"host.owner_corrupt\",\n \"The Host ownership record cannot be verified. Preserve it for diagnostics; automatic replacement is refused.\"\n );\n }\n return parsed.data;\n}\n","import {\n type ServiceExecutionHostIdentity,\n serviceExecutionHostMethods,\n} from \"@openmeld/schemas\";\nimport {\n type StoredAuthSession,\n withAdmittedServiceSession,\n} from \"../../config/auth-session\";\nimport { resolveRuntimeContext } from \"../../runtime/context\";\nimport { createPresenter } from \"../../runtime/presenter/index\";\nimport { ensureDaemonRuntimePaths } from \"../state/daemon-device-id\";\nimport {\n ExecutionHostError,\n type ExecutionHostHandlers,\n serveExecutionHost,\n} from \"./channel\";\nimport { validateExecutionHostIdentity } from \"./identity\";\nimport {\n acquireExecutionHostOwnership,\n readExecutionHostBootIdentity,\n} from \"./ownership\";\nimport { parentExecutionHostChannel } from \"./process-channel\";\n\n// This entry has no public listener and accepts no executable/path override.\n// The inherited pipe, parent incarnation and current Service account are all\n// required before the provider graph or any local runtime state is opened.\nexport function runExecutionHost(hostInstanceId: string): Promise<void> {\n const channel = parentExecutionHostChannel();\n const done = Promise.withResolvers<void>();\n let runtime: Awaited<\n ReturnType<typeof import(\"./runtime\").createExecutionHostRuntime>\n > | null = null;\n let ownership: Awaited<\n ReturnType<typeof acquireExecutionHostOwnership>\n > | null = null;\n let session: StoredAuthSession | null = null;\n let acceptedIdentity: ServiceExecutionHostIdentity | null = null;\n let initializing: Promise<void> | null = null;\n let closing: Promise<void> | null = null;\n let disconnected = false;\n\n const close = (): Promise<void> => {\n if (!closing) {\n closing = (async () => {\n try {\n await initializing;\n if (runtime && session) {\n const currentRuntime = runtime;\n await withAdmittedServiceSession(session, () =>\n currentRuntime.closeAfterConnectorLoss()\n );\n }\n } finally {\n await ownership?.release();\n server.dispose();\n if (process.connected) {\n process.disconnect();\n }\n }\n })();\n closing.then(\n () => done.resolve(),\n (error) => done.reject(error)\n );\n }\n return closing;\n };\n\n const handlers = {\n initialize: async (identity: ServiceExecutionHostIdentity) => {\n if (\n acceptedIdentity &&\n JSON.stringify(acceptedIdentity) !== JSON.stringify(identity)\n ) {\n throw new ExecutionHostError(\n \"host.identity_mismatch\",\n \"This Host is already assigned to a different Service incarnation.\"\n );\n }\n if (!initializing) {\n acceptedIdentity = identity;\n initializing = (async () => {\n const verified = await validateExecutionHostIdentity(identity);\n if (disconnected) {\n throw new ExecutionHostError(\n \"host.disconnected\",\n \"The supervising Service left before Host initialization.\"\n );\n }\n const verifiedOwnership = await acquireExecutionHostOwnership({\n ...identity,\n hostInstanceId,\n bootIdentity: await readExecutionHostBootIdentity(),\n });\n ownership = verifiedOwnership;\n session = verified.session;\n await withAdmittedServiceSession(session, async () => {\n const { createExecutionHostRuntime, createExecutionHostResources } =\n await import(\"./runtime\");\n const runtimePaths = await ensureDaemonRuntimePaths();\n const presenter = createPresenter(\n await resolveRuntimeContext({ view: \"agent\" })\n );\n runtime = await createExecutionHostRuntime({\n resources: await createExecutionHostResources({\n runtimePaths,\n presenter,\n }),\n hostInstanceId,\n identity,\n runtimePaths,\n serviceBundleId: verified.contract.bundleId,\n profileOwnerName: verified.session.user?.name ?? null,\n presenter,\n emit: (event) => {\n if (!disconnected) {\n server.emit(event);\n }\n },\n onWorkStateChange: (quiescent) =>\n verifiedOwnership.observeLocalQuiescence(quiescent),\n });\n });\n })();\n }\n await initializing;\n if (!runtime || disconnected) {\n throw new ExecutionHostError(\n \"host.disconnected\",\n \"The execution Host is not available.\"\n );\n }\n return runtime.snapshot();\n },\n } as ExecutionHostHandlers;\n\n // Each concrete method is still decoded by the shared method table at both\n // ends; the forwarding bridge cannot select a new account or mutate identity.\n for (const method of Object.keys(serviceExecutionHostMethods) as Array<\n keyof ExecutionHostHandlers\n >) {\n if (method === \"initialize\") {\n continue;\n }\n const target = handlers as unknown as Record<\n string,\n (payload: unknown) => Promise<unknown>\n >;\n target[method] = async (payload) => {\n if (!(runtime && session) || disconnected) {\n throw new ExecutionHostError(\n \"host.not_initialized\",\n \"Initialize this Host through its supervising Service first.\"\n );\n }\n const invoke = runtime.handlers[method] as (value: unknown) => unknown;\n return await withAdmittedServiceSession(\n session,\n async () => await invoke(payload)\n );\n };\n }\n\n const server = serveExecutionHost({\n channel,\n hostInstanceId,\n handlers,\n onFailure: (error) => {\n console.error(\"[openmeld.execution_host.channel_failed]\", error);\n disconnected = true;\n close().catch(() => undefined);\n },\n onDisconnect: () => {\n disconnected = true;\n close().catch(() => undefined);\n },\n });\n return done.promise;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"entry-DIjUKIep.js","names":[],"sources":["../src/local-service/execution-host/identity.ts","../src/local-service/execution-host/ownership.ts","../src/local-service/execution-host/entry.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport type { ServiceExecutionHostIdentity } from \"@openmeld/schemas\";\nimport {\n buildStoredAuthSessionIdentity,\n getAuthSessionState,\n} from \"../../config/auth-session\";\nimport { resolveBaseUrl } from \"../../config/base-url\";\nimport { readDaemonServiceContract } from \"../../config/daemon-service-contract\";\nimport { resolveOpenMeldRootDir } from \"../../config/paths\";\nimport { readProcessStartIdentity } from \"../../system/process-identity\";\nimport { ExecutionHostError } from \"./channel\";\n\nexport async function validateExecutionHostIdentity(\n identity: ServiceExecutionHostIdentity\n) {\n if (\n process.ppid !== identity.parentPid ||\n (process.platform !== \"win32\" &&\n readProcessStartIdentity(process.ppid) !==\n identity.parentProcessStartedAt) ||\n resolve(resolveOpenMeldRootDir()) !== resolve(identity.stateRoot)\n ) {\n throw new ExecutionHostError(\n \"host.identity_mismatch\",\n \"The Host's parent or installation changed.\"\n );\n }\n const [auth, contract, gateway] = await Promise.all([\n getAuthSessionState(),\n readDaemonServiceContract(),\n resolveBaseUrl(),\n ]);\n const session = auth.session;\n if (\n auth.state !== \"valid\" ||\n !session ||\n !contract ||\n session.user?.id !== identity.ownerUserId ||\n buildStoredAuthSessionIdentity(session) !== identity.sessionIdentity ||\n session.authBaseUrl !== identity.authBaseUrl ||\n gateway !== identity.gatewayBaseUrl ||\n contract.gatewayUrl !== identity.gatewayBaseUrl ||\n contract.ownerUserId !== identity.ownerUserId ||\n contract.deviceId !== identity.deviceId ||\n contract.lane !== identity.lane ||\n contract.generation !== identity.serviceContractGeneration\n ) {\n throw new ExecutionHostError(\n \"host.identity_mismatch\",\n \"The Host's account, device or Service generation changed.\"\n );\n }\n return { session, contract };\n}\n","import { execFile } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { serviceExecutionHostOwnerSchema } from \"@openmeld/schemas\";\nimport { z } from \"zod/v4\";\nimport { acquireLock, releaseLock } from \"../../config/lock\";\nimport { systemDir } from \"../../config/paths\";\nimport { ExecutionHostError } from \"./channel\";\n\nconst run = promisify(execFile);\nconst WINDOWS_BOOT_EVENT = /^\\d+:\\d+$/;\nconst DECIMAL = /^\\d+$/;\n\nexport async function readExecutionHostBootIdentity(): Promise<string | null> {\n try {\n return await readBootIdentity();\n } catch {\n // Fresh/quiescent starts do not require reboot evidence. Unknown evidence\n // can never clear an unsafe previous owner, and is not another boot.\n console.warn(\n \"[openmeld.execution_host.boot_unknown] Automatic recovery of unconfirmed work requires operating-system restart evidence.\"\n );\n return null;\n }\n}\n\nasync function readBootIdentity(): Promise<string | null> {\n if (process.platform === \"linux\") {\n const id = z\n .uuid()\n .parse(\n (await readFile(\"/proc/sys/kernel/random/boot_id\", \"utf8\")).trim()\n );\n return `linux:${id.toLowerCase()}`;\n }\n let stdout = \"\";\n if (process.platform === \"darwin\") {\n // XNU's immutable boot-session UUID, not its clock-adjustable boot time.\n ({ stdout } = await run(\n \"/usr/sbin/sysctl\",\n [\"-n\", \"kern.bootsessionuuid\"],\n {\n timeout: 5000,\n }\n ));\n return `darwin:${z.uuid().parse(stdout.trim()).toLowerCase()}`;\n }\n if (process.platform === \"win32\") {\n ({ stdout } = await run(\n \"powershell.exe\",\n [\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-Command\",\n \"$ErrorActionPreference='Stop'; $e=Get-WinEvent -FilterHashtable @{LogName='System';ProviderName='Microsoft-Windows-Kernel-General';Id=12} -MaxEvents 1; if($null -eq $e.RecordId -or $null -eq $e.TimeCreated){throw 'Boot event unavailable'}; [Console]::WriteLine(([string]$e.RecordId)+':'+([string]$e.TimeCreated.ToUniversalTime().Ticks))\",\n ],\n { timeout: 5000, windowsHide: true }\n ));\n if (!WINDOWS_BOOT_EVENT.test(stdout.trim())) {\n throw new Error(\"Invalid Windows boot event\");\n }\n return `win32:${stdout.trim()}`;\n }\n return null;\n}\n\nfunction confirmsNewBoot(\n previous: string | null,\n current: string | null\n): boolean {\n if (!(previous && current) || previous === current) {\n return false;\n }\n const [priorSource, priorId, priorTime] = previous.split(\":\");\n const [source, id, time] = current.split(\":\");\n if (source !== priorSource) {\n return false;\n }\n if (source === \"linux\" || source === \"darwin\") {\n return (\n z.uuid().safeParse(id).success && z.uuid().safeParse(priorId).success\n );\n }\n // Kernel-General 12 records OS startup, not EventLog-service restarts or\n // wall-clock corrections. Require a later retained event in both fields;\n // missing/cleared/rotated evidence cannot authorize replacing unknown work.\n if (\n source !== \"win32\" ||\n !id ||\n !time ||\n !priorId ||\n !priorTime ||\n ![id, time, priorId, priorTime].every((value) => DECIMAL.test(value))\n ) {\n return false;\n }\n return BigInt(id) > BigInt(priorId) && BigInt(time) > BigInt(priorTime);\n}\n\nexport async function acquireExecutionHostOwnership(input: {\n hostInstanceId: string;\n ownerUserId: string;\n deviceId: string;\n lane: \"prod\" | \"dev-local\" | \"canary\";\n stateRoot: string;\n bootIdentity: string | null;\n}) {\n const lock = await acquireLock({\n openMeldProfileId: \"service-execution-host\",\n key: \"process-owner\",\n pathResolution: { env: { ...process.env, OPENMELD_HOME: input.stateRoot } },\n meta: {\n hostInstanceId: input.hostInstanceId,\n ownerUserId: input.ownerUserId,\n },\n });\n const path = join(\n systemDir({ env: { OPENMELD_HOME: input.stateRoot } }),\n \"execution-host-owner.json\"\n );\n try {\n const previous = readOwner(path);\n if (\n previous &&\n !previous.localQuiescent &&\n !confirmsNewBoot(previous.bootIdentity, input.bootIdentity)\n ) {\n throw new ExecutionHostError(\n \"host.previous_work_unconfirmed\",\n \"The previous execution host ended before its local work was confirmed stopped. Restart this Computer, then check its connection. If restart evidence is unavailable, inspect the retained Host diagnostics before recovery. Existing results remain saved; no task will be restarted automatically.\"\n );\n }\n let owner = serviceExecutionHostOwnerSchema.parse({\n schema: \"service-execution-host-owner-v1\",\n hostInstanceId: input.hostInstanceId,\n ownerUserId: input.ownerUserId,\n deviceId: input.deviceId,\n lane: input.lane,\n pid: process.pid,\n bootIdentity: input.bootIdentity,\n localQuiescent: true,\n });\n persist(owner);\n function persist(next: typeof owner) {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n const temporary = `${path}.${randomUUID()}.tmp`;\n writeFileSync(temporary, JSON.stringify(next), {\n mode: 0o600,\n flag: \"wx\",\n });\n renameSync(temporary, path);\n }\n return {\n observeLocalQuiescence(quiescent: boolean) {\n if (owner.localQuiescent === quiescent) {\n return;\n }\n const next = { ...owner, localQuiescent: quiescent };\n // The unsafe transition is durable before any provider operation. A\n // failed write refuses that operation rather than weakening the fence.\n persist(next);\n owner = next;\n },\n release: () => releaseLock(lock),\n };\n } catch (error) {\n await releaseLock(lock);\n throw error;\n }\n}\n\nfunction readOwner(path: string) {\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n const parsed = serviceExecutionHostOwnerSchema.safeParse(JSON.parse(raw));\n if (!parsed.success) {\n throw new ExecutionHostError(\n \"host.owner_corrupt\",\n \"The Host ownership record cannot be verified. Preserve it for diagnostics; automatic replacement is refused.\"\n );\n }\n return parsed.data;\n}\n","import {\n type ServiceExecutionHostIdentity,\n serviceExecutionHostMethods,\n} from \"@openmeld/schemas\";\nimport {\n type StoredAuthSession,\n withAdmittedServiceSession,\n} from \"../../config/auth-session\";\nimport { resolveRuntimeContext } from \"../../runtime/context\";\nimport { createPresenter } from \"../../runtime/presenter/index\";\nimport { ensureDaemonRuntimePaths } from \"../state/daemon-device-id\";\nimport {\n ExecutionHostError,\n type ExecutionHostHandlers,\n serveExecutionHost,\n} from \"./channel\";\nimport { validateExecutionHostIdentity } from \"./identity\";\nimport {\n acquireExecutionHostOwnership,\n readExecutionHostBootIdentity,\n} from \"./ownership\";\nimport { parentExecutionHostChannel } from \"./process-channel\";\n\n// This entry has no public listener and accepts no executable/path override.\n// The inherited pipe, parent incarnation and current Service account are all\n// required before the provider graph or any local runtime state is opened.\nexport function runExecutionHost(hostInstanceId: string): Promise<void> {\n const channel = parentExecutionHostChannel();\n const done = Promise.withResolvers<void>();\n let runtime: Awaited<\n ReturnType<typeof import(\"./runtime\").createExecutionHostRuntime>\n > | null = null;\n let ownership: Awaited<\n ReturnType<typeof acquireExecutionHostOwnership>\n > | null = null;\n let session: StoredAuthSession | null = null;\n let acceptedIdentity: ServiceExecutionHostIdentity | null = null;\n let initializing: Promise<void> | null = null;\n let closing: Promise<void> | null = null;\n let disconnected = false;\n\n const close = (): Promise<void> => {\n if (!closing) {\n closing = (async () => {\n try {\n await initializing;\n if (runtime && session) {\n const currentRuntime = runtime;\n await withAdmittedServiceSession(session, () =>\n currentRuntime.closeAfterConnectorLoss()\n );\n }\n } finally {\n await ownership?.release();\n server.dispose();\n if (process.connected) {\n process.disconnect();\n }\n }\n })();\n closing.then(\n () => done.resolve(),\n (error) => done.reject(error)\n );\n }\n return closing;\n };\n\n const handlers = {\n initialize: async (identity: ServiceExecutionHostIdentity) => {\n if (\n acceptedIdentity &&\n JSON.stringify(acceptedIdentity) !== JSON.stringify(identity)\n ) {\n throw new ExecutionHostError(\n \"host.identity_mismatch\",\n \"This Host is already assigned to a different Service incarnation.\"\n );\n }\n if (!initializing) {\n acceptedIdentity = identity;\n initializing = (async () => {\n const verified = await validateExecutionHostIdentity(identity);\n if (disconnected) {\n throw new ExecutionHostError(\n \"host.disconnected\",\n \"The supervising Service left before Host initialization.\"\n );\n }\n const verifiedOwnership = await acquireExecutionHostOwnership({\n ...identity,\n hostInstanceId,\n bootIdentity: await readExecutionHostBootIdentity(),\n });\n ownership = verifiedOwnership;\n session = verified.session;\n await withAdmittedServiceSession(session, async () => {\n const { createExecutionHostRuntime, createExecutionHostResources } =\n await import(\"./runtime\");\n const runtimePaths = await ensureDaemonRuntimePaths();\n const presenter = createPresenter(\n await resolveRuntimeContext({ view: \"agent\" })\n );\n runtime = await createExecutionHostRuntime({\n resources: await createExecutionHostResources({\n runtimePaths,\n presenter,\n }),\n hostInstanceId,\n identity,\n runtimePaths,\n serviceBundleId: verified.contract.bundleId,\n profileOwnerName: verified.session.user?.name ?? null,\n presenter,\n emit: (event) => {\n if (!disconnected) {\n server.emit(event);\n }\n },\n onWorkStateChange: (quiescent) =>\n verifiedOwnership.observeLocalQuiescence(quiescent),\n });\n });\n })();\n }\n await initializing;\n if (!runtime || disconnected) {\n throw new ExecutionHostError(\n \"host.disconnected\",\n \"The execution Host is not available.\"\n );\n }\n return runtime.snapshot();\n },\n } as ExecutionHostHandlers;\n\n // Each concrete method is still decoded by the shared method table at both\n // ends; the forwarding bridge cannot select a new account or mutate identity.\n for (const method of Object.keys(serviceExecutionHostMethods) as Array<\n keyof ExecutionHostHandlers\n >) {\n if (method === \"initialize\") {\n continue;\n }\n const target = handlers as unknown as Record<\n string,\n (payload: unknown) => Promise<unknown>\n >;\n target[method] = async (payload) => {\n if (!(runtime && session) || disconnected) {\n throw new ExecutionHostError(\n \"host.not_initialized\",\n \"Initialize this Host through its supervising Service first.\"\n );\n }\n const invoke = runtime.handlers[method] as (value: unknown) => unknown;\n return await withAdmittedServiceSession(\n session,\n async () => await invoke(payload)\n );\n };\n }\n\n const server = serveExecutionHost({\n channel,\n hostInstanceId,\n handlers,\n onFailure: (error) => {\n console.error(\"[openmeld.execution_host.channel_failed]\", error);\n disconnected = true;\n close().catch(() => undefined);\n },\n onDisconnect: () => {\n disconnected = true;\n close().catch(() => undefined);\n },\n });\n return done.promise;\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { H as skillsDir } from "./paths-DSkUuEu3.js";
4
- import { $ as canManageRegistryAgentSkillTargets, et as detectInstalledSkillsAgents, tt as resolveSkillsAgentRegistry } from "./prepare-provider-runtime-DDYaeyRp.js";
5
- import { n as resolveSkillsInstallStates, r as ensureLocalSkills, t as resolveSkillInstallStateForTarget } from "./state-mQWCO2uD.js";
4
+ import { $ as canManageRegistryAgentSkillTargets, et as detectInstalledSkillsAgents, tt as resolveSkillsAgentRegistry } from "./prepare-provider-runtime-DfsSj_N_.js";
5
+ import { n as resolveSkillsInstallStates, r as ensureLocalSkills, t as resolveSkillInstallStateForTarget } from "./state-CdSbKM0J.js";
6
6
  import { T as updateConfiguredSkillsConfig, g as getConfiguredSkillsConfig, y as resolveRuntimeSkillsCustomTargetId } from "./base-url-eck31vC8.js";
7
7
  import { stat } from "node:fs/promises";
8
8
  //#region src/skills/installation-inventory.ts
@@ -240,4 +240,4 @@ function normalizeInstallRecordForCompare(input) {
240
240
  //#endregion
241
241
  export { mergeTargetsByDir as a, summarizeSkillState as c, filterTargetsWithInstalledOpenMeldSkills as i, collectSkillsReadinessSnapshot as n, persistDetectedInstallStateFromCheck as o, compareInstallRecords as r, resolveTrackedInstallTargets as s, buildAgentTargets as t };
242
242
 
243
- //# sourceMappingURL=installation-inventory-BgZq7fWv.js.map
243
+ //# sourceMappingURL=installation-inventory-DllgoKT1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"installation-inventory-BgZq7fWv.js","names":[],"sources":["../src/skills/installation-inventory.ts"],"sourcesContent":["import { stat } from \"node:fs/promises\";\nimport { skillsDir } from \"../config/paths\";\nimport {\n getConfiguredSkillsConfig,\n type RuntimeSkillsConfig,\n type RuntimeSkillsCustomTarget,\n type RuntimeSkillsInstallRecord,\n resolveRuntimeSkillsCustomTargetId,\n updateConfiguredSkillsConfig,\n} from \"../config/runtime-config\";\nimport {\n canManageRegistryAgentSkillTargets,\n detectInstalledSkillsAgents,\n resolveSkillsAgentRegistry,\n} from \"./agents\";\nimport type { SkillsInstallTarget } from \"./installer\";\nimport {\n resolveSkillInstallStateForTarget,\n resolveSkillsInstallStates,\n type SkillInstallStateResult,\n} from \"./state\";\nimport { ensureLocalSkills, type LocalSkill } from \"./store\";\n\nexport type SkillsReadinessSnapshot = {\n status: \"up_to_date\" | \"action_required\" | \"no_targets\";\n targetCount: number;\n summary: {\n upToDate: number;\n outdated: number;\n missing: number;\n externalConflict: number;\n };\n};\n\nexport async function collectSkillsReadinessSnapshot(): Promise<SkillsReadinessSnapshot> {\n const skillsConfig = await getConfiguredSkillsConfig();\n const registry = resolveSkillsAgentRegistry(skillsConfig);\n const installedAgents = await detectInstalledSkillsAgents(registry);\n const localSkills = await ensureLocalSkills();\n const detectedAgentTargets = buildAgentTargets(installedAgents, registry);\n const trackedTargets = await resolveTrackedInstallTargets({\n skillsConfig,\n registry,\n localSkills,\n onlyOpenMeldInstalledTargets: false,\n });\n const checkTargets = mergeTargetsByDir({\n primary: detectedAgentTargets,\n secondary: trackedTargets,\n });\n const states = await resolveSkillsInstallStates({\n skills: localSkills,\n targets: checkTargets,\n });\n await persistDetectedInstallStateFromCheck({ states });\n const summary = summarizeSkillState(states);\n const hasIssues =\n summary.outdated > 0 || summary.missing > 0 || summary.externalConflict > 0;\n let status: SkillsReadinessSnapshot[\"status\"] = \"up_to_date\";\n if (checkTargets.length === 0) {\n status = \"no_targets\";\n } else if (hasIssues) {\n status = \"action_required\";\n }\n return {\n status,\n targetCount: checkTargets.length,\n summary,\n };\n}\n\nexport function buildAgentTargets(\n agents: string[],\n registry: ReturnType<typeof resolveSkillsAgentRegistry>\n): SkillsInstallTarget[] {\n return agents.flatMap((agentName) => {\n const config = registry[agentName];\n if (!config?.globalSkillsDir || config.skillsInstallable !== true) {\n return [];\n }\n return [\n {\n id: agentName,\n dir: config.globalSkillsDir,\n type: \"agent\" as const,\n },\n ];\n });\n}\n\nfunction isLikelyCustomTargetId(value: string): boolean {\n return value.startsWith(\"custom-\");\n}\n\nexport function resolveTrackedInstallTargets(input: {\n skillsConfig: RuntimeSkillsConfig | null;\n registry: ReturnType<typeof resolveSkillsAgentRegistry>;\n localSkills: LocalSkill[];\n onlyOpenMeldInstalledTargets: boolean;\n}): Promise<SkillsInstallTarget[]> {\n const installs = input.skillsConfig?.installs ?? [];\n const customTargets = input.skillsConfig?.customTargets ?? [];\n const customTargetByDir = buildCustomTargetByDir(customTargets);\n const byTargetDir = new Map<string, SkillsInstallTarget>();\n seedTrackedTargetsFromCustomTargets({\n byTargetDir,\n customTargetByDir,\n });\n seedTrackedTargetsFromInstallRecords({\n byTargetDir,\n installs,\n registry: input.registry,\n customTargetByDir,\n });\n\n const candidates = sortTrackedTargets([...byTargetDir.values()]);\n const allowRegistryDefaults = canManageRegistryAgentSkillTargets();\n const laneSafeCandidates = allowRegistryDefaults\n ? candidates\n : candidates.filter(\n (target) =>\n target.type === \"custom\" ||\n input.registry[target.id]?.globalSkillsDirSource === \"config-override\"\n );\n return filterTrackedTargetsByState({\n candidates: laneSafeCandidates,\n localSkills: input.localSkills,\n onlyOpenMeldInstalledTargets: input.onlyOpenMeldInstalledTargets,\n });\n}\n\nfunction buildCustomTargetByDir(\n customTargets: RuntimeSkillsCustomTarget[]\n): Map<string, RuntimeSkillsCustomTarget> {\n const customTargetByDir = new Map<string, RuntimeSkillsCustomTarget>();\n for (const customTarget of customTargets) {\n const id = resolveRuntimeSkillsCustomTargetId({\n dir: customTarget.dir,\n ...(customTarget.id ? { id: customTarget.id } : {}),\n });\n customTargetByDir.set(customTarget.dir, {\n id,\n name: customTarget.name,\n dir: customTarget.dir,\n });\n }\n return customTargetByDir;\n}\n\nfunction seedTrackedTargetsFromCustomTargets(input: {\n byTargetDir: Map<string, SkillsInstallTarget>;\n customTargetByDir: Map<string, RuntimeSkillsCustomTarget>;\n}): void {\n for (const customTarget of input.customTargetByDir.values()) {\n input.byTargetDir.set(customTarget.dir, {\n id:\n customTarget.id ??\n resolveRuntimeSkillsCustomTargetId({ dir: customTarget.dir }),\n dir: customTarget.dir,\n type: \"custom\",\n });\n }\n}\n\nfunction seedTrackedTargetsFromInstallRecords(input: {\n byTargetDir: Map<string, SkillsInstallTarget>;\n installs: RuntimeSkillsInstallRecord[];\n registry: ReturnType<typeof resolveSkillsAgentRegistry>;\n customTargetByDir: Map<string, RuntimeSkillsCustomTarget>;\n}): void {\n for (const install of input.installs) {\n const trackedTarget = buildTrackedTargetFromInstallRecord({\n install,\n registry: input.registry,\n customTargetByDir: input.customTargetByDir,\n });\n input.byTargetDir.set(install.targetDir, trackedTarget);\n }\n}\n\nfunction buildTrackedTargetFromInstallRecord(input: {\n install: RuntimeSkillsInstallRecord;\n registry: ReturnType<typeof resolveSkillsAgentRegistry>;\n customTargetByDir: Map<string, RuntimeSkillsCustomTarget>;\n}): SkillsInstallTarget {\n const knownAgentDir = input.registry[input.install.targetId]?.globalSkillsDir;\n const targetType: SkillsInstallTarget[\"type\"] =\n knownAgentDir && knownAgentDir === input.install.targetDir\n ? \"agent\"\n : \"custom\";\n if (targetType === \"agent\") {\n return {\n id: input.install.targetId,\n dir: input.install.targetDir,\n type: \"agent\",\n };\n }\n\n const customTarget = input.customTargetByDir.get(input.install.targetDir);\n const fallbackCustomId = isLikelyCustomTargetId(input.install.targetId)\n ? input.install.targetId\n : undefined;\n const resolvedCustomId = customTarget?.id ?? fallbackCustomId;\n return {\n id: resolveRuntimeSkillsCustomTargetId({\n dir: input.install.targetDir,\n ...(resolvedCustomId ? { id: resolvedCustomId } : {}),\n }),\n dir: input.install.targetDir,\n type: \"custom\",\n };\n}\n\nfunction sortTrackedTargets(\n targets: SkillsInstallTarget[]\n): SkillsInstallTarget[] {\n return [...targets].sort((a, b) =>\n `${a.id}:${a.dir}`.localeCompare(`${b.id}:${b.dir}`)\n );\n}\n\nexport function mergeTargetsByDir(input: {\n primary: SkillsInstallTarget[];\n secondary: SkillsInstallTarget[];\n}): SkillsInstallTarget[] {\n const byDir = new Map<string, SkillsInstallTarget>();\n for (const target of input.secondary) {\n byDir.set(target.dir, target);\n }\n for (const target of input.primary) {\n byDir.set(target.dir, target);\n }\n return sortTrackedTargets([...byDir.values()]);\n}\n\nasync function filterInstalledTrackedTargets(input: {\n candidates: SkillsInstallTarget[];\n localSkills: LocalSkill[];\n}): Promise<SkillsInstallTarget[]> {\n const installedOnly: SkillsInstallTarget[] = [];\n for (const candidate of input.candidates) {\n const hasInstalledOpenMeldSkill = await targetHasInstalledOpenMeldSkill({\n target: candidate,\n localSkills: input.localSkills,\n });\n if (!hasInstalledOpenMeldSkill) {\n continue;\n }\n installedOnly.push(candidate);\n }\n return installedOnly;\n}\n\nexport async function filterTargetsWithInstalledOpenMeldSkills(input: {\n targets: SkillsInstallTarget[];\n localSkills: LocalSkill[];\n}): Promise<SkillsInstallTarget[]> {\n const existingTargets = await filterExistingTargetDirs(input.targets);\n return filterInstalledTrackedTargets({\n candidates: existingTargets,\n localSkills: input.localSkills,\n });\n}\n\nasync function filterTrackedTargetsByState(input: {\n candidates: SkillsInstallTarget[];\n localSkills: LocalSkill[];\n onlyOpenMeldInstalledTargets: boolean;\n}): Promise<SkillsInstallTarget[]> {\n const existingTargets = await filterExistingTargetDirs(input.candidates);\n if (!input.onlyOpenMeldInstalledTargets) {\n return existingTargets;\n }\n\n return filterInstalledTrackedTargets({\n candidates: existingTargets,\n localSkills: input.localSkills,\n });\n}\n\nasync function filterExistingTargetDirs(\n candidates: SkillsInstallTarget[]\n): Promise<SkillsInstallTarget[]> {\n const existing: SkillsInstallTarget[] = [];\n for (const candidate of candidates) {\n const targetDirStats = await stat(candidate.dir).catch(() => null);\n if (!targetDirStats?.isDirectory()) {\n continue;\n }\n existing.push(candidate);\n }\n return existing;\n}\n\nexport function summarizeSkillState(states: SkillInstallStateResult[]): {\n upToDate: number;\n outdated: number;\n missing: number;\n externalConflict: number;\n} {\n return {\n upToDate: states.filter((state) => state.state === \"up_to_date\").length,\n outdated: states.filter((state) => state.state === \"outdated\").length,\n missing: states.filter((state) => state.state === \"missing\").length,\n externalConflict: states.filter(\n (state) => state.state === \"external_conflict\"\n ).length,\n };\n}\n\nasync function targetHasInstalledOpenMeldSkill(input: {\n target: SkillsInstallTarget;\n localSkills: LocalSkill[];\n}): Promise<boolean> {\n const targetDirStats = await stat(input.target.dir).catch(() => null);\n if (!targetDirStats?.isDirectory()) {\n return false;\n }\n\n for (const skill of input.localSkills) {\n const state = await resolveSkillInstallStateForTarget({\n skill,\n target: input.target,\n });\n if (state.state === \"up_to_date\" || state.state === \"outdated\") {\n return true;\n }\n }\n\n return false;\n}\n\nexport async function persistDetectedInstallStateFromCheck(input: {\n states: SkillInstallStateResult[];\n}): Promise<void> {\n const discoveredByTargetDir = new Map<string, SkillInstallStateResult[]>();\n for (const state of input.states) {\n if (!(state.state === \"up_to_date\" || state.state === \"outdated\")) {\n continue;\n }\n const list = discoveredByTargetDir.get(state.targetDir) ?? [];\n list.push(state);\n discoveredByTargetDir.set(state.targetDir, list);\n }\n\n if (discoveredByTargetDir.size === 0) {\n return;\n }\n\n await updateConfiguredSkillsConfig((currentSkillsConfig) => {\n const byTargetDir = new Map<string, RuntimeSkillsInstallRecord>();\n for (const record of currentSkillsConfig?.installs ?? []) {\n byTargetDir.set(record.targetDir, record);\n }\n\n const now = new Date().toISOString();\n for (const [targetDir, group] of discoveredByTargetDir) {\n const first = group[0];\n if (!first) {\n continue;\n }\n const mode: RuntimeSkillsInstallRecord[\"mode\"] = group.some(\n (state) => state.targetMode === \"copy\"\n )\n ? \"copy\"\n : \"symlink\";\n const skillIds = Array.from(\n new Set(group.map((state) => state.skillId))\n ).sort((a, b) => a.localeCompare(b));\n\n byTargetDir.set(targetDir, {\n targetId: first.targetId,\n targetDir,\n mode,\n status: \"installed\",\n skillIds,\n updatedAt: now,\n });\n }\n\n const nextInstalls = [...byTargetDir.values()].sort(compareInstallRecords);\n const previousInstalls = [...(currentSkillsConfig?.installs ?? [])]\n .sort(compareInstallRecords)\n .map(normalizeInstallRecordForCompare);\n const nextComparable = nextInstalls.map(normalizeInstallRecordForCompare);\n if (JSON.stringify(previousInstalls) === JSON.stringify(nextComparable)) {\n return currentSkillsConfig;\n }\n\n return {\n storeDir: currentSkillsConfig?.storeDir ?? skillsDir(),\n ...(currentSkillsConfig?.agents\n ? { agents: currentSkillsConfig.agents }\n : {}),\n ...(currentSkillsConfig?.customTargets\n ? { customTargets: currentSkillsConfig.customTargets }\n : {}),\n installs: nextInstalls,\n };\n });\n}\n\nexport function compareInstallRecords(\n left: RuntimeSkillsInstallRecord,\n right: RuntimeSkillsInstallRecord\n): number {\n const byTargetId = left.targetId.localeCompare(right.targetId);\n if (byTargetId !== 0) {\n return byTargetId;\n }\n return left.targetDir.localeCompare(right.targetDir);\n}\n\nfunction normalizeInstallRecordForCompare(\n input: RuntimeSkillsInstallRecord\n): Omit<RuntimeSkillsInstallRecord, \"updatedAt\"> {\n return {\n targetId: input.targetId,\n targetDir: input.targetDir,\n mode: input.mode,\n status: input.status,\n skillIds: [...input.skillIds].sort((a, b) => a.localeCompare(b)),\n ...(input.reason ? { reason: input.reason } : {}),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"installation-inventory-DllgoKT1.js","names":[],"sources":["../src/skills/installation-inventory.ts"],"sourcesContent":["import { stat } from \"node:fs/promises\";\nimport { skillsDir } from \"../config/paths\";\nimport {\n getConfiguredSkillsConfig,\n type RuntimeSkillsConfig,\n type RuntimeSkillsCustomTarget,\n type RuntimeSkillsInstallRecord,\n resolveRuntimeSkillsCustomTargetId,\n updateConfiguredSkillsConfig,\n} from \"../config/runtime-config\";\nimport {\n canManageRegistryAgentSkillTargets,\n detectInstalledSkillsAgents,\n resolveSkillsAgentRegistry,\n} from \"./agents\";\nimport type { SkillsInstallTarget } from \"./installer\";\nimport {\n resolveSkillInstallStateForTarget,\n resolveSkillsInstallStates,\n type SkillInstallStateResult,\n} from \"./state\";\nimport { ensureLocalSkills, type LocalSkill } from \"./store\";\n\nexport type SkillsReadinessSnapshot = {\n status: \"up_to_date\" | \"action_required\" | \"no_targets\";\n targetCount: number;\n summary: {\n upToDate: number;\n outdated: number;\n missing: number;\n externalConflict: number;\n };\n};\n\nexport async function collectSkillsReadinessSnapshot(): Promise<SkillsReadinessSnapshot> {\n const skillsConfig = await getConfiguredSkillsConfig();\n const registry = resolveSkillsAgentRegistry(skillsConfig);\n const installedAgents = await detectInstalledSkillsAgents(registry);\n const localSkills = await ensureLocalSkills();\n const detectedAgentTargets = buildAgentTargets(installedAgents, registry);\n const trackedTargets = await resolveTrackedInstallTargets({\n skillsConfig,\n registry,\n localSkills,\n onlyOpenMeldInstalledTargets: false,\n });\n const checkTargets = mergeTargetsByDir({\n primary: detectedAgentTargets,\n secondary: trackedTargets,\n });\n const states = await resolveSkillsInstallStates({\n skills: localSkills,\n targets: checkTargets,\n });\n await persistDetectedInstallStateFromCheck({ states });\n const summary = summarizeSkillState(states);\n const hasIssues =\n summary.outdated > 0 || summary.missing > 0 || summary.externalConflict > 0;\n let status: SkillsReadinessSnapshot[\"status\"] = \"up_to_date\";\n if (checkTargets.length === 0) {\n status = \"no_targets\";\n } else if (hasIssues) {\n status = \"action_required\";\n }\n return {\n status,\n targetCount: checkTargets.length,\n summary,\n };\n}\n\nexport function buildAgentTargets(\n agents: string[],\n registry: ReturnType<typeof resolveSkillsAgentRegistry>\n): SkillsInstallTarget[] {\n return agents.flatMap((agentName) => {\n const config = registry[agentName];\n if (!config?.globalSkillsDir || config.skillsInstallable !== true) {\n return [];\n }\n return [\n {\n id: agentName,\n dir: config.globalSkillsDir,\n type: \"agent\" as const,\n },\n ];\n });\n}\n\nfunction isLikelyCustomTargetId(value: string): boolean {\n return value.startsWith(\"custom-\");\n}\n\nexport function resolveTrackedInstallTargets(input: {\n skillsConfig: RuntimeSkillsConfig | null;\n registry: ReturnType<typeof resolveSkillsAgentRegistry>;\n localSkills: LocalSkill[];\n onlyOpenMeldInstalledTargets: boolean;\n}): Promise<SkillsInstallTarget[]> {\n const installs = input.skillsConfig?.installs ?? [];\n const customTargets = input.skillsConfig?.customTargets ?? [];\n const customTargetByDir = buildCustomTargetByDir(customTargets);\n const byTargetDir = new Map<string, SkillsInstallTarget>();\n seedTrackedTargetsFromCustomTargets({\n byTargetDir,\n customTargetByDir,\n });\n seedTrackedTargetsFromInstallRecords({\n byTargetDir,\n installs,\n registry: input.registry,\n customTargetByDir,\n });\n\n const candidates = sortTrackedTargets([...byTargetDir.values()]);\n const allowRegistryDefaults = canManageRegistryAgentSkillTargets();\n const laneSafeCandidates = allowRegistryDefaults\n ? candidates\n : candidates.filter(\n (target) =>\n target.type === \"custom\" ||\n input.registry[target.id]?.globalSkillsDirSource === \"config-override\"\n );\n return filterTrackedTargetsByState({\n candidates: laneSafeCandidates,\n localSkills: input.localSkills,\n onlyOpenMeldInstalledTargets: input.onlyOpenMeldInstalledTargets,\n });\n}\n\nfunction buildCustomTargetByDir(\n customTargets: RuntimeSkillsCustomTarget[]\n): Map<string, RuntimeSkillsCustomTarget> {\n const customTargetByDir = new Map<string, RuntimeSkillsCustomTarget>();\n for (const customTarget of customTargets) {\n const id = resolveRuntimeSkillsCustomTargetId({\n dir: customTarget.dir,\n ...(customTarget.id ? { id: customTarget.id } : {}),\n });\n customTargetByDir.set(customTarget.dir, {\n id,\n name: customTarget.name,\n dir: customTarget.dir,\n });\n }\n return customTargetByDir;\n}\n\nfunction seedTrackedTargetsFromCustomTargets(input: {\n byTargetDir: Map<string, SkillsInstallTarget>;\n customTargetByDir: Map<string, RuntimeSkillsCustomTarget>;\n}): void {\n for (const customTarget of input.customTargetByDir.values()) {\n input.byTargetDir.set(customTarget.dir, {\n id:\n customTarget.id ??\n resolveRuntimeSkillsCustomTargetId({ dir: customTarget.dir }),\n dir: customTarget.dir,\n type: \"custom\",\n });\n }\n}\n\nfunction seedTrackedTargetsFromInstallRecords(input: {\n byTargetDir: Map<string, SkillsInstallTarget>;\n installs: RuntimeSkillsInstallRecord[];\n registry: ReturnType<typeof resolveSkillsAgentRegistry>;\n customTargetByDir: Map<string, RuntimeSkillsCustomTarget>;\n}): void {\n for (const install of input.installs) {\n const trackedTarget = buildTrackedTargetFromInstallRecord({\n install,\n registry: input.registry,\n customTargetByDir: input.customTargetByDir,\n });\n input.byTargetDir.set(install.targetDir, trackedTarget);\n }\n}\n\nfunction buildTrackedTargetFromInstallRecord(input: {\n install: RuntimeSkillsInstallRecord;\n registry: ReturnType<typeof resolveSkillsAgentRegistry>;\n customTargetByDir: Map<string, RuntimeSkillsCustomTarget>;\n}): SkillsInstallTarget {\n const knownAgentDir = input.registry[input.install.targetId]?.globalSkillsDir;\n const targetType: SkillsInstallTarget[\"type\"] =\n knownAgentDir && knownAgentDir === input.install.targetDir\n ? \"agent\"\n : \"custom\";\n if (targetType === \"agent\") {\n return {\n id: input.install.targetId,\n dir: input.install.targetDir,\n type: \"agent\",\n };\n }\n\n const customTarget = input.customTargetByDir.get(input.install.targetDir);\n const fallbackCustomId = isLikelyCustomTargetId(input.install.targetId)\n ? input.install.targetId\n : undefined;\n const resolvedCustomId = customTarget?.id ?? fallbackCustomId;\n return {\n id: resolveRuntimeSkillsCustomTargetId({\n dir: input.install.targetDir,\n ...(resolvedCustomId ? { id: resolvedCustomId } : {}),\n }),\n dir: input.install.targetDir,\n type: \"custom\",\n };\n}\n\nfunction sortTrackedTargets(\n targets: SkillsInstallTarget[]\n): SkillsInstallTarget[] {\n return [...targets].sort((a, b) =>\n `${a.id}:${a.dir}`.localeCompare(`${b.id}:${b.dir}`)\n );\n}\n\nexport function mergeTargetsByDir(input: {\n primary: SkillsInstallTarget[];\n secondary: SkillsInstallTarget[];\n}): SkillsInstallTarget[] {\n const byDir = new Map<string, SkillsInstallTarget>();\n for (const target of input.secondary) {\n byDir.set(target.dir, target);\n }\n for (const target of input.primary) {\n byDir.set(target.dir, target);\n }\n return sortTrackedTargets([...byDir.values()]);\n}\n\nasync function filterInstalledTrackedTargets(input: {\n candidates: SkillsInstallTarget[];\n localSkills: LocalSkill[];\n}): Promise<SkillsInstallTarget[]> {\n const installedOnly: SkillsInstallTarget[] = [];\n for (const candidate of input.candidates) {\n const hasInstalledOpenMeldSkill = await targetHasInstalledOpenMeldSkill({\n target: candidate,\n localSkills: input.localSkills,\n });\n if (!hasInstalledOpenMeldSkill) {\n continue;\n }\n installedOnly.push(candidate);\n }\n return installedOnly;\n}\n\nexport async function filterTargetsWithInstalledOpenMeldSkills(input: {\n targets: SkillsInstallTarget[];\n localSkills: LocalSkill[];\n}): Promise<SkillsInstallTarget[]> {\n const existingTargets = await filterExistingTargetDirs(input.targets);\n return filterInstalledTrackedTargets({\n candidates: existingTargets,\n localSkills: input.localSkills,\n });\n}\n\nasync function filterTrackedTargetsByState(input: {\n candidates: SkillsInstallTarget[];\n localSkills: LocalSkill[];\n onlyOpenMeldInstalledTargets: boolean;\n}): Promise<SkillsInstallTarget[]> {\n const existingTargets = await filterExistingTargetDirs(input.candidates);\n if (!input.onlyOpenMeldInstalledTargets) {\n return existingTargets;\n }\n\n return filterInstalledTrackedTargets({\n candidates: existingTargets,\n localSkills: input.localSkills,\n });\n}\n\nasync function filterExistingTargetDirs(\n candidates: SkillsInstallTarget[]\n): Promise<SkillsInstallTarget[]> {\n const existing: SkillsInstallTarget[] = [];\n for (const candidate of candidates) {\n const targetDirStats = await stat(candidate.dir).catch(() => null);\n if (!targetDirStats?.isDirectory()) {\n continue;\n }\n existing.push(candidate);\n }\n return existing;\n}\n\nexport function summarizeSkillState(states: SkillInstallStateResult[]): {\n upToDate: number;\n outdated: number;\n missing: number;\n externalConflict: number;\n} {\n return {\n upToDate: states.filter((state) => state.state === \"up_to_date\").length,\n outdated: states.filter((state) => state.state === \"outdated\").length,\n missing: states.filter((state) => state.state === \"missing\").length,\n externalConflict: states.filter(\n (state) => state.state === \"external_conflict\"\n ).length,\n };\n}\n\nasync function targetHasInstalledOpenMeldSkill(input: {\n target: SkillsInstallTarget;\n localSkills: LocalSkill[];\n}): Promise<boolean> {\n const targetDirStats = await stat(input.target.dir).catch(() => null);\n if (!targetDirStats?.isDirectory()) {\n return false;\n }\n\n for (const skill of input.localSkills) {\n const state = await resolveSkillInstallStateForTarget({\n skill,\n target: input.target,\n });\n if (state.state === \"up_to_date\" || state.state === \"outdated\") {\n return true;\n }\n }\n\n return false;\n}\n\nexport async function persistDetectedInstallStateFromCheck(input: {\n states: SkillInstallStateResult[];\n}): Promise<void> {\n const discoveredByTargetDir = new Map<string, SkillInstallStateResult[]>();\n for (const state of input.states) {\n if (!(state.state === \"up_to_date\" || state.state === \"outdated\")) {\n continue;\n }\n const list = discoveredByTargetDir.get(state.targetDir) ?? [];\n list.push(state);\n discoveredByTargetDir.set(state.targetDir, list);\n }\n\n if (discoveredByTargetDir.size === 0) {\n return;\n }\n\n await updateConfiguredSkillsConfig((currentSkillsConfig) => {\n const byTargetDir = new Map<string, RuntimeSkillsInstallRecord>();\n for (const record of currentSkillsConfig?.installs ?? []) {\n byTargetDir.set(record.targetDir, record);\n }\n\n const now = new Date().toISOString();\n for (const [targetDir, group] of discoveredByTargetDir) {\n const first = group[0];\n if (!first) {\n continue;\n }\n const mode: RuntimeSkillsInstallRecord[\"mode\"] = group.some(\n (state) => state.targetMode === \"copy\"\n )\n ? \"copy\"\n : \"symlink\";\n const skillIds = Array.from(\n new Set(group.map((state) => state.skillId))\n ).sort((a, b) => a.localeCompare(b));\n\n byTargetDir.set(targetDir, {\n targetId: first.targetId,\n targetDir,\n mode,\n status: \"installed\",\n skillIds,\n updatedAt: now,\n });\n }\n\n const nextInstalls = [...byTargetDir.values()].sort(compareInstallRecords);\n const previousInstalls = [...(currentSkillsConfig?.installs ?? [])]\n .sort(compareInstallRecords)\n .map(normalizeInstallRecordForCompare);\n const nextComparable = nextInstalls.map(normalizeInstallRecordForCompare);\n if (JSON.stringify(previousInstalls) === JSON.stringify(nextComparable)) {\n return currentSkillsConfig;\n }\n\n return {\n storeDir: currentSkillsConfig?.storeDir ?? skillsDir(),\n ...(currentSkillsConfig?.agents\n ? { agents: currentSkillsConfig.agents }\n : {}),\n ...(currentSkillsConfig?.customTargets\n ? { customTargets: currentSkillsConfig.customTargets }\n : {}),\n installs: nextInstalls,\n };\n });\n}\n\nexport function compareInstallRecords(\n left: RuntimeSkillsInstallRecord,\n right: RuntimeSkillsInstallRecord\n): number {\n const byTargetId = left.targetId.localeCompare(right.targetId);\n if (byTargetId !== 0) {\n return byTargetId;\n }\n return left.targetDir.localeCompare(right.targetDir);\n}\n\nfunction normalizeInstallRecordForCompare(\n input: RuntimeSkillsInstallRecord\n): Omit<RuntimeSkillsInstallRecord, \"updatedAt\"> {\n return {\n targetId: input.targetId,\n targetDir: input.targetDir,\n mode: input.mode,\n status: input.status,\n skillIds: [...input.skillIds].sort((a, b) => a.localeCompare(b)),\n ...(input.reason ? { reason: input.reason } : {}),\n };\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { c as replaceSkillDirectory, f as withSkillsInstallLock, o as writeOpenMeldSkillMarker, s as recoverSkillReplacement, t as resolveSkillInstallStateForTarget } from "./state-mQWCO2uD.js";
3
+ import { c as replaceSkillDirectory, f as withSkillsInstallLock, o as writeOpenMeldSkillMarker, s as recoverSkillReplacement, t as resolveSkillInstallStateForTarget } from "./state-CdSbKM0J.js";
4
4
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
5
5
  import { cp, mkdir, readFile, realpath, symlink } from "node:fs/promises";
6
6
  import process from "node:process";
@@ -122,4 +122,4 @@ async function tryCreateSymlink(input) {
122
122
  //#endregion
123
123
  export { installSkillsToTargets as t };
124
124
 
125
- //# sourceMappingURL=installer-DxU4S_WH.js.map
125
+ //# sourceMappingURL=installer-Sc79LhuA.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"installer-DxU4S_WH.js","names":[],"sources":["../src/skills/installer.ts"],"sourcesContent":["import { cp, mkdir, readFile, realpath, symlink } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport process from \"node:process\";\nimport { withSkillsInstallLock } from \"./install-lock\";\n\n// biome-ignore lint/performance/noBarrelFile: Keep the existing installer lock API while the source store shares its owner.\nexport { withSkillsInstallLock } from \"./install-lock\";\n\nimport {\n recoverSkillReplacement,\n replaceSkillDirectory,\n} from \"./replace-directory\";\nimport type { SkillInstallStateResult } from \"./state\";\nimport { resolveSkillInstallStateForTarget } from \"./state\";\nimport type { LocalSkill } from \"./store\";\nimport { writeOpenMeldSkillMarker } from \"./store\";\n\nexport type SkillsInstallMode = \"symlink\" | \"copy\" | \"unknown\";\nexport type SkillsInstallStatus = \"installed\" | \"skipped\" | \"failed\";\n\nexport type SkillsInstallTarget = {\n id: string;\n dir: string;\n type: \"agent\" | \"custom\";\n};\n\nexport type SkillsInstallResult = {\n targetId: string;\n targetDir: string;\n targetType: \"agent\" | \"custom\";\n skillId: string;\n status: SkillsInstallStatus;\n mode: SkillsInstallMode;\n degraded: boolean;\n reason?: string;\n};\n\nexport function installSkillsToTargets(input: {\n skills: LocalSkill[];\n targets: SkillsInstallTarget[];\n}): Promise<SkillsInstallResult[]> {\n return withSkillsInstallLock(() => installSkillsToTargetsLocked(input));\n}\n\nasync function installSkillsToTargetsLocked(input: {\n skills: LocalSkill[];\n targets: SkillsInstallTarget[];\n}): Promise<SkillsInstallResult[]> {\n const results: SkillsInstallResult[] = [];\n\n for (const target of input.targets) {\n for (const skill of input.skills) {\n const result = await installOneSkillToTarget({\n skill,\n target,\n });\n results.push(result);\n }\n }\n\n return results;\n}\n\nasync function installOneSkillToTarget(input: {\n skill: LocalSkill;\n target: SkillsInstallTarget;\n}): Promise<SkillsInstallResult> {\n const targetDir = input.target.dir;\n const failInstall = (reason: string): SkillsInstallResult => ({\n targetId: input.target.id,\n targetDir,\n targetType: input.target.type,\n skillId: input.skill.id,\n status: \"failed\",\n mode: \"unknown\",\n degraded: false,\n reason,\n });\n\n if (!isAbsolute(targetDir)) {\n return failInstall(\"target dir must be an absolute path\");\n }\n\n const skillId = input.skill.id;\n if (\n skillId.trim().length === 0 ||\n isAbsolute(skillId) ||\n skillId === \".\" ||\n skillId === \"..\" ||\n skillId.includes(\"/\") ||\n skillId.includes(\"\\\\\")\n ) {\n return failInstall(\"skill id would escape target dir\");\n }\n\n const resolvedTargetDir = resolve(targetDir);\n const resolvedSkillDir = resolve(resolvedTargetDir, skillId);\n const skillRelativePath = relative(resolvedTargetDir, resolvedSkillDir);\n if (\n skillRelativePath === \"..\" ||\n skillRelativePath.startsWith(\"../\") ||\n skillRelativePath.startsWith(\"..\\\\\")\n ) {\n return failInstall(\"skill id would escape target dir\");\n }\n\n const skillTargetDir = resolvedSkillDir;\n\n await mkdir(targetDir, { recursive: true });\n await recoverSkillReplacement(skillTargetDir);\n const state = await resolveSkillInstallStateForTarget({\n skill: input.skill,\n target: input.target,\n });\n if (state.state === \"external_conflict\") {\n return {\n targetId: input.target.id,\n targetDir,\n targetType: input.target.type,\n skillId: input.skill.id,\n status: \"skipped\",\n mode: resolveSkippedInstallMode(state),\n degraded: false,\n reason: state.reason,\n };\n }\n\n if (state.state === \"up_to_date\") {\n return {\n targetId: input.target.id,\n targetDir,\n targetType: input.target.type,\n skillId: input.skill.id,\n status: \"skipped\",\n mode: resolveSkippedInstallMode(state),\n degraded: false,\n reason: state.reason,\n };\n }\n\n const installation: { mode: SkillsInstallMode } = { mode: \"symlink\" };\n try {\n await readFile(join(input.skill.absolutePath, \"SKILL.md\"), \"utf8\");\n await replaceSkillDirectory(skillTargetDir, async (stagedDir) => {\n const symlinked = await tryCreateSymlink({\n sourceDir: input.skill.absolutePath,\n targetDir: stagedDir,\n });\n if (symlinked) {\n return;\n }\n installation.mode = \"copy\";\n await cp(input.skill.absolutePath, stagedDir, {\n recursive: true,\n errorOnExist: true,\n force: false,\n });\n await writeOpenMeldSkillMarker({\n skillDir: stagedDir,\n skillId: input.skill.id,\n mode: \"copy\",\n ...(input.skill.contentHash\n ? { contentHash: input.skill.contentHash }\n : {}),\n ...(input.skill.version ? { version: input.skill.version } : {}),\n });\n });\n return {\n targetId: input.target.id,\n targetDir,\n targetType: input.target.type,\n skillId: input.skill.id,\n status: \"installed\",\n mode: installation.mode,\n degraded: installation.mode === \"copy\",\n ...(installation.mode === \"copy\"\n ? { reason: \"symlink failed; fell back to copy\" }\n : {}),\n };\n } catch (error) {\n return failInstall(\n error instanceof Error\n ? error.message\n : \"failed to install skill to target\"\n );\n }\n}\n\nfunction resolveSkippedInstallMode(\n state: SkillInstallStateResult\n): SkillsInstallMode {\n if (state.targetMode === \"copy\") {\n return \"copy\";\n }\n if (state.targetMode === \"symlink\") {\n return \"symlink\";\n }\n return \"unknown\";\n}\n\nasync function tryCreateSymlink(input: {\n sourceDir: string;\n targetDir: string;\n}): Promise<boolean> {\n try {\n await mkdir(dirname(input.targetDir), { recursive: true });\n\n const targetParentDir = dirname(input.targetDir);\n const resolvedTargetParentDir = await realpath(targetParentDir).catch(\n () => targetParentDir\n );\n const resolvedSourceDir = await realpath(input.sourceDir).catch(\n () => input.sourceDir\n );\n const relativeTarget = relative(resolvedTargetParentDir, resolvedSourceDir);\n await symlink(\n process.platform === \"win32\" ? resolvedSourceDir : relativeTarget,\n input.targetDir,\n process.platform === \"win32\" ? \"junction\" : undefined\n );\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"installer-Sc79LhuA.js","names":[],"sources":["../src/skills/installer.ts"],"sourcesContent":["import { cp, mkdir, readFile, realpath, symlink } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport process from \"node:process\";\nimport { withSkillsInstallLock } from \"./install-lock\";\n\n// biome-ignore lint/performance/noBarrelFile: Keep the existing installer lock API while the source store shares its owner.\nexport { withSkillsInstallLock } from \"./install-lock\";\n\nimport {\n recoverSkillReplacement,\n replaceSkillDirectory,\n} from \"./replace-directory\";\nimport type { SkillInstallStateResult } from \"./state\";\nimport { resolveSkillInstallStateForTarget } from \"./state\";\nimport type { LocalSkill } from \"./store\";\nimport { writeOpenMeldSkillMarker } from \"./store\";\n\nexport type SkillsInstallMode = \"symlink\" | \"copy\" | \"unknown\";\nexport type SkillsInstallStatus = \"installed\" | \"skipped\" | \"failed\";\n\nexport type SkillsInstallTarget = {\n id: string;\n dir: string;\n type: \"agent\" | \"custom\";\n};\n\nexport type SkillsInstallResult = {\n targetId: string;\n targetDir: string;\n targetType: \"agent\" | \"custom\";\n skillId: string;\n status: SkillsInstallStatus;\n mode: SkillsInstallMode;\n degraded: boolean;\n reason?: string;\n};\n\nexport function installSkillsToTargets(input: {\n skills: LocalSkill[];\n targets: SkillsInstallTarget[];\n}): Promise<SkillsInstallResult[]> {\n return withSkillsInstallLock(() => installSkillsToTargetsLocked(input));\n}\n\nasync function installSkillsToTargetsLocked(input: {\n skills: LocalSkill[];\n targets: SkillsInstallTarget[];\n}): Promise<SkillsInstallResult[]> {\n const results: SkillsInstallResult[] = [];\n\n for (const target of input.targets) {\n for (const skill of input.skills) {\n const result = await installOneSkillToTarget({\n skill,\n target,\n });\n results.push(result);\n }\n }\n\n return results;\n}\n\nasync function installOneSkillToTarget(input: {\n skill: LocalSkill;\n target: SkillsInstallTarget;\n}): Promise<SkillsInstallResult> {\n const targetDir = input.target.dir;\n const failInstall = (reason: string): SkillsInstallResult => ({\n targetId: input.target.id,\n targetDir,\n targetType: input.target.type,\n skillId: input.skill.id,\n status: \"failed\",\n mode: \"unknown\",\n degraded: false,\n reason,\n });\n\n if (!isAbsolute(targetDir)) {\n return failInstall(\"target dir must be an absolute path\");\n }\n\n const skillId = input.skill.id;\n if (\n skillId.trim().length === 0 ||\n isAbsolute(skillId) ||\n skillId === \".\" ||\n skillId === \"..\" ||\n skillId.includes(\"/\") ||\n skillId.includes(\"\\\\\")\n ) {\n return failInstall(\"skill id would escape target dir\");\n }\n\n const resolvedTargetDir = resolve(targetDir);\n const resolvedSkillDir = resolve(resolvedTargetDir, skillId);\n const skillRelativePath = relative(resolvedTargetDir, resolvedSkillDir);\n if (\n skillRelativePath === \"..\" ||\n skillRelativePath.startsWith(\"../\") ||\n skillRelativePath.startsWith(\"..\\\\\")\n ) {\n return failInstall(\"skill id would escape target dir\");\n }\n\n const skillTargetDir = resolvedSkillDir;\n\n await mkdir(targetDir, { recursive: true });\n await recoverSkillReplacement(skillTargetDir);\n const state = await resolveSkillInstallStateForTarget({\n skill: input.skill,\n target: input.target,\n });\n if (state.state === \"external_conflict\") {\n return {\n targetId: input.target.id,\n targetDir,\n targetType: input.target.type,\n skillId: input.skill.id,\n status: \"skipped\",\n mode: resolveSkippedInstallMode(state),\n degraded: false,\n reason: state.reason,\n };\n }\n\n if (state.state === \"up_to_date\") {\n return {\n targetId: input.target.id,\n targetDir,\n targetType: input.target.type,\n skillId: input.skill.id,\n status: \"skipped\",\n mode: resolveSkippedInstallMode(state),\n degraded: false,\n reason: state.reason,\n };\n }\n\n const installation: { mode: SkillsInstallMode } = { mode: \"symlink\" };\n try {\n await readFile(join(input.skill.absolutePath, \"SKILL.md\"), \"utf8\");\n await replaceSkillDirectory(skillTargetDir, async (stagedDir) => {\n const symlinked = await tryCreateSymlink({\n sourceDir: input.skill.absolutePath,\n targetDir: stagedDir,\n });\n if (symlinked) {\n return;\n }\n installation.mode = \"copy\";\n await cp(input.skill.absolutePath, stagedDir, {\n recursive: true,\n errorOnExist: true,\n force: false,\n });\n await writeOpenMeldSkillMarker({\n skillDir: stagedDir,\n skillId: input.skill.id,\n mode: \"copy\",\n ...(input.skill.contentHash\n ? { contentHash: input.skill.contentHash }\n : {}),\n ...(input.skill.version ? { version: input.skill.version } : {}),\n });\n });\n return {\n targetId: input.target.id,\n targetDir,\n targetType: input.target.type,\n skillId: input.skill.id,\n status: \"installed\",\n mode: installation.mode,\n degraded: installation.mode === \"copy\",\n ...(installation.mode === \"copy\"\n ? { reason: \"symlink failed; fell back to copy\" }\n : {}),\n };\n } catch (error) {\n return failInstall(\n error instanceof Error\n ? error.message\n : \"failed to install skill to target\"\n );\n }\n}\n\nfunction resolveSkippedInstallMode(\n state: SkillInstallStateResult\n): SkillsInstallMode {\n if (state.targetMode === \"copy\") {\n return \"copy\";\n }\n if (state.targetMode === \"symlink\") {\n return \"symlink\";\n }\n return \"unknown\";\n}\n\nasync function tryCreateSymlink(input: {\n sourceDir: string;\n targetDir: string;\n}): Promise<boolean> {\n try {\n await mkdir(dirname(input.targetDir), { recursive: true });\n\n const targetParentDir = dirname(input.targetDir);\n const resolvedTargetParentDir = await realpath(targetParentDir).catch(\n () => targetParentDir\n );\n const resolvedSourceDir = await realpath(input.sourceDir).catch(\n () => input.sourceDir\n );\n const relativeTarget = relative(resolvedTargetParentDir, resolvedSourceDir);\n await symlink(\n process.platform === \"win32\" ? resolvedSourceDir : relativeTarget,\n input.targetDir,\n process.platform === \"win32\" ? \"junction\" : undefined\n );\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { f as toSpaceMetaUrl } from "./urls-CY2uzH2-.js";
4
4
  import { F as resolveOpenMeldEnvPreset, w as openMeldManagedBinaryPath } from "./paths-DSkUuEu3.js";
5
5
  import { Bn as toStructuredApiClientFailure, ei as spaceMemberDirectoryEntrySchema, gi as spaceMetaSchema, mn as createSpaceApi, nr as OPENMELD_HEADER_REQUEST_ID, t as OpenMeldApiClientHttpError, yr as gatewayErrorEnvelopeSchema } from "./dist-CAypwFRu.js";
6
6
  import { Jt as SPACE_FILE_MAX_SIZE_BYTES, Q as openMeldSpaceEgressActionSchema, _n as spaceFileNameSchema, in as resolveSpaceFileMimeType, rr as executionContextAssignmentSchema } from "./runtime-transport-D4x8_AmR.js";
7
- import { _n as OPENMELD_DISPATCH_RUNTIME_TARGET_PROFILE_ID_ENV, gn as OPENMELD_DISPATCH_RUNTIME_MODE_ENV, hn as OPENMELD_DISPATCH_RUNTIME_DISPATCH_ID_ENV, pn as DISPATCH_OWNED_RUNTIME_MODE, vn as OPENMELD_SPACE_ACTION_TOOL_COMMAND_PATH_ENV, yn as OPENMELD_USER_FACING_CLI_COMMAND_ENV } from "./daemon-frame-transport-BQR5LfG2.js";
7
+ import { _n as OPENMELD_DISPATCH_RUNTIME_TARGET_PROFILE_ID_ENV, gn as OPENMELD_DISPATCH_RUNTIME_MODE_ENV, hn as OPENMELD_DISPATCH_RUNTIME_DISPATCH_ID_ENV, pn as DISPATCH_OWNED_RUNTIME_MODE, vn as OPENMELD_SPACE_ACTION_TOOL_COMMAND_PATH_ENV, yn as OPENMELD_USER_FACING_CLI_COMMAND_ENV } from "./daemon-frame-transport-xQnNyg6E.js";
8
8
  import { h as isSelfWakeSpaceAction } from "./dist-DFhd6JmQ.js";
9
9
  import { n as resolveOpenMeldDistribution } from "./distribution-BDQT2ilb.js";
10
10
  import { h as daemonRuntimeRootPath } from "./daemon-state-B6G5xe7f.js";
@@ -324,26 +324,29 @@ function buildDispatchOwnedRuntimeEnv(input) {
324
324
  ...input.env ?? {}
325
325
  };
326
326
  const currentPath = normalizeOptionalText$1(input.env?.PATH ?? process.env.PATH);
327
- const shimDir = ensureDispatchOwnedRuntimeCliShims({
327
+ const actionCommand = resolveDispatchOwnedRuntimeActionCliEntryCommand({ env });
328
+ const actionCommandPath = (input.platform ?? process.platform) === "win32" && (input.distribution ?? resolveOpenMeldDistribution()) === "binary" ? resolveDispatchOwnedRuntimeBinaryCliEntryPath({
329
+ cliEntryPath: input.cliEntryPath,
330
+ env
331
+ }) : join(ensureDispatchOwnedRuntimeCliShims({
328
332
  cliEntryPath: input.cliEntryPath,
329
333
  dispatchId: input.dispatchId,
330
334
  distribution: input.distribution,
331
335
  env,
332
336
  spaceActionContextPath: input.spaceActionContextPath,
333
337
  targetProfileId: input.targetProfileId
334
- });
335
- const actionCommand = resolveDispatchOwnedRuntimeActionCliEntryCommand({ env });
338
+ }), actionCommand);
336
339
  return {
337
340
  ...env,
338
341
  PATH: prependPathEntry({
339
342
  currentPath,
340
- nextEntry: shimDir
343
+ nextEntry: dirname(actionCommandPath)
341
344
  }),
342
345
  [OPENMELD_DISPATCH_RUNTIME_MODE_ENV]: DISPATCH_OWNED_RUNTIME_MODE,
343
346
  [OPENMELD_DISPATCH_RUNTIME_DISPATCH_ID_ENV]: input.dispatchId,
344
347
  [OPENMELD_DISPATCH_RUNTIME_TARGET_PROFILE_ID_ENV]: input.targetProfileId,
345
348
  [OPENMELD_USER_FACING_CLI_COMMAND_ENV]: actionCommand,
346
- [OPENMELD_SPACE_ACTION_TOOL_COMMAND_PATH_ENV]: join(shimDir, actionCommand),
349
+ [OPENMELD_SPACE_ACTION_TOOL_COMMAND_PATH_ENV]: actionCommandPath,
347
350
  [OPENMELD_ENV_PRESET_ENV]: resolveDispatchOwnedRuntimeEnvPreset({ env }),
348
351
  ...input.spaceActionContextPath ? { [OPENMELD_SPACE_ACTION_CONTEXT_PATH_ENV]: input.spaceActionContextPath } : {}
349
352
  };
@@ -839,4 +842,4 @@ async function updateSpaceMeta(input) {
839
842
  //#endregion
840
843
  export { supersedeDispatchSpaceActionRecordForReconsideration as C, readDispatchSpaceActionRecord as S, DispatchSpaceActionRejectedError as _, GatewayHttpError as a, readDispatchSpaceActionContextForReceiptFromEnv as b, toStructuredGatewayFailure as c, uploadPreparedSpaceFiles as d, createCliSpaceApi as f, DispatchSpaceActionClosedError as g, readDispatchOwnedRuntimeGuard as h, parseSpaceMetaResponse as i, parseJsonResponse as l, buildDispatchOwnedRuntimeEnv as m, updateSpaceMeta as n, readGatewayJsonResponse as o, assertDispatchOwnedRuntimePublicWriteAllowed as p, parseSpaceMetaPayload as r, readGatewayTextResponse as s, fetchSpaceMeta as t, prepareRequestedSpaceSendFiles as u, OPENMELD_SPACE_ACTION_CONTEXT_PATH_ENV as v, writeDispatchSpaceActionRecord as w, readDispatchSpaceActionContextFromEnv as x, createDispatchSpaceActionContext as y };
841
844
 
842
- //# sourceMappingURL=meta-api-D0nhhSY7.js.map
845
+ //# sourceMappingURL=meta-api-CEw8eOeN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-api-CEw8eOeN.js","names":["normalizeOptionalText","normalizeOptionalText","record"],"sources":["../src/runtime/dispatch-space-action-context.ts","../src/runtime/dispatch-owned-runtime.ts","../src/space/cli-space-api.ts","../src/space/send-files.ts","../src/space/api-json.ts","../src/space/gateway-response.ts","../src/space/space-meta-response.ts","../src/space/meta-api.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n writeFileSync,\n} from \"node:fs\";\nimport { isAbsolute, join } from \"node:path\";\nimport { isDeepStrictEqual } from \"node:util\";\nimport {\n executionContextAssignmentSchema,\n openMeldSpaceEgressActionSchema,\n spaceMemberDirectoryEntrySchema,\n} from \"@openmeld/schemas\";\nimport type {\n DispatchSpaceActionClosedReasonCode,\n DispatchSpaceActionReceipt,\n OpenMeldSpaceEgressAction,\n SpaceContract,\n SpaceMemberDirectoryEntry,\n} from \"@openmeld/schemas/types\";\nimport { isSelfWakeSpaceAction } from \"@openmeld/space-mesh\";\nimport { daemonRuntimeRootPath } from \"../config/daemon-state\";\nimport type { OpenMeldPathResolutionInput } from \"../config/paths\";\nimport {\n DISPATCH_OWNED_RUNTIME_MODE,\n OPENMELD_DISPATCH_RUNTIME_DISPATCH_ID_ENV,\n OPENMELD_DISPATCH_RUNTIME_MODE_ENV,\n OPENMELD_DISPATCH_RUNTIME_TARGET_PROFILE_ID_ENV,\n} from \"./dispatch-runtime-env\";\n\nexport const OPENMELD_SPACE_ACTION_CONTEXT_PATH_ENV =\n \"OPENMELD_SPACE_ACTION_CONTEXT_PATH\";\n\n/** The local action context is known expired/closed/mismatched: a new ordinary action must be rejected, never recorded. */\nexport class DispatchSpaceActionClosedError extends Error {\n readonly receipt = \"rejected_closed\" as const;\n readonly reasonCode: DispatchSpaceActionClosedReasonCode;\n constructor(\n reasonCode: DispatchSpaceActionClosedReasonCode,\n message: string\n ) {\n super(message);\n this.name = \"DispatchSpaceActionClosedError\";\n this.reasonCode = reasonCode;\n }\n}\n\n/** Use only at a boundary that has positively rejected this call before recording. */\nexport class DispatchSpaceActionRejectedError extends Error {\n readonly reasonCode: Extract<\n DispatchSpaceActionReceipt,\n { status: \"rejected_before_recording\" }\n >[\"reasonCode\"];\n\n constructor(\n reasonCode: DispatchSpaceActionRejectedError[\"reasonCode\"],\n message: string\n ) {\n super(message);\n this.name = \"DispatchSpaceActionRejectedError\";\n this.reasonCode = reasonCode;\n }\n}\n\nconst DISPATCH_SPACE_ACTION_CONTEXT_VERSION = 1 as const;\nconst DISPATCH_SPACE_ACTION_RECORD_VERSION = 1 as const;\nconst DEFAULT_CONTEXT_TTL_MS = 12 * 60 * 60 * 1000;\n\nexport type DispatchSpaceActionSendTargetReference =\n | {\n status: \"loaded\";\n projection: SpaceMemberDirectoryEntry[];\n referenceLines: string[];\n }\n | {\n status: \"failed\";\n errorMessage: string;\n projection: null;\n referenceLines: [];\n };\n\nexport type DispatchSpaceActionContext = {\n projectShell?: {\n boundaryRoot: string;\n executionContextId: string;\n ledgerRootPath: string;\n workspacePath: string;\n runtime: {\n binary: string;\n engineIdentity: string;\n kind: \"docker\" | \"podman\";\n };\n };\n workingCopyId?: string;\n version: typeof DISPATCH_SPACE_ACTION_CONTEXT_VERSION;\n actionRecordPath: string;\n attemptId: string;\n contextId: string;\n dispatchId: string;\n expiresAtMs: number;\n nonce: string;\n replyToSignalId: string | null;\n sendTargetReference: DispatchSpaceActionSendTargetReference;\n sourceEventId: string;\n spaceContractSnapshot: Pick<\n SpaceContract,\n \"allowedActions\" | \"publicationMode\"\n > | null;\n spaceId: string;\n targetProfileId: string;\n taskId: string;\n};\n\nexport type DispatchSpaceActionRecord = {\n version: typeof DISPATCH_SPACE_ACTION_RECORD_VERSION;\n action: OpenMeldSpaceEgressAction;\n command: string;\n contextId: string;\n createdAtMs: number;\n nonce: string;\n};\n\nexport type DispatchSpaceActionRecordReadResult =\n | {\n status: \"missing\";\n }\n | {\n errorMessage: string;\n status: \"invalid\";\n }\n | {\n record: DispatchSpaceActionRecord;\n status: \"loaded\";\n };\n\nexport function createDispatchSpaceActionContext(input: {\n projectShell?: DispatchSpaceActionContext[\"projectShell\"];\n workingCopyId?: string;\n attemptId: string;\n dispatchId: string;\n env?: Record<string, string | undefined>;\n pathInput?: OpenMeldPathResolutionInput;\n replyToSignalId?: string | null;\n sendTargetReference: DispatchSpaceActionSendTargetReference;\n sourceEventId: string;\n spaceContractSnapshot:\n | Pick<SpaceContract, \"allowedActions\" | \"publicationMode\">\n | null\n | undefined;\n spaceId: string;\n targetProfileId: string;\n taskId: string;\n ttlMs?: number;\n}): {\n context: DispatchSpaceActionContext;\n contextPath: string;\n} {\n const contextId = randomUUID();\n const nonce = randomUUID();\n const contextDir = join(\n daemonRuntimeRootPath(input.pathInput ?? { env: input.env }),\n \"dispatch-space-actions\",\n `${Date.now().toString(36)}-${contextId}`\n );\n mkdirSync(contextDir, { recursive: true, mode: 0o700 });\n chmodSync(contextDir, 0o700);\n\n const contextPath = join(contextDir, \"context.json\");\n const actionRecordPath = join(contextDir, \"action.json\");\n const context: DispatchSpaceActionContext = {\n ...(input.projectShell ? { projectShell: input.projectShell } : {}),\n ...(input.workingCopyId ? { workingCopyId: input.workingCopyId } : {}),\n version: DISPATCH_SPACE_ACTION_CONTEXT_VERSION,\n actionRecordPath,\n attemptId: input.attemptId,\n contextId,\n dispatchId: input.dispatchId,\n expiresAtMs: Date.now() + (input.ttlMs ?? DEFAULT_CONTEXT_TTL_MS),\n nonce,\n replyToSignalId: normalizeOptionalText(input.replyToSignalId),\n sendTargetReference: input.sendTargetReference,\n sourceEventId: input.sourceEventId,\n spaceContractSnapshot: input.spaceContractSnapshot\n ? {\n allowedActions: input.spaceContractSnapshot.allowedActions,\n publicationMode: input.spaceContractSnapshot.publicationMode,\n }\n : null,\n spaceId: input.spaceId,\n targetProfileId: input.targetProfileId,\n taskId: input.taskId,\n };\n\n writeJsonFileExclusive(contextPath, context);\n return { context, contextPath };\n}\n\nexport function readDispatchSpaceActionContextFromEnv(\n env: NodeJS.ProcessEnv = process.env\n): DispatchSpaceActionContext {\n const context = readDispatchSpaceActionContextForReceiptFromEnv(env);\n assertContextActive(context, Date.now());\n return context;\n}\n\n// Expiry does not erase a prior receipt. Callers may use this context to compare\n// an exact existing action; writeDispatchSpaceActionRecord still rejects new\n// actions after expiry. File reads/uploads and target listing use the active\n// context reader instead.\nexport function readDispatchSpaceActionContextForReceiptFromEnv(\n env: NodeJS.ProcessEnv = process.env\n): DispatchSpaceActionContext {\n const contextPath = normalizeOptionalText(\n env[OPENMELD_SPACE_ACTION_CONTEXT_PATH_ENV]\n );\n if (!contextPath) {\n throw new Error(\n \"No active OpenMeld Space Action dispatch context was found. Use this command inside an OpenMeld Space Wake dispatch.\"\n );\n }\n const context = readDispatchSpaceActionContext(contextPath);\n assertDispatchRuntimeEnvMatchesContext({ context, env });\n return context;\n}\n\nexport function readDispatchSpaceActionContext(\n contextPath: string\n): DispatchSpaceActionContext {\n return parseDispatchSpaceActionContext(readJsonFile(contextPath));\n}\n\nexport function writeDispatchSpaceActionRecord(input: {\n action: OpenMeldSpaceEgressAction;\n command: string;\n context: DispatchSpaceActionContext;\n nowMs?: number;\n}): DispatchSpaceActionRecord {\n const parsedAction = openMeldSpaceEgressActionSchema.safeParse(input.action);\n if (!parsedAction.success) {\n throw new DispatchSpaceActionRejectedError(\n \"space_action.invalid_input\",\n parsedAction.error.message\n );\n }\n if (isSelfWakeSpaceAction(parsedAction.data, input.context.targetProfileId)) {\n throw new DispatchSpaceActionRejectedError(\n \"space_action.invalid_input\",\n \"An Agent cannot Wake itself. To reply to the current message, omit wakeTargets (CLI: --wake) and submit the reply again. No action was recorded.\"\n );\n }\n\n const existing = readDispatchSpaceActionRecord({ context: input.context });\n if (existing.status === \"invalid\") {\n throw new Error(existing.errorMessage);\n }\n if (\n existing.status === \"loaded\" &&\n isDeepStrictEqual(existing.record.action, parsedAction.data)\n ) {\n return existing.record;\n }\n assertContextActive(input.context, input.nowMs ?? Date.now());\n\n const record: DispatchSpaceActionRecord = {\n version: DISPATCH_SPACE_ACTION_RECORD_VERSION,\n action: parsedAction.data,\n command: input.command,\n contextId: input.context.contextId,\n createdAtMs: input.nowMs ?? Date.now(),\n nonce: input.context.nonce,\n };\n try {\n writeJsonFileExclusive(input.context.actionRecordPath, record);\n } catch (error) {\n if (isNodeErrorCode(error, \"EEXIST\")) {\n const existing = readDispatchSpaceActionRecord({\n context: input.context,\n });\n // A lost acknowledgement may cause the same proposal to be submitted\n // again. Acknowledge that record, never replace it or accept a new action.\n if (\n existing.status === \"loaded\" &&\n isDeepStrictEqual(existing.record.action, parsedAction.data)\n ) {\n return existing.record;\n }\n throw new DispatchSpaceActionRejectedError(\n \"space_action.already_recorded\",\n \"An OpenMeld Space Action has already been recorded for this dispatch. A Wake can only have one final Space action. Recover its receipt with the exact original arguments; do not replace it with a different action.\"\n );\n }\n throw error;\n }\n return record;\n}\n\nexport function readDispatchSpaceActionRecord(input: {\n context: DispatchSpaceActionContext;\n nowMs?: number;\n}): DispatchSpaceActionRecordReadResult {\n if (!existsSync(input.context.actionRecordPath)) {\n return { status: \"missing\" };\n }\n try {\n const record = parseDispatchSpaceActionRecord(\n readJsonFile(input.context.actionRecordPath)\n );\n if (\n record.contextId !== input.context.contextId ||\n record.nonce !== input.context.nonce\n ) {\n return {\n status: \"invalid\",\n errorMessage:\n \"OpenMeld Space Action record does not match the active dispatch context.\",\n };\n }\n if (record.createdAtMs > input.context.expiresAtMs) {\n return {\n status: \"invalid\",\n errorMessage:\n \"OpenMeld Space Action record was created after the active dispatch context expired.\",\n };\n }\n return { status: \"loaded\", record };\n } catch (error) {\n return {\n status: \"invalid\",\n errorMessage: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport function supersedeDispatchSpaceActionRecordForReconsideration(input: {\n context: DispatchSpaceActionContext;\n nowMs?: number;\n}): { archivedPath: string; record: DispatchSpaceActionRecord } | null {\n const readResult = readDispatchSpaceActionRecord(input);\n if (readResult.status === \"missing\") {\n return null;\n }\n if (readResult.status === \"invalid\") {\n throw new Error(readResult.errorMessage);\n }\n const archivedPath = `${input.context.actionRecordPath}.superseded-${String(input.nowMs ?? Date.now())}-${randomUUID()}`;\n renameSync(input.context.actionRecordPath, archivedPath);\n return { archivedPath, record: readResult.record };\n}\n\nfunction parseDispatchSpaceActionContext(\n value: unknown\n): DispatchSpaceActionContext {\n const record = toRecord(value, \"OpenMeld Space Action context\");\n const version = record.version;\n if (version !== DISPATCH_SPACE_ACTION_CONTEXT_VERSION) {\n throw new Error(\"Unsupported OpenMeld Space Action context version.\");\n }\n const sendTargetReference = parseSendTargetReference(\n record.sendTargetReference\n );\n return {\n ...(record.projectShell\n ? { projectShell: parseProjectShell(record.projectShell) }\n : {}),\n version,\n actionRecordPath: requiredString(\n record.actionRecordPath,\n \"actionRecordPath\"\n ),\n attemptId: requiredString(record.attemptId, \"attemptId\"),\n contextId: requiredString(record.contextId, \"contextId\"),\n dispatchId: requiredString(record.dispatchId, \"dispatchId\"),\n expiresAtMs: requiredFiniteNumber(record.expiresAtMs, \"expiresAtMs\"),\n nonce: requiredString(record.nonce, \"nonce\"),\n replyToSignalId: optionalString(record.replyToSignalId),\n sendTargetReference,\n sourceEventId: requiredString(record.sourceEventId, \"sourceEventId\"),\n spaceContractSnapshot: parseSpaceContractSnapshot(\n record.spaceContractSnapshot\n ),\n spaceId: requiredString(record.spaceId, \"spaceId\"),\n targetProfileId: requiredString(record.targetProfileId, \"targetProfileId\"),\n taskId: requiredString(record.taskId, \"taskId\"),\n ...(record.workingCopyId\n ? { workingCopyId: requiredString(record.workingCopyId, \"workingCopyId\") }\n : {}),\n };\n}\n\nfunction parseProjectShell(\n value: unknown\n): NonNullable<DispatchSpaceActionContext[\"projectShell\"]> {\n const record = toRecord(value, \"OpenMeld project shell context\");\n const runtime = toRecord(record.runtime, \"OpenMeld project shell runtime\");\n const kind = runtime.kind;\n if (kind !== \"docker\" && kind !== \"podman\") {\n throw new Error(\"OpenMeld project shell runtime is invalid.\");\n }\n const executionContextId = requiredString(\n record.executionContextId,\n \"executionContextId\"\n );\n const workspacePath = requiredString(record.workspacePath, \"workspacePath\");\n const boundaryRoot = requiredString(record.boundaryRoot, \"boundaryRoot\");\n const ledgerRootPath = requiredString(\n record.ledgerRootPath,\n \"ledgerRootPath\"\n );\n const binary = requiredString(runtime.binary, \"binary\");\n const validContextId =\n executionContextAssignmentSchema.shape.id.safeParse(\n executionContextId\n ).success;\n const validPaths = [\n workspacePath,\n boundaryRoot,\n ledgerRootPath,\n binary,\n ].every(isAbsolute);\n if (!(validContextId && validPaths)) {\n throw new Error(\"OpenMeld project shell context is invalid.\");\n }\n return {\n boundaryRoot,\n executionContextId,\n ledgerRootPath,\n workspacePath,\n runtime: {\n binary,\n engineIdentity: requiredString(runtime.engineIdentity, \"engineIdentity\"),\n kind,\n },\n };\n}\n\nfunction assertDispatchRuntimeEnvMatchesContext(input: {\n context: DispatchSpaceActionContext;\n env: NodeJS.ProcessEnv;\n}): void {\n const mode = normalizeOptionalText(\n input.env[OPENMELD_DISPATCH_RUNTIME_MODE_ENV]\n );\n if (mode !== DISPATCH_OWNED_RUNTIME_MODE) {\n return;\n }\n\n const envDispatchId = normalizeOptionalText(\n input.env[OPENMELD_DISPATCH_RUNTIME_DISPATCH_ID_ENV]\n );\n if (!envDispatchId) {\n throw new Error(\n \"OpenMeld Space Action dispatch runtime is missing the active dispatch ID.\"\n );\n }\n if (envDispatchId !== input.context.dispatchId) {\n throw new DispatchSpaceActionClosedError(\n \"space_action.context_mismatch\",\n \"OpenMeld Space Action dispatch context does not match the active dispatch runtime.\"\n );\n }\n\n const envTargetProfileId = normalizeOptionalText(\n input.env[OPENMELD_DISPATCH_RUNTIME_TARGET_PROFILE_ID_ENV]\n );\n if (!envTargetProfileId) {\n throw new Error(\n \"OpenMeld Space Action dispatch runtime is missing the active target profile ID.\"\n );\n }\n if (envTargetProfileId !== input.context.targetProfileId) {\n throw new DispatchSpaceActionClosedError(\n \"space_action.context_mismatch\",\n \"OpenMeld Space Action target profile does not match the active dispatch runtime.\"\n );\n }\n}\n\nfunction parseDispatchSpaceActionRecord(\n value: unknown\n): DispatchSpaceActionRecord {\n const record = toRecord(value, \"OpenMeld Space Action record\");\n const version = record.version;\n if (version !== DISPATCH_SPACE_ACTION_RECORD_VERSION) {\n throw new Error(\"Unsupported OpenMeld Space Action record version.\");\n }\n const parsedAction = openMeldSpaceEgressActionSchema.safeParse(record.action);\n if (!parsedAction.success) {\n throw parsedAction.error;\n }\n return {\n version,\n action: parsedAction.data,\n command: requiredString(record.command, \"command\"),\n contextId: requiredString(record.contextId, \"contextId\"),\n createdAtMs: requiredFiniteNumber(record.createdAtMs, \"createdAtMs\"),\n nonce: requiredString(record.nonce, \"nonce\"),\n };\n}\n\nfunction parseSendTargetReference(\n value: unknown\n): DispatchSpaceActionSendTargetReference {\n const record = toRecord(value, \"sendTargetReference\");\n if (record.status === \"loaded\") {\n if (!Array.isArray(record.projection)) {\n throw new Error(\n \"OpenMeld Space Action send target projection must be an array.\"\n );\n }\n return {\n status: \"loaded\",\n projection: record.projection.map(parseSendTargetProjectionEntry),\n referenceLines: parseStringArray(record.referenceLines),\n };\n }\n if (record.status === \"failed\") {\n return {\n status: \"failed\",\n errorMessage: requiredString(record.errorMessage, \"errorMessage\"),\n projection: null,\n referenceLines: [],\n };\n }\n throw new Error(\n \"Invalid OpenMeld Space Action send target reference status.\"\n );\n}\n\nfunction parseSendTargetProjectionEntry(\n value: unknown,\n index: number\n): SpaceMemberDirectoryEntry {\n const parsed = spaceMemberDirectoryEntrySchema.safeParse(value);\n if (!parsed.success) {\n throw new Error(\n `OpenMeld Space Action target projection entry ${index} is not a valid Space member directory entry.`\n );\n }\n return parsed.data;\n}\n\nfunction parseSpaceContractSnapshot(\n value: unknown\n): Pick<SpaceContract, \"allowedActions\" | \"publicationMode\"> | null {\n if (value === null || value === undefined) {\n return null;\n }\n const record = toRecord(value, \"spaceContractSnapshot\");\n return {\n allowedActions: Array.isArray(record.allowedActions)\n ? (record.allowedActions as SpaceContract[\"allowedActions\"])\n : [],\n publicationMode:\n record.publicationMode === \"raw_context_sharing\"\n ? \"raw_context_sharing\"\n : \"collaboration\",\n };\n}\n\nfunction assertContextActive(\n context: DispatchSpaceActionContext,\n nowMs: number\n): void {\n if (nowMs > context.expiresAtMs) {\n throw new DispatchSpaceActionClosedError(\n \"space_action.context_expired\",\n \"The OpenMeld Space Action dispatch context has expired.\"\n );\n }\n}\n\nfunction readJsonFile(path: string): unknown {\n return JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n}\n\nfunction writeJsonFileExclusive(path: string, value: unknown): void {\n writeFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, {\n encoding: \"utf8\",\n flag: \"wx\",\n mode: 0o600,\n });\n chmodSync(path, 0o600);\n}\n\nfunction toRecord(value: unknown, label: string): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${label} must be a JSON object.`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction requiredString(value: unknown, fieldName: string): string {\n const normalized = normalizeOptionalText(value);\n if (!normalized) {\n throw new Error(`${fieldName} must be a non-empty string.`);\n }\n return normalized;\n}\n\nfunction requiredFiniteNumber(value: unknown, fieldName: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number.`);\n }\n return value;\n}\n\nfunction optionalString(value: unknown): string | null {\n if (value === null || value === undefined) {\n return null;\n }\n return normalizeOptionalText(value);\n}\n\nfunction parseStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value\n .map((item) => normalizeOptionalText(item))\n .filter((item): item is string => Boolean(item));\n}\n\nfunction normalizeOptionalText(value: unknown): string | null {\n const normalized = String(value ?? \"\").trim();\n return normalized.length > 0 ? normalized : null;\n}\n\nfunction isNodeErrorCode(error: unknown, code: string): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: unknown }).code === code\n );\n}\n","import {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { delimiter, dirname, join, resolve } from \"node:path\";\nimport { daemonRuntimeRootPath } from \"../config/daemon-state\";\nimport {\n type OpenMeldPathResolutionInput,\n openMeldManagedBinaryPath,\n resolveOpenMeldEnvPreset,\n} from \"../config/paths\";\nimport {\n DISPATCH_OWNED_RUNTIME_MODE,\n OPENMELD_DISPATCH_RUNTIME_DISPATCH_ID_ENV,\n OPENMELD_DISPATCH_RUNTIME_MODE_ENV,\n OPENMELD_DISPATCH_RUNTIME_TARGET_PROFILE_ID_ENV,\n OPENMELD_SPACE_ACTION_TOOL_COMMAND_PATH_ENV,\n OPENMELD_USER_FACING_CLI_COMMAND_ENV,\n} from \"./dispatch-runtime-env\";\nimport { OPENMELD_SPACE_ACTION_CONTEXT_PATH_ENV } from \"./dispatch-space-action-context\";\nimport {\n type OpenMeldDistribution,\n resolveOpenMeldDistribution,\n} from \"./distribution\";\n\nconst DISPATCH_OWNED_RUNTIME_CLI_SHIM_DIRNAME = \"dispatch-owned-cli\";\nconst DISPATCH_SPACE_ACTION_CLI_SHIM_DIRNAME = \"bin\";\nconst OPENMELD_ENV_PRESET_ENV = \"OPENMELD_ENV_PRESET\";\nconst DISPATCH_OWNED_RUNTIME_CLI_COMMAND_NAMES = [\n \"openmeld\",\n \"openmeld-dev\",\n \"openmeld-canary\",\n] as const;\n\nexport type DispatchOwnedRuntimeGuard = {\n active: boolean;\n dispatchId: string | null;\n targetProfileId: string | null;\n};\n\nexport function buildDispatchOwnedRuntimeEnv(input: {\n dispatchId: string;\n targetProfileId: string;\n distribution?: OpenMeldDistribution;\n platform?: NodeJS.Platform;\n env?: Record<string, string | undefined>;\n cliEntryPath?: string;\n spaceActionContextPath?: string | null;\n}): Record<string, string | undefined> {\n // Provider overrides are not a replacement for the carrier's lane. Keep\n // these non-secret installation selectors without copying unrelated Service\n // credentials into the provider environment.\n const env = {\n OPENMELD_HOME: process.env.OPENMELD_HOME,\n OPENMELD_ENV_PRESET: process.env.OPENMELD_ENV_PRESET,\n ...(input.env ?? {}),\n };\n const currentPath = normalizeOptionalText(\n input.env?.PATH ?? process.env.PATH\n );\n const actionCommand = resolveDispatchOwnedRuntimeActionCliEntryCommand({\n env,\n });\n const nativeWindowsBinary =\n (input.platform ?? process.platform) === \"win32\" &&\n (input.distribution ?? resolveOpenMeldDistribution()) === \"binary\";\n // Windows cannot CreateProcess a POSIX shim. The managed launcher is already\n // a native executable, and the dispatch identity remains in the child env.\n const actionCommandPath = nativeWindowsBinary\n ? resolveDispatchOwnedRuntimeBinaryCliEntryPath({\n cliEntryPath: input.cliEntryPath,\n env,\n })\n : join(\n ensureDispatchOwnedRuntimeCliShims({\n cliEntryPath: input.cliEntryPath,\n dispatchId: input.dispatchId,\n distribution: input.distribution,\n env,\n spaceActionContextPath: input.spaceActionContextPath,\n targetProfileId: input.targetProfileId,\n }),\n actionCommand\n );\n return {\n ...env,\n PATH: prependPathEntry({\n currentPath,\n nextEntry: dirname(actionCommandPath),\n }),\n [OPENMELD_DISPATCH_RUNTIME_MODE_ENV]: DISPATCH_OWNED_RUNTIME_MODE,\n [OPENMELD_DISPATCH_RUNTIME_DISPATCH_ID_ENV]: input.dispatchId,\n [OPENMELD_DISPATCH_RUNTIME_TARGET_PROFILE_ID_ENV]: input.targetProfileId,\n [OPENMELD_USER_FACING_CLI_COMMAND_ENV]: actionCommand,\n [OPENMELD_SPACE_ACTION_TOOL_COMMAND_PATH_ENV]: actionCommandPath,\n [OPENMELD_ENV_PRESET_ENV]: resolveDispatchOwnedRuntimeEnvPreset({\n env,\n }),\n ...(input.spaceActionContextPath\n ? {\n [OPENMELD_SPACE_ACTION_CONTEXT_PATH_ENV]:\n input.spaceActionContextPath,\n }\n : {}),\n };\n}\n\nexport function resolveDispatchOwnedRuntimeActionCliEntryCommand(\n input: OpenMeldPathResolutionInput = {}\n): \"openmeld\" | \"openmeld-dev\" | \"openmeld-canary\" {\n const preset = resolveOpenMeldEnvPreset(input);\n if (preset === \"dev-local\") {\n return \"openmeld-dev\";\n }\n if (preset === \"canary\") {\n return \"openmeld-canary\";\n }\n return \"openmeld\";\n}\n\nexport function resolveDispatchOwnedRuntimeCliShimDir(\n input: OpenMeldPathResolutionInput & {\n spaceActionContextPath?: string | null;\n } = {}\n): string {\n const spaceActionContextPath = normalizeOptionalText(\n input.spaceActionContextPath\n );\n if (spaceActionContextPath) {\n return join(\n dirname(spaceActionContextPath),\n DISPATCH_SPACE_ACTION_CLI_SHIM_DIRNAME\n );\n }\n return join(\n daemonRuntimeRootPath(input),\n \"bin\",\n DISPATCH_OWNED_RUNTIME_CLI_SHIM_DIRNAME\n );\n}\n\nexport function ensureDispatchOwnedRuntimeCliShims(input?: {\n cliEntryPath?: string;\n distribution?: OpenMeldDistribution;\n dispatchId?: string;\n env?: Record<string, string | undefined>;\n spaceActionContextPath?: string | null;\n targetProfileId?: string;\n}): string {\n const distribution = input?.distribution ?? resolveOpenMeldDistribution();\n const cliEntryPath =\n distribution === \"binary\"\n ? resolveDispatchOwnedRuntimeBinaryCliEntryPath({\n cliEntryPath: input?.cliEntryPath,\n env: input?.env,\n })\n : resolveDispatchOwnedRuntimeCliEntryPath(input?.cliEntryPath);\n const shimDir = resolveDispatchOwnedRuntimeCliShimDir({\n env: input?.env,\n spaceActionContextPath: input?.spaceActionContextPath,\n });\n mkdirSync(shimDir, { recursive: true });\n\n for (const commandName of DISPATCH_OWNED_RUNTIME_CLI_COMMAND_NAMES) {\n const shimPath = join(shimDir, commandName);\n const shimSource = buildDispatchOwnedRuntimeCliShimSource({\n cliEntryPath,\n commandName,\n dispatchId: input?.dispatchId,\n distribution,\n nodePath: process.execPath,\n spaceActionContextPath: input?.spaceActionContextPath,\n targetProfileId: input?.targetProfileId,\n });\n if (existsSync(shimPath)) {\n const currentSource = safeReadTextFile(shimPath);\n if (currentSource === shimSource) {\n chmodSync(shimPath, 0o755);\n continue;\n }\n }\n writeFileSync(shimPath, shimSource, {\n encoding: \"utf8\",\n mode: 0o755,\n });\n chmodSync(shimPath, 0o755);\n }\n\n return shimDir;\n}\n\nexport function readDispatchOwnedRuntimeGuard(\n env: NodeJS.ProcessEnv = process.env\n): DispatchOwnedRuntimeGuard {\n const mode = normalizeOptionalText(env[OPENMELD_DISPATCH_RUNTIME_MODE_ENV]);\n if (mode !== DISPATCH_OWNED_RUNTIME_MODE) {\n return {\n active: false,\n dispatchId: null,\n targetProfileId: null,\n };\n }\n\n return {\n active: true,\n dispatchId: normalizeOptionalText(\n env[OPENMELD_DISPATCH_RUNTIME_DISPATCH_ID_ENV]\n ),\n targetProfileId: normalizeOptionalText(\n env[OPENMELD_DISPATCH_RUNTIME_TARGET_PROFILE_ID_ENV]\n ),\n };\n}\n\nexport function assertDispatchOwnedRuntimePublicWriteAllowed(input: {\n commandLabel: string;\n env?: NodeJS.ProcessEnv;\n}): void {\n const guard = readDispatchOwnedRuntimeGuard(input.env);\n if (!guard.active) {\n return;\n }\n\n const dispatchIdSuffix = guard.dispatchId\n ? ` (dispatch ${guard.dispatchId})`\n : \"\";\n throw new Error(\n `${input.commandLabel} is blocked inside a dispatch-owned runtime${dispatchIdSuffix}. Public space writes must be returned through OpenMeld Space structured actions: post_message, post_status, or stay_silent.`\n );\n}\n\nfunction normalizeOptionalText(value: unknown): string | null {\n const normalized = String(value ?? \"\").trim();\n return normalized.length > 0 ? normalized : null;\n}\n\nfunction resolveDispatchOwnedRuntimeCliEntryPath(\n cliEntryPath?: string\n): string {\n const normalizedCliEntryPath =\n normalizeOptionalText(cliEntryPath) ??\n normalizeOptionalText(process.argv[1]) ??\n null;\n if (!normalizedCliEntryPath) {\n throw new Error(\n \"dispatch-owned runtime CLI shim requires a current CLI entry path\"\n );\n }\n return resolve(normalizedCliEntryPath);\n}\n\nfunction resolveDispatchOwnedRuntimeBinaryCliEntryPath(input: {\n cliEntryPath?: string;\n env?: Record<string, string | undefined>;\n}): string {\n // A background Service may keep running from an executable path that an\n // upgrade later replaces with a launcher. The lane-owned managed CLI is the\n // stable command authority for new Space Action subprocesses.\n const normalizedCliEntryPath =\n normalizeOptionalText(input.cliEntryPath) ??\n normalizeOptionalText(openMeldManagedBinaryPath({ env: input.env })) ??\n null;\n if (!normalizedCliEntryPath) {\n throw new Error(\n \"dispatch-owned runtime CLI shim requires a current binary CLI path\"\n );\n }\n return resolve(normalizedCliEntryPath);\n}\n\nfunction buildDispatchOwnedRuntimeCliShimSource(input: {\n cliEntryPath: string;\n commandName: (typeof DISPATCH_OWNED_RUNTIME_CLI_COMMAND_NAMES)[number];\n distribution: OpenMeldDistribution;\n dispatchId?: string;\n nodePath: string;\n spaceActionContextPath?: string | null;\n targetProfileId?: string;\n}): string {\n const embeddedEnv = {\n [OPENMELD_DISPATCH_RUNTIME_MODE_ENV]: DISPATCH_OWNED_RUNTIME_MODE,\n [OPENMELD_ENV_PRESET_ENV]: resolveEnvPresetForCommandName(\n input.commandName\n ),\n [OPENMELD_USER_FACING_CLI_COMMAND_ENV]: input.commandName,\n ...(normalizeOptionalText(input.dispatchId)\n ? {\n [OPENMELD_DISPATCH_RUNTIME_DISPATCH_ID_ENV]: normalizeOptionalText(\n input.dispatchId\n ) as string,\n }\n : {}),\n ...(normalizeOptionalText(input.targetProfileId)\n ? {\n [OPENMELD_DISPATCH_RUNTIME_TARGET_PROFILE_ID_ENV]:\n normalizeOptionalText(input.targetProfileId) as string,\n }\n : {}),\n ...(normalizeOptionalText(input.spaceActionContextPath)\n ? {\n [OPENMELD_SPACE_ACTION_CONTEXT_PATH_ENV]: normalizeOptionalText(\n input.spaceActionContextPath\n ) as string,\n }\n : {}),\n };\n if (input.distribution === \"binary\") {\n const exportRows = Object.entries(embeddedEnv).map(\n ([key, value]) => `export ${key}=${quoteShellValue(value)}`\n );\n return `#!/bin/sh\n${exportRows.join(\"\\n\")}\nexec ${quoteShellValue(input.cliEntryPath)} \"$@\"\n`;\n }\n return `#!/usr/bin/env node\nimport { spawnSync } from \"node:child_process\";\n\nconst result = spawnSync(${JSON.stringify(input.nodePath)}, [${JSON.stringify(\n input.cliEntryPath\n )}, ...process.argv.slice(2)], {\n env: { ...process.env, ...${JSON.stringify(embeddedEnv)} },\n stdio: \"inherit\",\n});\n\nif (result.error) {\n throw result.error;\n}\n\nprocess.exit(result.status ?? 1);\n`;\n}\n\nfunction resolveDispatchOwnedRuntimeEnvPreset(input: {\n env?: Record<string, string | undefined>;\n}): \"prod\" | \"dev-local\" | \"canary\" {\n return resolveEnvPresetForCommandName(\n resolveDispatchOwnedRuntimeActionCliEntryCommand({\n env: input.env,\n })\n );\n}\n\nfunction resolveEnvPresetForCommandName(\n commandName: (typeof DISPATCH_OWNED_RUNTIME_CLI_COMMAND_NAMES)[number]\n): \"prod\" | \"dev-local\" | \"canary\" {\n if (commandName === \"openmeld-dev\") {\n return \"dev-local\";\n }\n if (commandName === \"openmeld-canary\") {\n return \"canary\";\n }\n return \"prod\";\n}\n\nfunction quoteShellValue(value: string): string {\n return `'${value.replaceAll(\"'\", \"'\\\\''\")}'`;\n}\n\nfunction safeReadTextFile(path: string): string | null {\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction prependPathEntry(input: {\n currentPath: string | null;\n nextEntry: string;\n}): string {\n const currentEntries = (input.currentPath ?? \"\")\n .split(delimiter)\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n const dedupedEntries = currentEntries.filter(\n (entry) => entry !== input.nextEntry\n );\n return [input.nextEntry, ...dedupedEntries].join(delimiter);\n}\n","import { createSpaceApi, type SpaceApi } from \"@openmeld/api-client\";\nimport { createCliApiClientFoundation } from \"./api-client-foundation\";\n\nexport type {\n SpaceApi,\n SpaceSignalsReadQuery,\n} from \"@openmeld/api-client\";\n\nexport function createCliSpaceApi(\n baseUrl: string,\n options: Parameters<typeof createCliApiClientFoundation>[1] = {}\n): SpaceApi {\n return createSpaceApi(createCliApiClientFoundation(baseUrl, options));\n}\n","import { openAsBlob } from \"node:fs\";\nimport { access } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\nimport {\n type StructuredApiClientFailure,\n toStructuredApiClientFailure,\n} from \"@openmeld/api-client\";\nimport {\n resolveSpaceFileMimeType,\n SPACE_FILE_MAX_SIZE_BYTES,\n SPACE_MESSAGE_FILE_MAX_COUNT,\n spaceFileNameSchema,\n} from \"@openmeld/schemas\";\nimport type {\n OpenMeldRequestContext,\n SpaceMessageFileReference,\n} from \"@openmeld/schemas/types\";\nimport type { SpaceApi } from \"./cli-space-api\";\n\ntype PreparedSpaceFile = {\n bytes: Blob;\n name: string;\n mimeType: string;\n};\n\ntype SpaceFileCleanupFailure = {\n failure: StructuredApiClientFailure;\n fileId: string;\n};\n\nexport class SpaceSendFileError extends Error {\n readonly code: string;\n readonly requestId?: string;\n readonly status?: number;\n readonly upstreamCode?: string;\n\n constructor(input: {\n code: string;\n message: string;\n cause?: unknown;\n requestId?: string | null;\n status?: number | null;\n upstreamCode?: string | null;\n }) {\n super(input.message, { cause: input.cause });\n this.name = \"SpaceSendFileError\";\n this.code = input.code;\n if (input.requestId) {\n this.requestId = input.requestId;\n }\n if (input.status !== null && input.status !== undefined) {\n this.status = input.status;\n }\n if (input.upstreamCode) {\n this.upstreamCode = input.upstreamCode;\n }\n }\n}\n\nexport async function prepareRequestedSpaceSendFiles(input: {\n filePaths: readonly string[];\n}): Promise<readonly PreparedSpaceFile[]> {\n if (input.filePaths.length > SPACE_MESSAGE_FILE_MAX_COUNT) {\n throw new SpaceSendFileError({\n code: \"space.file.too_many\",\n message: `A Space message can include at most ${SPACE_MESSAGE_FILE_MAX_COUNT} files. The message was not sent.`,\n });\n }\n\n const prepared: PreparedSpaceFile[] = [];\n for (const rawPath of input.filePaths) {\n if (!rawPath.trim()) {\n throw new SpaceSendFileError({\n code: \"space.file.invalid_path\",\n message: \"File paths cannot be empty. The message was not sent.\",\n });\n }\n prepared.push(await prepareSpaceSendFile(rawPath));\n }\n return prepared;\n}\n\nexport async function uploadPreparedSpaceFiles(input: {\n files: readonly PreparedSpaceFile[];\n password?: string;\n requestContext: OpenMeldRequestContext;\n spaceApi: SpaceApi;\n spaceId: string;\n}): Promise<readonly SpaceMessageFileReference[]> {\n const uploaded: SpaceMessageFileReference[] = [];\n for (const file of input.files) {\n try {\n const descriptor = await input.spaceApi.uploadFile({\n bytes: file.bytes,\n clientMutationId: crypto.randomUUID(),\n mimeType: file.mimeType,\n name: file.name,\n origin: \"chat_upload\",\n parentId: null,\n requestContext: input.requestContext,\n spaceId: input.spaceId,\n ...(input.password === undefined\n ? {}\n : { spacePassword: input.password }),\n });\n uploaded.push({\n fileId: descriptor.id,\n revision: descriptor.latestRevision.revision,\n name: descriptor.name,\n mimeType: descriptor.latestRevision.mimeType,\n sizeBytes: descriptor.latestRevision.sizeBytes,\n });\n } catch (error) {\n const failure = toStructuredApiClientFailure(error);\n const cleanupFailures = await moveUploadedFilesToTrash({\n files: uploaded,\n password: input.password,\n requestContext: input.requestContext,\n spaceApi: input.spaceApi,\n spaceId: input.spaceId,\n });\n let cleanupMessage = \"\";\n if (uploaded.length > 0) {\n cleanupMessage =\n cleanupFailures.length === 0\n ? \" Files added earlier in this send were moved to Trash.\"\n : ` ${formatCleanupFailures({\n failures: cleanupFailures,\n passwordProtected: input.password !== undefined,\n profileId: input.requestContext.actorContext.openMeldProfileId,\n spaceId: input.spaceId,\n })}`;\n }\n throw new SpaceSendFileError({\n code: failure.code ?? \"space.file.upload_failed\",\n message: `Could not add file \"${file.name}\" to this Space. The message was not sent. ${failure.message}${cleanupMessage}`,\n cause: error,\n requestId: failure.requestId,\n status: failure.status,\n upstreamCode: failure.upstreamCode,\n });\n }\n }\n return uploaded;\n}\n\nasync function moveUploadedFilesToTrash(input: {\n files: readonly SpaceMessageFileReference[];\n password?: string;\n requestContext: OpenMeldRequestContext;\n spaceApi: SpaceApi;\n spaceId: string;\n}): Promise<readonly SpaceFileCleanupFailure[]> {\n const failures: SpaceFileCleanupFailure[] = [];\n for (const file of input.files) {\n try {\n await input.spaceApi.trashFileEntry({\n clientMutationId: crypto.randomUUID(),\n entryId: file.fileId,\n requestContext: input.requestContext,\n spaceId: input.spaceId,\n ...(input.password === undefined\n ? {}\n : { spacePassword: input.password }),\n });\n } catch (error) {\n failures.push({\n failure: toStructuredApiClientFailure(error),\n fileId: file.fileId,\n });\n }\n }\n return failures;\n}\n\nfunction formatCleanupFailures(input: {\n failures: readonly SpaceFileCleanupFailure[];\n passwordProtected: boolean;\n profileId: string;\n spaceId: string;\n}): string {\n const failureMessages = input.failures\n .map(({ failure, fileId }) => {\n const evidence = [\n failure.code ? `code ${failure.code}` : null,\n failure.requestId ? `request ${failure.requestId}` : null,\n ]\n .filter((value): value is string => value !== null)\n .join(\", \");\n const evidenceText = evidence ? ` (${evidence})` : \"\";\n return `Could not move file ${fileId} to Trash${evidenceText}: ${failure.message} Run \\`openmeld space files trash ${input.spaceId} ${fileId} --profile ${input.profileId}\\` to finish cleanup.`;\n })\n .join(\" \");\n const passwordGuidance = input.passwordProtected\n ? \" This Space is password protected. Add `--password` with the same Space password you used for this send; OpenMeld does not include the password in this message.\"\n : \"\";\n return `${failureMessages}${passwordGuidance}`;\n}\n\nasync function prepareSpaceSendFile(\n sourcePath: string\n): Promise<PreparedSpaceFile> {\n let bytes: Blob;\n try {\n // openAsBlob collapses missing paths into ERR_INVALID_ARG_VALUE on Node 24.\n // Preserve the filesystem error code for the user-facing failure category.\n await access(sourcePath);\n bytes = await openAsBlob(sourcePath);\n } catch (error) {\n const code = readNodeErrorCode(error);\n if (code === \"ENOENT\") {\n throw new SpaceSendFileError({\n code: \"space.file.file_not_found\",\n message: `File not found: ${sourcePath}. The message was not sent.`,\n cause: error,\n });\n }\n throw new SpaceSendFileError({\n code: \"space.file.file_unreadable\",\n message: `Could not read file: ${sourcePath}. The message was not sent.`,\n cause: error,\n });\n }\n\n if (bytes.size > SPACE_FILE_MAX_SIZE_BYTES) {\n throw new SpaceSendFileError({\n code: \"space.file.too_large\",\n message: `File exceeds the ${formatFileSizeLimit()} limit: ${sourcePath}. The message was not sent.`,\n });\n }\n\n const parsedName = spaceFileNameSchema.safeParse(basename(sourcePath));\n if (!parsedName.success) {\n throw new SpaceSendFileError({\n code: \"space.file.invalid_file_name\",\n message: `File name is invalid: ${sourcePath}. The message was not sent.`,\n });\n }\n\n return {\n bytes,\n name: parsedName.data,\n mimeType: resolveSpaceFileMimeType({ fileName: parsedName.data }),\n };\n}\n\nfunction readNodeErrorCode(error: unknown): string | null {\n if (!(error && typeof error === \"object\" && \"code\" in error)) {\n return null;\n }\n return typeof error.code === \"string\" ? error.code : null;\n}\n\nfunction formatFileSizeLimit(): string {\n return `${SPACE_FILE_MAX_SIZE_BYTES / (1024 * 1024)} MiB`;\n}\n","export function parseJsonResponse(raw: string): unknown {\n if (!raw.trim()) {\n return null;\n }\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n","import { OpenMeldApiClientHttpError } from \"@openmeld/api-client\";\nimport { OPENMELD_HEADER_REQUEST_ID } from \"@openmeld/gateway-contract\";\nimport { gatewayErrorEnvelopeSchema } from \"@openmeld/schemas\";\nimport type { GatewayErrorCode } from \"@openmeld/schemas/types\";\nimport { parseJsonResponse } from \"./api-json\";\n\nconst FALLBACK_GATEWAY_HTTP_ERROR_CODE = \"gateway.http_error\" as const;\nconst GENERIC_NETWORK_ERROR_CODES = [\n \"network.timeout\",\n \"network.request_failed\",\n] as const;\n\ntype SafeParseResult<T> = { success: true; data: T } | { success: false };\n\ntype GatewayResponseSchema<T> = {\n safeParse: (value: unknown) => SafeParseResult<T>;\n};\n\nexport type GatewayResponseErrorCode =\n | GatewayErrorCode\n | typeof FALLBACK_GATEWAY_HTTP_ERROR_CODE\n | (typeof GENERIC_NETWORK_ERROR_CODES)[number]\n | string;\n\nexport type StructuredGatewayFailure = {\n code: GatewayResponseErrorCode | null;\n message: string;\n requestId: string | null;\n status: number | null;\n upstreamCode: string | null;\n};\n\nexport class GatewayHttpError extends Error {\n readonly code: GatewayResponseErrorCode;\n readonly requestId: string | null;\n readonly status: number;\n readonly rawBody: string;\n readonly upstreamCode: string | null;\n\n constructor(input: {\n code: GatewayResponseErrorCode;\n message: string;\n requestId?: string | null;\n status: number;\n rawBody: string;\n upstreamCode?: string | null;\n }) {\n super(input.message);\n this.name = \"GatewayHttpError\";\n this.code = input.code;\n this.requestId = normalizeOptionalText(input.requestId);\n this.status = input.status;\n this.rawBody = input.rawBody;\n this.upstreamCode = normalizeOptionalText(input.upstreamCode);\n }\n}\n\nexport async function readGatewayJsonResponse<T>(input: {\n response: Response;\n schema: GatewayResponseSchema<T>;\n invalidMessage: string;\n}): Promise<T> {\n const raw = await input.response.text();\n assertGatewayResponseOk({\n response: input.response,\n raw,\n });\n\n const parsed = input.schema.safeParse(parseJsonResponse(raw));\n if (!parsed.success) {\n throw new Error(input.invalidMessage);\n }\n return parsed.data;\n}\n\nexport async function readGatewayTextResponse(input: {\n response: Response;\n}): Promise<string> {\n const raw = await input.response.text();\n assertGatewayResponseOk({\n response: input.response,\n raw,\n });\n return raw;\n}\n\nexport function assertGatewayResponseOk(input: {\n response: Response;\n raw: string;\n}): void {\n if (input.response.ok) {\n return;\n }\n throw parseGatewayErrorResponse(input);\n}\n\nexport function parseGatewayErrorResponse(input: {\n response: Pick<Response, \"headers\" | \"status\">;\n raw: string;\n}): GatewayHttpError {\n const payload = parseJsonResponse(input.raw);\n const parsed = gatewayErrorEnvelopeSchema.safeParse(payload);\n const headerRequestId = normalizeOptionalText(\n input.response.headers.get(OPENMELD_HEADER_REQUEST_ID)\n );\n\n if (parsed.success) {\n return new GatewayHttpError({\n code: parsed.data.error.code,\n message: parsed.data.error.message,\n requestId: parsed.data.error.requestId || headerRequestId,\n status: input.response.status,\n rawBody: input.raw,\n upstreamCode: parsed.data.error.upstreamCode ?? null,\n });\n }\n\n const looseEnvelope = readLooseGatewayErrorEnvelope(payload);\n if (looseEnvelope) {\n return new GatewayHttpError({\n code: looseEnvelope.code ?? FALLBACK_GATEWAY_HTTP_ERROR_CODE,\n message:\n looseEnvelope.message ??\n `Gateway request failed with HTTP ${input.response.status}.`,\n requestId: looseEnvelope.requestId ?? headerRequestId,\n status: input.response.status,\n rawBody: input.raw,\n upstreamCode: looseEnvelope.upstreamCode,\n });\n }\n\n return new GatewayHttpError({\n code: FALLBACK_GATEWAY_HTTP_ERROR_CODE,\n message:\n normalizeOptionalText(input.raw) ??\n `Gateway request failed with HTTP ${input.response.status}.`,\n requestId: headerRequestId,\n status: input.response.status,\n rawBody: input.raw,\n upstreamCode: null,\n });\n}\n\nexport function toStructuredGatewayFailure(\n error: unknown\n): StructuredGatewayFailure {\n if (error instanceof OpenMeldApiClientHttpError) {\n return {\n code: error.code,\n message: normalizeFailureMessage(error.message),\n requestId: error.requestId,\n status: error.status,\n upstreamCode: error.upstreamCode,\n };\n }\n\n if (error instanceof GatewayHttpError) {\n return {\n code: error.code,\n message: normalizeFailureMessage(error.message),\n requestId: error.requestId,\n status: error.status,\n upstreamCode: error.upstreamCode,\n };\n }\n\n const genericErrorCode = readGenericErrorCode(error);\n if (genericErrorCode) {\n return {\n code: genericErrorCode,\n message: normalizeFailureMessage(\n error instanceof Error ? error.message : String(error)\n ),\n requestId: null,\n status: null,\n upstreamCode: null,\n };\n }\n\n return {\n code: null,\n message: normalizeFailureMessage(\n error instanceof Error ? error.message : String(error)\n ),\n requestId: null,\n status: null,\n upstreamCode: null,\n };\n}\n\nfunction normalizeOptionalText(value: unknown): string | null {\n const normalized = String(value ?? \"\").trim();\n return normalized.length > 0 ? normalized : null;\n}\n\nfunction normalizeFailureMessage(value: unknown): string {\n return normalizeOptionalText(value) ?? \"Unknown error.\";\n}\n\nfunction readGenericErrorCode(value: unknown): GatewayResponseErrorCode | null {\n if (!value || typeof value !== \"object\" || !(\"code\" in value)) {\n return null;\n }\n\n const normalized = normalizeOptionalText(\n (value as { code?: unknown }).code ?? null\n );\n return normalized as GatewayResponseErrorCode | null;\n}\n\nfunction readLooseGatewayErrorEnvelope(value: unknown): {\n code: string | null;\n message: string | null;\n requestId: string | null;\n upstreamCode: string | null;\n} | null {\n if (!value || typeof value !== \"object\") {\n return null;\n }\n\n const record = value as {\n error?: {\n code?: unknown;\n message?: unknown;\n requestId?: unknown;\n upstreamCode?: unknown;\n } | null;\n };\n const error = record.error;\n if (!error || typeof error !== \"object\") {\n return null;\n }\n\n const code = normalizeOptionalText(error.code);\n const message = normalizeOptionalText(error.message);\n const requestId = normalizeOptionalText(error.requestId);\n const upstreamCode = normalizeOptionalText(error.upstreamCode);\n if (!(code || message || requestId || upstreamCode)) {\n return null;\n }\n\n return {\n code,\n message,\n requestId,\n upstreamCode,\n };\n}\n","import type { SpaceMeta } from \"@openmeld/protocol\";\nimport { spaceMetaSchema } from \"@openmeld/schemas\";\n\ntype SpaceMetaParseOperation =\n | \"createSpaceMeta\"\n | \"fetchSpaceMeta\"\n | \"updateSpaceMeta\";\n\nexport function parseSpaceMetaPayload(input: {\n data: unknown;\n endpoint: string;\n operation: SpaceMetaParseOperation;\n}): SpaceMeta {\n try {\n const validation = spaceMetaSchema.safeParse(input.data);\n if (!validation.success) {\n const reason =\n validation.error.issues[0]?.message ??\n \"space meta payload does not match schema\";\n throw new Error(reason);\n }\n return validation.data;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(\n `${input.operation} received invalid response payload from ${input.endpoint}: ${reason}; raw=${JSON.stringify(input.data)}`\n );\n }\n}\n\nexport function parseSpaceMetaResponse(input: {\n raw: string;\n endpoint: string;\n operation: Extract<\n SpaceMetaParseOperation,\n \"fetchSpaceMeta\" | \"updateSpaceMeta\"\n >;\n}): SpaceMeta {\n try {\n return parseSpaceMetaPayload({\n data: JSON.parse(input.raw) as unknown,\n endpoint: input.endpoint,\n operation: input.operation,\n });\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(\n `${input.operation} received invalid response payload from ${input.endpoint}: ${reason}; raw=${input.raw}`\n );\n }\n}\n","import type { SpaceMeta } from \"@openmeld/protocol\";\nimport type { OpenMeldRequestContext } from \"@openmeld/schemas/types\";\nimport { buildOpenMeldRequestContextHeadersWithAuth } from \"../config/request-headers\";\nimport { toSpaceMetaUrl } from \"../protocol/urls\";\nimport { fetchSpaceRequestWithTimeout } from \"./fetch-with-timeout\";\nimport { readGatewayTextResponse } from \"./gateway-response\";\nimport { parseSpaceMetaResponse } from \"./space-meta-response\";\n\ntype SpaceMetaApiInput = {\n requestContext: OpenMeldRequestContext;\n baseUrl: string;\n space: string;\n password?: string;\n};\n\nexport async function fetchSpaceMeta(\n input: SpaceMetaApiInput\n): Promise<SpaceMeta> {\n const endpoint = toSpaceMetaUrl(input.baseUrl, input.space);\n const response = await fetchSpaceRequestWithTimeout({\n url: endpoint,\n operation: \"space.fetch_meta\",\n init: {\n method: \"GET\",\n headers: await buildOpenMeldRequestContextHeadersWithAuth({\n requestUrl: endpoint,\n requestContext: input.requestContext,\n spacePassword: input.password,\n }),\n },\n });\n const raw = await readGatewayTextResponse({ response });\n\n return parseSpaceMetaResponse({\n raw,\n endpoint,\n operation: \"fetchSpaceMeta\",\n });\n}\n\nexport async function updateSpaceMeta(\n input: SpaceMetaApiInput & {\n purpose?: string;\n guide?: string;\n }\n): Promise<SpaceMeta> {\n const endpoint = toSpaceMetaUrl(input.baseUrl, input.space);\n const headers = await buildOpenMeldRequestContextHeadersWithAuth({\n requestUrl: endpoint,\n requestContext: input.requestContext,\n spacePassword: input.password,\n });\n headers[\"content-type\"] = \"application/json\";\n\n const response = await fetchSpaceRequestWithTimeout({\n url: endpoint,\n operation: \"space.update_meta\",\n init: {\n method: \"PATCH\",\n headers,\n body: JSON.stringify({\n ...(input.purpose === undefined ? {} : { purpose: input.purpose }),\n ...(input.guide === undefined ? {} : { guide: input.guide }),\n }),\n },\n });\n const raw = await readGatewayTextResponse({ response });\n\n return parseSpaceMetaResponse({\n raw,\n endpoint,\n operation: \"updateSpaceMeta\",\n });\n}\n"],"mappings":"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"}