openmeld 0.3.292 → 0.3.294

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 (120) hide show
  1. package/dist/{add-me-membership-DzyYrmrJ.js → add-me-membership-C4nE3q77.js} +2 -2
  2. package/dist/{add-me-membership-DzyYrmrJ.js.map → add-me-membership-C4nE3q77.js.map} +1 -1
  3. package/dist/{agents-Cx-N8w-U.js → agents-n8zJg-mP.js} +9 -9
  4. package/dist/{agents-Cx-N8w-U.js.map → agents-n8zJg-mP.js.map} +1 -1
  5. package/dist/{api-client-foundation-D4qt8-I7.js → api-client-foundation-CRQZIYVN.js} +5 -5
  6. package/dist/{api-client-foundation-D4qt8-I7.js.map → api-client-foundation-CRQZIYVN.js.map} +1 -1
  7. package/dist/{api-client-foundation-f11_Z91X.js → api-client-foundation-DcWfF50S.js} +1 -1
  8. package/dist/{auth-session-GYsWoDuJ.js → auth-session-QFK36vfX.js} +2 -2
  9. package/dist/{auth-session-GYsWoDuJ.js.map → auth-session-QFK36vfX.js.map} +1 -1
  10. package/dist/auth-session-WM8aC6bg.js +3 -0
  11. package/dist/{channel-DfaHRitM.js → channel-D1NKTdY0.js} +3 -3
  12. package/dist/{channel-DfaHRitM.js.map → channel-D1NKTdY0.js.map} +1 -1
  13. package/dist/{cli-binary-manifest-t_TXQ6-t.js → cli-binary-manifest-DhSiC1mr.js} +2 -2
  14. package/dist/{cli-binary-manifest-t_TXQ6-t.js.map → cli-binary-manifest-DhSiC1mr.js.map} +1 -1
  15. package/dist/{cloud-computer-KEqLjDMV.js → cloud-computer-BXo_qq3t.js} +5 -5
  16. package/dist/{cloud-computer-KEqLjDMV.js.map → cloud-computer-BXo_qq3t.js.map} +1 -1
  17. package/dist/{command-LBzVb7R2.js → command-tf3JS9zQ.js} +17 -17
  18. package/dist/{command-LBzVb7R2.js.map → command-tf3JS9zQ.js.map} +1 -1
  19. package/dist/{computer-connection-review-D32sB8oo.js → computer-connection-review-Du83vbfo.js} +4 -4
  20. package/dist/{computer-connection-review-D32sB8oo.js.map → computer-connection-review-Du83vbfo.js.map} +1 -1
  21. package/dist/{computer-disconnect-DJe5veAd.js → computer-disconnect-DwEkzrH8.js} +7 -7
  22. package/dist/{computer-disconnect-DJe5veAd.js.map → computer-disconnect-DwEkzrH8.js.map} +1 -1
  23. package/dist/{computer-setup-continuation-SasfkSwQ.js → computer-setup-continuation-D1OrA5G_.js} +5 -5
  24. package/dist/{computer-setup-continuation-SasfkSwQ.js.map → computer-setup-continuation-D1OrA5G_.js.map} +1 -1
  25. package/dist/{computer-update-wait-CAvCeH6l.js → computer-update-wait-D4ly51hV.js} +4 -4
  26. package/dist/{computer-update-wait-CAvCeH6l.js.map → computer-update-wait-D4ly51hV.js.map} +1 -1
  27. package/dist/{context-CPKBlAps.js → context-DqEUJy_k.js} +5 -5
  28. package/dist/{context-CPKBlAps.js.map → context-DqEUJy_k.js.map} +1 -1
  29. package/dist/{daemon-device-id-B-iuoFzM.js → daemon-device-id-DLKuN3Eo.js} +3 -3
  30. package/dist/{daemon-device-id-B-iuoFzM.js.map → daemon-device-id-DLKuN3Eo.js.map} +1 -1
  31. package/dist/{daemon-lifecycle-journal-BaI2xxdH.js → daemon-lifecycle-journal-BV6D0rSF.js} +3 -3
  32. package/dist/{daemon-lifecycle-journal-BaI2xxdH.js.map → daemon-lifecycle-journal-BV6D0rSF.js.map} +1 -1
  33. package/dist/{daemon-service-runtime-gMHnEHnq.js → daemon-service-runtime-BKUCCet9.js} +90 -6
  34. package/dist/daemon-service-runtime-BKUCCet9.js.map +1 -0
  35. package/dist/{daemon-service-update-state-BclTmkAC.js → daemon-service-update-state-CtzTzni1.js} +2 -2
  36. package/dist/{daemon-service-update-state-BclTmkAC.js.map → daemon-service-update-state-CtzTzni1.js.map} +1 -1
  37. package/dist/{dispatch-owned-runtime-DlpQwB6N.js → dispatch-owned-runtime-B6VEu6Ak.js} +10 -10
  38. package/dist/{dispatch-owned-runtime-DlpQwB6N.js.map → dispatch-owned-runtime-B6VEu6Ak.js.map} +1 -1
  39. package/dist/dist-BQj7QeWU.js +34 -0
  40. package/dist/{dist-BA8Q1IB5.js → dist-DUg7lB-e.js} +1 -1
  41. package/dist/{dist-B08nRCGz.js → dist-DsyrZzyU.js} +5 -5
  42. package/dist/{dist-B08nRCGz.js.map → dist-DsyrZzyU.js.map} +1 -1
  43. package/dist/{dist-W42Tu_IN.js → dist-WejKqo8X.js} +2 -2
  44. package/dist/{dist-D_FzuWN-.js → dist-zY7dD_tQ.js} +2 -2
  45. package/dist/{dist-D_FzuWN-.js.map → dist-zY7dD_tQ.js.map} +1 -1
  46. package/dist/{dual-view-guide-catalog-BZtmfAkF.js → dual-view-guide-catalog-cokJ8-5D.js} +4 -4
  47. package/dist/{dual-view-guide-catalog-BZtmfAkF.js.map → dual-view-guide-catalog-cokJ8-5D.js.map} +1 -1
  48. package/dist/{elapsed-time-FUf-2Hna.js → elapsed-time-CviuvW6T.js} +2 -2
  49. package/dist/{elapsed-time-FUf-2Hna.js.map → elapsed-time-CviuvW6T.js.map} +1 -1
  50. package/dist/{entry-BM8DA2U-.js → entry-Dej02SVj.js} +8 -8
  51. package/dist/{entry-BM8DA2U-.js.map → entry-Dej02SVj.js.map} +1 -1
  52. package/dist/{installation-inventory-BBR228VY.js → installation-inventory-C8O-r8eI.js} +3 -3
  53. package/dist/{installation-inventory-BBR228VY.js.map → installation-inventory-C8O-r8eI.js.map} +1 -1
  54. package/dist/{installer-D4dGpL9N.js → installer-B_Vvfk67.js} +2 -2
  55. package/dist/{installer-D4dGpL9N.js.map → installer-B_Vvfk67.js.map} +1 -1
  56. package/dist/{local-components-DlEpUgN3.js → local-components-BpA9Lc4v.js} +48 -2
  57. package/dist/local-components-BpA9Lc4v.js.map +1 -0
  58. package/dist/{meta-api-DgLrYkyU.js → meta-api-brhELEyk.js} +7 -7
  59. package/dist/{meta-api-DgLrYkyU.js.map → meta-api-brhELEyk.js.map} +1 -1
  60. package/dist/{openmeld-CinzKNUc.js → openmeld-BtdOh4Rn.js} +37 -37
  61. package/dist/{openmeld-CinzKNUc.js.map → openmeld-BtdOh4Rn.js.map} +1 -1
  62. package/dist/{openmeld-environment-target-BOA_c8yO.js → openmeld-environment-target-mLK2dK1_.js} +2 -2
  63. package/dist/{openmeld-environment-target-BOA_c8yO.js.map → openmeld-environment-target-mLK2dK1_.js.map} +1 -1
  64. package/dist/{openmeld-maintenance-worker-D0hTBra6.js → openmeld-maintenance-worker-Cu-c8PjX.js} +12 -11
  65. package/dist/{openmeld-maintenance-worker-D0hTBra6.js.map → openmeld-maintenance-worker-Cu-c8PjX.js.map} +1 -1
  66. package/dist/{openmeld-tools-update-attempt-state-D8oDuOp9.js → openmeld-tools-update-attempt-state--4fS27OC.js} +2 -2
  67. package/dist/{openmeld-tools-update-attempt-state-D8oDuOp9.js.map → openmeld-tools-update-attempt-state--4fS27OC.js.map} +1 -1
  68. package/dist/{openmeld-tools-update-coordinator-ChqDoSKS.js → openmeld-tools-update-coordinator-y37jBxio.js} +39 -67
  69. package/dist/openmeld-tools-update-coordinator-y37jBxio.js.map +1 -0
  70. package/dist/{openmeld-tools-update-failure-2jySZ04B.js → openmeld-tools-update-failure-B4OLQAq7.js} +2 -2
  71. package/dist/{openmeld-tools-update-failure-2jySZ04B.js.map → openmeld-tools-update-failure-B4OLQAq7.js.map} +1 -1
  72. package/dist/{openmeld-tools-update-join-CDWWs9KY.js → openmeld-tools-update-join-B6HcSSiK.js} +11 -5
  73. package/dist/openmeld-tools-update-join-B6HcSSiK.js.map +1 -0
  74. package/dist/{openmeld-tools-update-process-frame-Dj3k5JHe.js → openmeld-tools-update-process-frame-CGFA81PP.js} +3 -3
  75. package/dist/{openmeld-tools-update-process-frame-Dj3k5JHe.js.map → openmeld-tools-update-process-frame-CGFA81PP.js.map} +1 -1
  76. package/dist/{openmeld-tools-update-process-frame-B-RacMxU.js → openmeld-tools-update-process-frame-D4LEFHvl.js} +1 -1
  77. package/dist/openmeld.js +6 -6
  78. package/dist/{prepare-provider-runtime-CQ7ZJMG8.js → prepare-provider-runtime-Cdm1_kJt.js} +9 -9
  79. package/dist/{prepare-provider-runtime-CQ7ZJMG8.js.map → prepare-provider-runtime-Cdm1_kJt.js.map} +1 -1
  80. package/dist/{prepare-session-executor-CovScwhU.js → prepare-session-executor-BnBsq6Vg.js} +20 -20
  81. package/dist/{prepare-session-executor-CovScwhU.js.map → prepare-session-executor-BnBsq6Vg.js.map} +1 -1
  82. package/dist/{presenter-BIwIweT9.js → presenter-DqdYrUMa.js} +2 -2
  83. package/dist/{presenter-BIwIweT9.js.map → presenter-DqdYrUMa.js.map} +1 -1
  84. package/dist/{process-channel-Dx1KqiZj.js → process-channel-Vz_ntXXU.js} +2 -2
  85. package/dist/{process-channel-Dx1KqiZj.js.map → process-channel-Vz_ntXXU.js.map} +1 -1
  86. package/dist/{runtime-D0ejcBmE.js → runtime-MZYGkNRp.js} +17 -17
  87. package/dist/{runtime-D0ejcBmE.js.map → runtime-MZYGkNRp.js.map} +1 -1
  88. package/dist/{runtime-agent-controller-reporting-submission-BgAI8B4L.js → runtime-agent-controller-reporting-submission-CGskliia.js} +7 -7
  89. package/dist/{runtime-agent-controller-reporting-submission-BgAI8B4L.js.map → runtime-agent-controller-reporting-submission-CGskliia.js.map} +1 -1
  90. package/dist/{runtime-transport-DNkqgRhX.js → runtime-transport-Ca0cGpAY.js} +2 -2
  91. package/dist/{runtime-transport-DNkqgRhX.js.map → runtime-transport-Ca0cGpAY.js.map} +1 -1
  92. package/dist/{sensitive-operation-credentials-Dsps0o1U.js → sensitive-operation-credentials-D7aFniHa.js} +3 -3
  93. package/dist/{sensitive-operation-credentials-Dsps0o1U.js.map → sensitive-operation-credentials-D7aFniHa.js.map} +1 -1
  94. package/dist/{service-Cb8xFGDs.js → service-B-jrhCpV.js} +106 -63
  95. package/dist/service-B-jrhCpV.js.map +1 -0
  96. package/dist/{service-account-authorization-DbbHAoMV.js → service-account-authorization-CdUOvV3c.js} +3 -3
  97. package/dist/{service-account-authorization-DbbHAoMV.js.map → service-account-authorization-CdUOvV3c.js.map} +1 -1
  98. package/dist/{service-account-control-DSGwWnIO.js → service-account-control-Sh8RsnY4.js} +8 -8
  99. package/dist/{service-account-control-DSGwWnIO.js.map → service-account-control-Sh8RsnY4.js.map} +1 -1
  100. package/dist/{service-control-capabilities-CM3-R3Xt.js → service-control-capabilities-BqgOUxQ-.js} +2 -2
  101. package/dist/{service-control-capabilities-CM3-R3Xt.js.map → service-control-capabilities-BqgOUxQ-.js.map} +1 -1
  102. package/dist/{service-control-capabilities-BW2hiUog.js → service-control-capabilities-_-vnkLh1.js} +1 -1
  103. package/dist/{state-MwOfpQOL.js → state-Dz2UWXBu.js} +2 -2
  104. package/dist/{state-MwOfpQOL.js.map → state-Dz2UWXBu.js.map} +1 -1
  105. package/dist/{updates-api-B6gsuJ7E.js → updates-api-CXRhfS1w.js} +13 -13
  106. package/dist/{updates-api-B6gsuJ7E.js.map → updates-api-CXRhfS1w.js.map} +1 -1
  107. package/dist/{upgrade-DHLGtpdq.js → upgrade-BtpXCy-Y.js} +22 -12
  108. package/dist/upgrade-BtpXCy-Y.js.map +1 -0
  109. package/dist/upgrade-CvNhk6zk.js +3 -0
  110. package/dist/windows/openmeld-windows-process.exe +0 -0
  111. package/package.json +8 -8
  112. package/dist/auth-session-BrKZEvdi.js +0 -3
  113. package/dist/daemon-service-runtime-gMHnEHnq.js.map +0 -1
  114. package/dist/dist-CVuix2Ne.js +0 -34
  115. package/dist/local-components-DlEpUgN3.js.map +0 -1
  116. package/dist/openmeld-tools-update-coordinator-ChqDoSKS.js.map +0 -1
  117. package/dist/openmeld-tools-update-join-CDWWs9KY.js.map +0 -1
  118. package/dist/service-Cb8xFGDs.js.map +0 -1
  119. package/dist/upgrade-D2Dlqtxw.js +0 -3
  120. package/dist/upgrade-DHLGtpdq.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { ot as formatInlineOpenMeldCliCommands, st as formatOpenMeldCliCommand } from "./auth-session-GYsWoDuJ.js";
3
+ import { ot as formatInlineOpenMeldCliCommands, st as formatOpenMeldCliCommand } from "./auth-session-QFK36vfX.js";
4
4
  import { isCancel, select } from "@clack/prompts";
5
5
  //#region src/runtime/interaction.ts
6
6
  function canUseInteractivePrompts(context) {
@@ -119,4 +119,4 @@ function formatElapsedTime(durationMs) {
119
119
  //#endregion
120
120
  export { formatDaemonServiceDowngradeBlockedRecommendation as a, formatDaemonServiceMissingRecommendation as c, formatDaemonServiceMissingStatus as d, getDaemonDowngradeBlockedTitle as f, formatDaemonInstallFailedMessage as i, formatDaemonServiceMissingRunStepOne as l, canUseInteractivePrompts as m, resolveElapsedTimeMs as n, formatDaemonServiceMissingAction as o, runDaemonInstallDecisionPrompt as p, formatDaemonDowngradeBlockedNextStep as r, formatDaemonServiceMissingMeaning as s, formatElapsedTime as t, formatDaemonServiceMissingRunStepTwo as u };
121
121
 
122
- //# sourceMappingURL=elapsed-time-FUf-2Hna.js.map
122
+ //# sourceMappingURL=elapsed-time-CviuvW6T.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"elapsed-time-FUf-2Hna.js","names":[],"sources":["../src/runtime/interaction.ts","../src/system/local-service-install-attention.ts","../src/ui/elapsed-time.ts"],"sourcesContent":["import type { RuntimeContext } from \"./types\";\n\nexport function canUseInteractivePrompts(context: RuntimeContext): boolean {\n return context.resolvedView === \"human\" && context.interactive;\n}\n","import { isCancel, select } from \"@clack/prompts\";\nimport {\n formatInlineOpenMeldCliCommands,\n formatOpenMeldCliCommand,\n} from \"../runtime/cli-entry-command\";\n\nexport const DAEMON_INSTALL_DECISION_CHOICE = {\n install: \"install\",\n notNow: \"not_now\",\n} as const;\n\nexport type DaemonInstallDecisionKind = \"missing\" | \"outdated\";\n\nexport type DaemonInstallDecisionChoice =\n | (typeof DAEMON_INSTALL_DECISION_CHOICE)[keyof typeof DAEMON_INSTALL_DECISION_CHOICE]\n | \"cancelled\";\n\ntype DaemonVersionInput = {\n installedVersion?: string;\n expectedVersion: string;\n};\n\ntype DaemonInstallDecisionPromptConfig = {\n message: string;\n initialValue: (typeof DAEMON_INSTALL_DECISION_CHOICE)[\"install\"];\n options: Array<{\n value:\n | (typeof DAEMON_INSTALL_DECISION_CHOICE)[\"install\"]\n | (typeof DAEMON_INSTALL_DECISION_CHOICE)[\"notNow\"];\n label: string;\n hint?: string;\n }>;\n};\n\nconst DAEMON_INSTALL_COMMAND = \"openmeld service install\";\nconst DAEMON_REPAIR_COMMAND = \"openmeld service repair\";\nconst DAEMON_UPGRADE_COMMAND = \"openmeld upgrade\";\nconst DAEMON_AUTO_INSTALL_ALWAYS_FLAG = \"`--service-auto-install always`\";\nconst DAEMON_DECISION_RECOMMENDED_HINT = \"Recommended\";\n\nconst DAEMON_INSTALL_DECISION_COPY = {\n missing: {\n question: \"OpenMeld Service is missing. Install it now?\",\n explanation: \"Without it, this computer can't receive local Wake work.\",\n primaryLabel: \"Yes, install it for me\",\n deferred:\n \"OpenMeld Service is still missing. Install it later with `openmeld service install` so this computer can receive local Wake work.\",\n failed:\n \"OpenMeld Service could not be installed. Run `openmeld service install` so this computer can receive local Wake work.\",\n },\n outdated: {\n question: \"OpenMeld Service update required. Update it now?\",\n explanation:\n \"This service artifact is not compatible with current local Wake execution.\",\n primaryLabel: \"Yes, update it for me\",\n deferred:\n \"OpenMeld Service update skipped. Run `openmeld service update` before using local Wake work.\",\n failed: \"OpenMeld Service was not updated. Run `openmeld service update`.\",\n },\n} as const satisfies Record<\n DaemonInstallDecisionKind,\n {\n question: string;\n explanation: string;\n primaryLabel: string;\n deferred: string;\n failed: string;\n }\n>;\n\nexport function buildDaemonInstallDecisionPromptConfig(input: {\n kind: DaemonInstallDecisionKind;\n installedVersion?: string;\n expectedVersion?: string;\n}): DaemonInstallDecisionPromptConfig {\n const copy = DAEMON_INSTALL_DECISION_COPY[input.kind];\n const detailLine =\n input.kind === \"outdated\" &&\n typeof input.installedVersion === \"string\" &&\n typeof input.expectedVersion === \"string\"\n ? `Installed v${input.installedVersion}, expected v${input.expectedVersion}.`\n : null;\n return {\n message: [copy.question, copy.explanation, detailLine]\n .filter((line) => typeof line === \"string\" && line.length > 0)\n .join(\"\\n\"),\n initialValue: DAEMON_INSTALL_DECISION_CHOICE.install,\n options: [\n {\n value: DAEMON_INSTALL_DECISION_CHOICE.install,\n label: copy.primaryLabel,\n hint: DAEMON_DECISION_RECOMMENDED_HINT,\n },\n {\n value: DAEMON_INSTALL_DECISION_CHOICE.notNow,\n label: \"Not now\",\n },\n ],\n };\n}\n\nexport async function promptForDaemonInstallDecision(input: {\n kind: DaemonInstallDecisionKind;\n installedVersion?: string;\n expectedVersion?: string;\n}): Promise<DaemonInstallDecisionChoice> {\n const choice = await select(buildDaemonInstallDecisionPromptConfig(input));\n if (isCancel(choice)) {\n return \"cancelled\";\n }\n return choice === DAEMON_INSTALL_DECISION_CHOICE.install\n ? DAEMON_INSTALL_DECISION_CHOICE.install\n : DAEMON_INSTALL_DECISION_CHOICE.notNow;\n}\n\nexport async function runDaemonInstallDecisionPrompt(input: {\n kind: DaemonInstallDecisionKind;\n installedVersion?: string;\n expectedVersion?: string;\n emitLine: (text: string) => Promise<void> | void;\n installService: () => Promise<void>;\n}): Promise<\"install\" | \"not_now\" | \"cancelled\" | \"failed\"> {\n const decision = await promptForDaemonInstallDecision({\n kind: input.kind,\n installedVersion: input.installedVersion,\n expectedVersion: input.expectedVersion,\n });\n if (decision === DAEMON_INSTALL_DECISION_CHOICE.install) {\n try {\n await input.installService();\n return \"install\";\n } catch {\n await input.emitLine(formatDaemonInstallFailedMessage(input.kind));\n return \"failed\";\n }\n }\n\n if (decision === \"cancelled\") {\n return \"cancelled\";\n }\n\n await input.emitLine(formatDaemonInstallDeferredMessage(input.kind));\n return decision;\n}\n\nexport function formatDaemonInstallDeferredMessage(\n kind: DaemonInstallDecisionKind\n): string {\n return formatInlineOpenMeldCliCommands(\n DAEMON_INSTALL_DECISION_COPY[kind].deferred\n );\n}\n\nexport function formatDaemonInstallFailedMessage(\n kind: DaemonInstallDecisionKind\n): string {\n return formatInlineOpenMeldCliCommands(\n DAEMON_INSTALL_DECISION_COPY[kind].failed\n );\n}\n\nexport function formatDaemonServiceMissingRecommendation(): string {\n return \"OpenMeld Service is not installed yet. Install it so this computer can receive local Wake work.\";\n}\n\nexport function formatDaemonServiceInstallRecommendationNextStep(): string {\n return `Run \\`${formatOpenMeldCliCommand(DAEMON_INSTALL_COMMAND)}\\` now, or re-run command with ${DAEMON_AUTO_INSTALL_ALWAYS_FLAG}.`;\n}\n\nexport function formatDaemonServiceMissingStatus(): string {\n return \"Not installed yet.\";\n}\n\nexport function formatDaemonServiceMissingMeaning(): string {\n return \"Missing — install OpenMeld Service before this computer can receive local Wake work.\";\n}\n\nexport function formatDaemonServiceMissingAction(): string {\n return `Run \\`${formatOpenMeldCliCommand(DAEMON_INSTALL_COMMAND)}\\` to set it up.`;\n}\n\nexport function formatDaemonServiceMissingRunStepOne(): string {\n return `\\`${formatOpenMeldCliCommand(DAEMON_INSTALL_COMMAND)}\\``;\n}\n\nexport function formatDaemonServiceMissingRunStepTwo(): string {\n return `\\`${formatOpenMeldCliCommand(\"openmeld service start\")}\\``;\n}\n\nexport function formatDaemonServiceOutdatedRecommendation(\n input: DaemonVersionInput\n): string {\n const installedVersion = input.installedVersion ?? \"unknown\";\n return `OpenMeld Service version differs from this CLI (installed v${installedVersion}, CLI v${input.expectedVersion}). This is diagnostic unless service compatibility fails.`;\n}\n\nexport function formatDaemonServiceOutdatedStatus(\n input: DaemonVersionInput\n): string {\n const installedVersion = input.installedVersion ?? \"unknown\";\n return `Version differs from this CLI (installed v${installedVersion}, CLI v${input.expectedVersion}).`;\n}\n\nexport function formatDaemonServiceDowngradeBlockedRecommendation(\n input: DaemonVersionInput\n): string {\n if (input.installedVersion) {\n return `OpenMeld Service is already newer (installed v${input.installedVersion}, current CLI v${input.expectedVersion}). OpenMeld will not downgrade it automatically. Run \\`${formatOpenMeldCliCommand(DAEMON_UPGRADE_COMMAND)}\\`.`;\n }\n return `OpenMeld Service is already newer than this CLI. OpenMeld will not downgrade it automatically. Run \\`${formatOpenMeldCliCommand(DAEMON_UPGRADE_COMMAND)}\\`.`;\n}\n\nexport function getDaemonDowngradeBlockedTitle(): string {\n return \"⛔ OpenMeld Service Downgrade Blocked\";\n}\n\nexport function formatDaemonDowngradeBlockedNextStep(): string {\n return `Run \\`${formatOpenMeldCliCommand(DAEMON_UPGRADE_COMMAND)}\\`.`;\n}\n\nexport function formatDaemonStartupRepairNotice(): string {\n return `Run \\`${formatOpenMeldCliCommand(DAEMON_REPAIR_COMMAND)}\\` to repair it now.`;\n}\n","export const MIN_VISIBLE_ELAPSED_TIME_MS = 100;\n\nexport function resolveElapsedTimeMs(\n startedAtMs: number,\n currentTimeMs = Date.now()\n): number {\n return Math.max(0, currentTimeMs - startedAtMs);\n}\n\nexport function formatElapsedTime(durationMs: number): string {\n const seconds = durationMs / 1000;\n return seconds < 10 ? `${seconds.toFixed(1)}s` : `${Math.round(seconds)}s`;\n}\n"],"mappings":";;;;;AAEA,SAAgB,yBAAyB,SAAkC;CACzE,OAAO,QAAQ,iBAAiB,WAAW,QAAQ;AACrD;;;ACEA,MAAa,iCAAiC;CAC5C,SAAS;CACT,QAAQ;AACV;AAyBA,MAAM,yBAAyB;AAE/B,MAAM,yBAAyB;AAE/B,MAAM,mCAAmC;AAEzC,MAAM,+BAA+B;CACnC,SAAS;EACP,UAAU;EACV,aAAa;EACb,cAAc;EACd,UACE;EACF,QACE;CACJ;CACA,UAAU;EACR,UAAU;EACV,aACE;EACF,cAAc;EACd,UACE;EACF,QAAQ;CACV;AACF;AAWA,SAAgB,uCAAuC,OAIjB;CACpC,MAAM,OAAO,6BAA6B,MAAM;CAChD,MAAM,aACJ,MAAM,SAAS,cACf,OAAO,MAAM,qBAAqB,YAClC,OAAO,MAAM,oBAAoB,WAC7B,cAAc,MAAM,iBAAiB,cAAc,MAAM,gBAAgB,KACzE;CACN,OAAO;EACL,SAAS;GAAC,KAAK;GAAU,KAAK;GAAa;EAAU,CAAC,CACnD,QAAQ,SAAS,OAAO,SAAS,YAAY,KAAK,SAAS,CAAC,CAAC,CAC7D,KAAK,IAAI;EACZ,cAAc,+BAA+B;EAC7C,SAAS,CACP;GACE,OAAO,+BAA+B;GACtC,OAAO,KAAK;GACZ,MAAM;EACR,GACA;GACE,OAAO,+BAA+B;GACtC,OAAO;EACT,CACF;CACF;AACF;AAEA,eAAsB,+BAA+B,OAIZ;CACvC,MAAM,SAAS,MAAM,OAAO,uCAAuC,KAAK,CAAC;CACzE,IAAI,SAAS,MAAM,GACjB,OAAO;CAET,OAAO,WAAW,+BAA+B,UAC7C,+BAA+B,UAC/B,+BAA+B;AACrC;AAEA,eAAsB,+BAA+B,OAMO;CAC1D,MAAM,WAAW,MAAM,+BAA+B;EACpD,MAAM,MAAM;EACZ,kBAAkB,MAAM;EACxB,iBAAiB,MAAM;CACzB,CAAC;CACD,IAAI,aAAa,+BAA+B,SAC9C,IAAI;EACF,MAAM,MAAM,eAAe;EAC3B,OAAO;CACT,QAAQ;EACN,MAAM,MAAM,SAAS,iCAAiC,MAAM,IAAI,CAAC;EACjE,OAAO;CACT;CAGF,IAAI,aAAa,aACf,OAAO;CAGT,MAAM,MAAM,SAAS,mCAAmC,MAAM,IAAI,CAAC;CACnE,OAAO;AACT;AAEA,SAAgB,mCACd,MACQ;CACR,OAAO,gCACL,6BAA6B,KAAK,CAAC,QACrC;AACF;AAEA,SAAgB,iCACd,MACQ;CACR,OAAO,gCACL,6BAA6B,KAAK,CAAC,MACrC;AACF;AAEA,SAAgB,2CAAmD;CACjE,OAAO;AACT;AAMA,SAAgB,mCAA2C;CACzD,OAAO;AACT;AAEA,SAAgB,oCAA4C;CAC1D,OAAO;AACT;AAEA,SAAgB,mCAA2C;CACzD,OAAO,SAAS,yBAAyB,sBAAsB,EAAE;AACnE;AAEA,SAAgB,uCAA+C;CAC7D,OAAO,KAAK,yBAAyB,sBAAsB,EAAE;AAC/D;AAEA,SAAgB,uCAA+C;CAC7D,OAAO,KAAK,yBAAyB,wBAAwB,EAAE;AACjE;AAgBA,SAAgB,kDACd,OACQ;CACR,IAAI,MAAM,kBACR,OAAO,iDAAiD,MAAM,iBAAiB,iBAAiB,MAAM,gBAAgB,yDAAyD,yBAAyB,sBAAsB,EAAE;CAElO,OAAO,wGAAwG,yBAAyB,sBAAsB,EAAE;AAClK;AAEA,SAAgB,iCAAyC;CACvD,OAAO;AACT;AAEA,SAAgB,uCAA+C;CAC7D,OAAO,SAAS,yBAAyB,sBAAsB,EAAE;AACnE;;;ACxNA,SAAgB,qBACd,aACA,gBAAgB,KAAK,IAAI,GACjB;CACR,OAAO,KAAK,IAAI,GAAG,gBAAgB,WAAW;AAChD;AAEA,SAAgB,kBAAkB,YAA4B;CAC5D,MAAM,UAAU,aAAa;CAC7B,OAAO,UAAU,KAAK,GAAG,QAAQ,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,MAAM,OAAO,EAAE;AAC1E"}
1
+ {"version":3,"file":"elapsed-time-CviuvW6T.js","names":[],"sources":["../src/runtime/interaction.ts","../src/system/local-service-install-attention.ts","../src/ui/elapsed-time.ts"],"sourcesContent":["import type { RuntimeContext } from \"./types\";\n\nexport function canUseInteractivePrompts(context: RuntimeContext): boolean {\n return context.resolvedView === \"human\" && context.interactive;\n}\n","import { isCancel, select } from \"@clack/prompts\";\nimport {\n formatInlineOpenMeldCliCommands,\n formatOpenMeldCliCommand,\n} from \"../runtime/cli-entry-command\";\n\nexport const DAEMON_INSTALL_DECISION_CHOICE = {\n install: \"install\",\n notNow: \"not_now\",\n} as const;\n\nexport type DaemonInstallDecisionKind = \"missing\" | \"outdated\";\n\nexport type DaemonInstallDecisionChoice =\n | (typeof DAEMON_INSTALL_DECISION_CHOICE)[keyof typeof DAEMON_INSTALL_DECISION_CHOICE]\n | \"cancelled\";\n\ntype DaemonVersionInput = {\n installedVersion?: string;\n expectedVersion: string;\n};\n\ntype DaemonInstallDecisionPromptConfig = {\n message: string;\n initialValue: (typeof DAEMON_INSTALL_DECISION_CHOICE)[\"install\"];\n options: Array<{\n value:\n | (typeof DAEMON_INSTALL_DECISION_CHOICE)[\"install\"]\n | (typeof DAEMON_INSTALL_DECISION_CHOICE)[\"notNow\"];\n label: string;\n hint?: string;\n }>;\n};\n\nconst DAEMON_INSTALL_COMMAND = \"openmeld service install\";\nconst DAEMON_REPAIR_COMMAND = \"openmeld service repair\";\nconst DAEMON_UPGRADE_COMMAND = \"openmeld upgrade\";\nconst DAEMON_AUTO_INSTALL_ALWAYS_FLAG = \"`--service-auto-install always`\";\nconst DAEMON_DECISION_RECOMMENDED_HINT = \"Recommended\";\n\nconst DAEMON_INSTALL_DECISION_COPY = {\n missing: {\n question: \"OpenMeld Service is missing. Install it now?\",\n explanation: \"Without it, this computer can't receive local Wake work.\",\n primaryLabel: \"Yes, install it for me\",\n deferred:\n \"OpenMeld Service is still missing. Install it later with `openmeld service install` so this computer can receive local Wake work.\",\n failed:\n \"OpenMeld Service could not be installed. Run `openmeld service install` so this computer can receive local Wake work.\",\n },\n outdated: {\n question: \"OpenMeld Service update required. Update it now?\",\n explanation:\n \"This service artifact is not compatible with current local Wake execution.\",\n primaryLabel: \"Yes, update it for me\",\n deferred:\n \"OpenMeld Service update skipped. Run `openmeld service update` before using local Wake work.\",\n failed: \"OpenMeld Service was not updated. Run `openmeld service update`.\",\n },\n} as const satisfies Record<\n DaemonInstallDecisionKind,\n {\n question: string;\n explanation: string;\n primaryLabel: string;\n deferred: string;\n failed: string;\n }\n>;\n\nexport function buildDaemonInstallDecisionPromptConfig(input: {\n kind: DaemonInstallDecisionKind;\n installedVersion?: string;\n expectedVersion?: string;\n}): DaemonInstallDecisionPromptConfig {\n const copy = DAEMON_INSTALL_DECISION_COPY[input.kind];\n const detailLine =\n input.kind === \"outdated\" &&\n typeof input.installedVersion === \"string\" &&\n typeof input.expectedVersion === \"string\"\n ? `Installed v${input.installedVersion}, expected v${input.expectedVersion}.`\n : null;\n return {\n message: [copy.question, copy.explanation, detailLine]\n .filter((line) => typeof line === \"string\" && line.length > 0)\n .join(\"\\n\"),\n initialValue: DAEMON_INSTALL_DECISION_CHOICE.install,\n options: [\n {\n value: DAEMON_INSTALL_DECISION_CHOICE.install,\n label: copy.primaryLabel,\n hint: DAEMON_DECISION_RECOMMENDED_HINT,\n },\n {\n value: DAEMON_INSTALL_DECISION_CHOICE.notNow,\n label: \"Not now\",\n },\n ],\n };\n}\n\nexport async function promptForDaemonInstallDecision(input: {\n kind: DaemonInstallDecisionKind;\n installedVersion?: string;\n expectedVersion?: string;\n}): Promise<DaemonInstallDecisionChoice> {\n const choice = await select(buildDaemonInstallDecisionPromptConfig(input));\n if (isCancel(choice)) {\n return \"cancelled\";\n }\n return choice === DAEMON_INSTALL_DECISION_CHOICE.install\n ? DAEMON_INSTALL_DECISION_CHOICE.install\n : DAEMON_INSTALL_DECISION_CHOICE.notNow;\n}\n\nexport async function runDaemonInstallDecisionPrompt(input: {\n kind: DaemonInstallDecisionKind;\n installedVersion?: string;\n expectedVersion?: string;\n emitLine: (text: string) => Promise<void> | void;\n installService: () => Promise<void>;\n}): Promise<\"install\" | \"not_now\" | \"cancelled\" | \"failed\"> {\n const decision = await promptForDaemonInstallDecision({\n kind: input.kind,\n installedVersion: input.installedVersion,\n expectedVersion: input.expectedVersion,\n });\n if (decision === DAEMON_INSTALL_DECISION_CHOICE.install) {\n try {\n await input.installService();\n return \"install\";\n } catch {\n await input.emitLine(formatDaemonInstallFailedMessage(input.kind));\n return \"failed\";\n }\n }\n\n if (decision === \"cancelled\") {\n return \"cancelled\";\n }\n\n await input.emitLine(formatDaemonInstallDeferredMessage(input.kind));\n return decision;\n}\n\nexport function formatDaemonInstallDeferredMessage(\n kind: DaemonInstallDecisionKind\n): string {\n return formatInlineOpenMeldCliCommands(\n DAEMON_INSTALL_DECISION_COPY[kind].deferred\n );\n}\n\nexport function formatDaemonInstallFailedMessage(\n kind: DaemonInstallDecisionKind\n): string {\n return formatInlineOpenMeldCliCommands(\n DAEMON_INSTALL_DECISION_COPY[kind].failed\n );\n}\n\nexport function formatDaemonServiceMissingRecommendation(): string {\n return \"OpenMeld Service is not installed yet. Install it so this computer can receive local Wake work.\";\n}\n\nexport function formatDaemonServiceInstallRecommendationNextStep(): string {\n return `Run \\`${formatOpenMeldCliCommand(DAEMON_INSTALL_COMMAND)}\\` now, or re-run command with ${DAEMON_AUTO_INSTALL_ALWAYS_FLAG}.`;\n}\n\nexport function formatDaemonServiceMissingStatus(): string {\n return \"Not installed yet.\";\n}\n\nexport function formatDaemonServiceMissingMeaning(): string {\n return \"Missing — install OpenMeld Service before this computer can receive local Wake work.\";\n}\n\nexport function formatDaemonServiceMissingAction(): string {\n return `Run \\`${formatOpenMeldCliCommand(DAEMON_INSTALL_COMMAND)}\\` to set it up.`;\n}\n\nexport function formatDaemonServiceMissingRunStepOne(): string {\n return `\\`${formatOpenMeldCliCommand(DAEMON_INSTALL_COMMAND)}\\``;\n}\n\nexport function formatDaemonServiceMissingRunStepTwo(): string {\n return `\\`${formatOpenMeldCliCommand(\"openmeld service start\")}\\``;\n}\n\nexport function formatDaemonServiceOutdatedRecommendation(\n input: DaemonVersionInput\n): string {\n const installedVersion = input.installedVersion ?? \"unknown\";\n return `OpenMeld Service version differs from this CLI (installed v${installedVersion}, CLI v${input.expectedVersion}). This is diagnostic unless service compatibility fails.`;\n}\n\nexport function formatDaemonServiceOutdatedStatus(\n input: DaemonVersionInput\n): string {\n const installedVersion = input.installedVersion ?? \"unknown\";\n return `Version differs from this CLI (installed v${installedVersion}, CLI v${input.expectedVersion}).`;\n}\n\nexport function formatDaemonServiceDowngradeBlockedRecommendation(\n input: DaemonVersionInput\n): string {\n if (input.installedVersion) {\n return `OpenMeld Service is already newer (installed v${input.installedVersion}, current CLI v${input.expectedVersion}). OpenMeld will not downgrade it automatically. Run \\`${formatOpenMeldCliCommand(DAEMON_UPGRADE_COMMAND)}\\`.`;\n }\n return `OpenMeld Service is already newer than this CLI. OpenMeld will not downgrade it automatically. Run \\`${formatOpenMeldCliCommand(DAEMON_UPGRADE_COMMAND)}\\`.`;\n}\n\nexport function getDaemonDowngradeBlockedTitle(): string {\n return \"⛔ OpenMeld Service Downgrade Blocked\";\n}\n\nexport function formatDaemonDowngradeBlockedNextStep(): string {\n return `Run \\`${formatOpenMeldCliCommand(DAEMON_UPGRADE_COMMAND)}\\`.`;\n}\n\nexport function formatDaemonStartupRepairNotice(): string {\n return `Run \\`${formatOpenMeldCliCommand(DAEMON_REPAIR_COMMAND)}\\` to repair it now.`;\n}\n","export const MIN_VISIBLE_ELAPSED_TIME_MS = 100;\n\nexport function resolveElapsedTimeMs(\n startedAtMs: number,\n currentTimeMs = Date.now()\n): number {\n return Math.max(0, currentTimeMs - startedAtMs);\n}\n\nexport function formatElapsedTime(durationMs: number): string {\n const seconds = durationMs / 1000;\n return seconds < 10 ? `${seconds.toFixed(1)}s` : `${Math.round(seconds)}s`;\n}\n"],"mappings":"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"}
@@ -2,15 +2,15 @@
2
2
 
3
3
  import { a as resolveBaseUrl } from "./base-url-BOr6HWCA.js";
4
4
  import { F as resolveOpenMeldRootDir, U as systemDir } from "./paths-De9xdA2h.js";
5
- import { n as ensureDaemonRuntimePaths, v as toErrorMessage, y as warnDaemonEvent } from "./daemon-device-id-B-iuoFzM.js";
6
- import { d as serviceExecutionHostOwnerSchema, r as serveExecutionHost, t as ExecutionHostError, u as serviceExecutionHostMethods } from "./channel-DfaHRitM.js";
7
- import { E as withAdmittedServiceSession, d as getAuthSessionState, o as buildStoredAuthSessionIdentity } from "./auth-session-GYsWoDuJ.js";
5
+ import { n as ensureDaemonRuntimePaths, v as toErrorMessage, y as warnDaemonEvent } from "./daemon-device-id-DLKuN3Eo.js";
6
+ import { d as serviceExecutionHostOwnerSchema, r as serveExecutionHost, t as ExecutionHostError, u as serviceExecutionHostMethods } from "./channel-D1NKTdY0.js";
7
+ import { E as withAdmittedServiceSession, d as getAuthSessionState, o as buildStoredAuthSessionIdentity } from "./auth-session-QFK36vfX.js";
8
8
  import { a as isOpenMeldLockError, c as releaseLock, n as acquireLock, t as MALFORMED_LOCK_RECOVERY_GRACE_MS } from "./lock-B0YzvcUu.js";
9
9
  import { i as readProcessStartIdentity, r as isProcessIdentityAlive, t as CURRENT_PROCESS_START_IDENTITY } from "./process-identity-DsKKbftl.js";
10
- import { n as resolveRuntimeContext } from "./context-CPKBlAps.js";
11
- import { t as createPresenter } from "./presenter-BIwIweT9.js";
10
+ import { n as resolveRuntimeContext } from "./context-DqEUJy_k.js";
11
+ import { t as createPresenter } from "./presenter-DqdYrUMa.js";
12
12
  import { i as readDaemonServiceContract } from "./daemon-service-contract-B1EbK5p7.js";
13
- import { n as parentExecutionHostChannel } from "./process-channel-Dx1KqiZj.js";
13
+ import { n as parentExecutionHostChannel } from "./process-channel-Vz_ntXXU.js";
14
14
  import { randomUUID } from "node:crypto";
15
15
  import { dirname, join, resolve } from "node:path";
16
16
  import { lstat, readFile } from "node:fs/promises";
@@ -325,7 +325,7 @@ function runExecutionHost(hostInstanceId) {
325
325
  ownership = verifiedOwnership;
326
326
  session = verified.session;
327
327
  await withAdmittedServiceSession(session, async () => {
328
- const { createExecutionHostRuntime, createExecutionHostResources } = await import("./runtime-D0ejcBmE.js");
328
+ const { createExecutionHostRuntime, createExecutionHostResources } = await import("./runtime-MZYGkNRp.js");
329
329
  const runtimePaths = await ensureDaemonRuntimePaths();
330
330
  const presenter = createPresenter(await resolveRuntimeContext({ view: "agent" }));
331
331
  runtime = await createExecutionHostRuntime({
@@ -385,4 +385,4 @@ function runExecutionHost(hostInstanceId) {
385
385
  //#endregion
386
386
  export { runExecutionHost };
387
387
 
388
- //# sourceMappingURL=entry-BM8DA2U-.js.map
388
+ //# sourceMappingURL=entry-Dej02SVj.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entry-BM8DA2U-.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 { lstat, 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 {\n acquireLock,\n isOpenMeldLockError,\n MALFORMED_LOCK_RECOVERY_GRACE_MS,\n releaseLock,\n} from \"../../config/lock\";\nimport { systemDir } from \"../../config/paths\";\nimport {\n CURRENT_PROCESS_START_IDENTITY,\n isProcessIdentityAlive,\n readProcessStartIdentity,\n} from \"../../system/process-identity\";\nimport { toErrorMessage, warnDaemonEvent } from \"../core/logger\";\nimport { ExecutionHostError } from \"./channel\";\n\nconst run = promisify(execFile);\nconst WINDOWS_BOOT_EVENT = /^\\d+:\\d+$/;\nconst DECIMAL = /^\\d+$/;\n\ntype OwnedProcessEvent = {\n phase: \"process_exit\" | \"process_spawned\";\n processId: number | null;\n signalTarget: \"process\" | \"process_group\";\n taskId: string;\n};\n\ntype HostOwnerReceipt = Extract<\n z.infer<typeof serviceExecutionHostOwnerSchema>,\n {\n schema:\n | \"service-execution-host-owner-v2\"\n | \"service-execution-host-owner-v3\";\n }\n>;\n\nexport type ExecutionHostWorkState = {\n localQuiescent: boolean;\n // Controls, adapter maintenance and workspace cleanup launch unrecorded processes.\n unattributedWork: boolean;\n runningTaskIds: readonly string[];\n};\n\nexport type ProviderInvocationEvent = {\n phase: \"ended\" | \"started\";\n taskId: string;\n};\n\ntype TaskEvidence = {\n activeInvocations: number;\n // Points where a running invocation may launch a process it has not yet\n // recorded: its start, and each recorded exit before it ends.\n unrecordedLaunches: number;\n completedInvocation: boolean;\n};\n\n// Preparation before the first invocation can launch work it never records.\n// Workspace cleanup after an invocation is tracked as unattributed work.\nfunction isTaskEvidenceComplete(task: TaskEvidence): boolean {\n return task.activeInvocations > 0\n ? task.unrecordedLaunches === 0\n : task.completedInvocation;\n}\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 acquireProcessOwnerLock(input);\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 assertPreviousOwnerReplaceableOnSameBoot(previous);\n }\n let owner: HostOwnerReceipt = {\n schema: \"service-execution-host-owner-v2\",\n hostInstanceId: input.hostInstanceId,\n ownerUserId: input.ownerUserId,\n deviceId: input.deviceId,\n lane: input.lane,\n pid: process.pid,\n processStartedAt: CURRENT_PROCESS_START_IDENTITY,\n bootIdentity: input.bootIdentity,\n localQuiescent: true,\n processEvidenceComplete: true,\n ownedProcessTrees: [],\n };\n serviceExecutionHostOwnerSchema.parse(owner);\n persist(owner);\n function persist(next: HostOwnerReceipt) {\n try {\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 } catch (error) {\n warnDaemonEvent(\"[openmeld.execution_host.receipt_write_failed]\", {\n event: \"cli.execution_host.receipt_write_failed\",\n detail: toErrorMessage(error),\n });\n throw new ExecutionHostError(\n \"host.execution_record_unavailable\",\n \"The local execution host could not write its ownership record.\"\n );\n }\n }\n // A failed write throws to the caller, which refuses the operation rather\n // than weakening the fence.\n function update(changes: Partial<Omit<HostOwnerReceipt, \"schema\">>) {\n const merged = { ...owner, ...changes };\n const next: HostOwnerReceipt = {\n ...merged,\n // A quiescent receipt carries no evidence, so it keeps the shape an\n // older Service reads after a verified rollback.\n schema: merged.localQuiescent\n ? \"service-execution-host-owner-v2\"\n : \"service-execution-host-owner-v3\",\n };\n if (JSON.stringify(next) === JSON.stringify(owner)) {\n return;\n }\n persist(next);\n owner = next;\n }\n // Evidence is per running task and per provider invocation. One task's\n // record never vouches for another task, and one invocation's record never\n // vouches for the next invocation of the same task.\n const tasks = new Map<string, TaskEvidence>();\n let unattributedWork = false;\n const evidenceComplete = () =>\n !unattributedWork && [...tasks.values()].every(isTaskEvidenceComplete);\n return {\n observeWork(state: ExecutionHostWorkState) {\n if (state.localQuiescent) {\n tasks.clear();\n unattributedWork = false;\n // Idle slots do not prove a recorded process group has exited; the\n // receipt stays non-quiescent until every recorded tree is gone.\n const liveTrees = owner.ownedProcessTrees.filter(\n isOwnedProcessTreeAlive\n );\n update({\n localQuiescent: liveTrees.length === 0,\n processEvidenceComplete: true,\n ownedProcessTrees: liveTrees,\n });\n return;\n }\n const running = new Set(state.runningTaskIds);\n for (const taskId of tasks.keys()) {\n if (!running.has(taskId)) {\n tasks.delete(taskId);\n }\n }\n for (const taskId of running) {\n if (!tasks.has(taskId)) {\n tasks.set(taskId, {\n activeInvocations: 0,\n unrecordedLaunches: 0,\n completedInvocation: false,\n });\n }\n }\n unattributedWork = state.unattributedWork;\n update({\n localQuiescent: false,\n processEvidenceComplete: evidenceComplete(),\n });\n },\n // Called before a provider invocation can launch anything, so the\n // durable receipt is incomplete first; a failed write refuses it.\n observeProviderInvocation(event: ProviderInvocationEvent) {\n const task = tasks.get(event.taskId);\n if (!task) {\n return;\n }\n if (event.phase === \"started\") {\n task.activeInvocations += 1;\n task.unrecordedLaunches += 1;\n } else {\n task.activeInvocations = Math.max(0, task.activeInvocations - 1);\n if (task.activeInvocations === 0) {\n task.unrecordedLaunches = 0;\n task.completedInvocation = true;\n }\n }\n update({ processEvidenceComplete: evidenceComplete() });\n },\n observeOwnedProcess(event: OwnedProcessEvent) {\n const task = tasks.get(event.taskId);\n if (event.phase === \"process_spawned\") {\n if (event.processId === null) {\n return;\n }\n const processStartedAt =\n readProcessStartIdentity(event.processId) ??\n `fallback:${event.processId}:unknown`;\n if (task && task.activeInvocations > 0) {\n task.unrecordedLaunches = Math.max(0, task.unrecordedLaunches - 1);\n }\n update({\n localQuiescent: false,\n processEvidenceComplete: evidenceComplete(),\n ownedProcessTrees: [\n ...owner.ownedProcessTrees.filter(\n (process) => process.pid !== event.processId\n ),\n {\n pid: event.processId,\n processStartedAt,\n signalTarget: event.signalTarget,\n },\n ],\n });\n return;\n }\n if (event.processId === null) {\n return;\n }\n // A running invocation may launch again after a recorded process\n // exits, such as a context-heal retry.\n if (task && task.activeInvocations > 0) {\n task.unrecordedLaunches += 1;\n }\n update({\n processEvidenceComplete: evidenceComplete(),\n ownedProcessTrees: owner.ownedProcessTrees.filter(\n (process) =>\n process.pid !== event.processId ||\n isOwnedProcessTreeAlive(process)\n ),\n });\n },\n release: () => releaseLock(lock),\n };\n } catch (error) {\n await releaseLock(lock);\n throw error;\n }\n}\n\nasync function acquireProcessOwnerLock(input: {\n hostInstanceId: string;\n ownerUserId: string;\n stateRoot: string;\n}) {\n try {\n return await acquireLock({\n openMeldProfileId: \"service-execution-host\",\n key: \"process-owner\",\n pathResolution: {\n env: { ...process.env, OPENMELD_HOME: input.stateRoot },\n },\n meta: {\n hostInstanceId: input.hostInstanceId,\n ownerUserId: input.ownerUserId,\n },\n });\n } catch (error) {\n if (!(isOpenMeldLockError(error) && error.contentionState === \"active\")) {\n throw error;\n }\n if (typeof error.meta?.pid === \"number\") {\n throw new ExecutionHostError(\n \"host.previous_work_running\",\n \"Another execution host for this installation is still running. This Host starts after it exits; no task will be restarted automatically.\"\n );\n }\n // A lock briefly has no owner entry while it is published or released.\n // Past the lock's own recovery grace, there is no process to wait for.\n if (await isOwnerLockHandoffPossible(error.lockPath)) {\n throw new ExecutionHostError(\n \"host.previous_work_running\",\n \"Another execution host for this installation is starting or stopping. This Host checks again shortly; no task will be restarted automatically.\"\n );\n }\n throw new ExecutionHostError(\n \"host.owner_lock_unverified\",\n \"The execution host lock for this installation has no identifiable owner. Preserve it for diagnostics; automatic replacement is refused.\"\n );\n }\n}\n\nasync function isOwnerLockHandoffPossible(lockPath: string): Promise<boolean> {\n try {\n const stats = await lstat(lockPath);\n return Date.now() - stats.mtimeMs < MALFORMED_LOCK_RECOVERY_GRACE_MS;\n } catch (error) {\n return isNodeError(error, \"ENOENT\");\n }\n}\n\n// Waiting can clear only a fence whose recorded processes are still alive.\n// Incomplete or legacy evidence, including a non-quiescent V2 receipt whose\n// completeness was Host-wide, stays unconfirmed however long it is retried.\nfunction assertPreviousOwnerReplaceableOnSameBoot(\n previous: NonNullable<ReturnType<typeof readOwner>>\n): void {\n if (\n previous.schema !== \"service-execution-host-owner-v3\" ||\n !previous.processEvidenceComplete\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 if (\n isProcessIdentityAlive({\n ownerPid: previous.pid,\n ownerProcessStartedAt: previous.processStartedAt,\n }) ||\n previous.ownedProcessTrees.some(isOwnedProcessTreeAlive)\n ) {\n throw new ExecutionHostError(\n \"host.previous_work_running\",\n \"Local agent work recorded by the previous execution host is still running. This Host starts after that work exits; no task will be restarted automatically.\"\n );\n }\n}\n\nfunction isOwnedProcessTreeAlive(input: {\n pid: number;\n processStartedAt: string;\n signalTarget: \"process\" | \"process_group\";\n}): boolean {\n if (input.signalTarget === \"process_group\" && process.platform !== \"win32\") {\n try {\n process.kill(-input.pid, 0);\n return true;\n } catch (error) {\n return !isNodeError(error, \"ESRCH\");\n }\n }\n return isProcessIdentityAlive({\n ownerPid: input.pid,\n ownerProcessStartedAt: input.processStartedAt,\n });\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return (\n error instanceof Error && \"code\" in error && String(error.code) === code\n );\n}\n\nfunction readOwner(path: string) {\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return null;\n }\n throw new ExecutionHostError(\n \"host.owner_corrupt\",\n `The Host ownership record cannot be read (${error instanceof Error ? error.message : String(error)}). Preserve it for diagnostics; automatic replacement is refused.`\n );\n }\n try {\n const parsed = serviceExecutionHostOwnerSchema.safeParse(JSON.parse(raw));\n if (parsed.success) {\n return parsed.data;\n }\n } catch {\n // Unreadable JSON is as unverifiable as a record with the wrong shape.\n }\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","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 const attempt = (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 observeOwnedProcess: (event) =>\n verifiedOwnership.observeOwnedProcess(event),\n observeProviderInvocation: (event) =>\n verifiedOwnership.observeProviderInvocation(event),\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: (state) =>\n verifiedOwnership.observeWork(state),\n });\n });\n })();\n initializing = attempt;\n attempt.catch((error: unknown) => {\n // Ownership was refused before any runtime state opened. The\n // supervising Service asks again once the recorded work may have exited.\n if (\n initializing === attempt &&\n error instanceof ExecutionHostError &&\n error.code === \"host.previous_work_running\"\n ) {\n initializing = null;\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-Dej02SVj.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 { lstat, 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 {\n acquireLock,\n isOpenMeldLockError,\n MALFORMED_LOCK_RECOVERY_GRACE_MS,\n releaseLock,\n} from \"../../config/lock\";\nimport { systemDir } from \"../../config/paths\";\nimport {\n CURRENT_PROCESS_START_IDENTITY,\n isProcessIdentityAlive,\n readProcessStartIdentity,\n} from \"../../system/process-identity\";\nimport { toErrorMessage, warnDaemonEvent } from \"../core/logger\";\nimport { ExecutionHostError } from \"./channel\";\n\nconst run = promisify(execFile);\nconst WINDOWS_BOOT_EVENT = /^\\d+:\\d+$/;\nconst DECIMAL = /^\\d+$/;\n\ntype OwnedProcessEvent = {\n phase: \"process_exit\" | \"process_spawned\";\n processId: number | null;\n signalTarget: \"process\" | \"process_group\";\n taskId: string;\n};\n\ntype HostOwnerReceipt = Extract<\n z.infer<typeof serviceExecutionHostOwnerSchema>,\n {\n schema:\n | \"service-execution-host-owner-v2\"\n | \"service-execution-host-owner-v3\";\n }\n>;\n\nexport type ExecutionHostWorkState = {\n localQuiescent: boolean;\n // Controls, adapter maintenance and workspace cleanup launch unrecorded processes.\n unattributedWork: boolean;\n runningTaskIds: readonly string[];\n};\n\nexport type ProviderInvocationEvent = {\n phase: \"ended\" | \"started\";\n taskId: string;\n};\n\ntype TaskEvidence = {\n activeInvocations: number;\n // Points where a running invocation may launch a process it has not yet\n // recorded: its start, and each recorded exit before it ends.\n unrecordedLaunches: number;\n completedInvocation: boolean;\n};\n\n// Preparation before the first invocation can launch work it never records.\n// Workspace cleanup after an invocation is tracked as unattributed work.\nfunction isTaskEvidenceComplete(task: TaskEvidence): boolean {\n return task.activeInvocations > 0\n ? task.unrecordedLaunches === 0\n : task.completedInvocation;\n}\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 acquireProcessOwnerLock(input);\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 assertPreviousOwnerReplaceableOnSameBoot(previous);\n }\n let owner: HostOwnerReceipt = {\n schema: \"service-execution-host-owner-v2\",\n hostInstanceId: input.hostInstanceId,\n ownerUserId: input.ownerUserId,\n deviceId: input.deviceId,\n lane: input.lane,\n pid: process.pid,\n processStartedAt: CURRENT_PROCESS_START_IDENTITY,\n bootIdentity: input.bootIdentity,\n localQuiescent: true,\n processEvidenceComplete: true,\n ownedProcessTrees: [],\n };\n serviceExecutionHostOwnerSchema.parse(owner);\n persist(owner);\n function persist(next: HostOwnerReceipt) {\n try {\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 } catch (error) {\n warnDaemonEvent(\"[openmeld.execution_host.receipt_write_failed]\", {\n event: \"cli.execution_host.receipt_write_failed\",\n detail: toErrorMessage(error),\n });\n throw new ExecutionHostError(\n \"host.execution_record_unavailable\",\n \"The local execution host could not write its ownership record.\"\n );\n }\n }\n // A failed write throws to the caller, which refuses the operation rather\n // than weakening the fence.\n function update(changes: Partial<Omit<HostOwnerReceipt, \"schema\">>) {\n const merged = { ...owner, ...changes };\n const next: HostOwnerReceipt = {\n ...merged,\n // A quiescent receipt carries no evidence, so it keeps the shape an\n // older Service reads after a verified rollback.\n schema: merged.localQuiescent\n ? \"service-execution-host-owner-v2\"\n : \"service-execution-host-owner-v3\",\n };\n if (JSON.stringify(next) === JSON.stringify(owner)) {\n return;\n }\n persist(next);\n owner = next;\n }\n // Evidence is per running task and per provider invocation. One task's\n // record never vouches for another task, and one invocation's record never\n // vouches for the next invocation of the same task.\n const tasks = new Map<string, TaskEvidence>();\n let unattributedWork = false;\n const evidenceComplete = () =>\n !unattributedWork && [...tasks.values()].every(isTaskEvidenceComplete);\n return {\n observeWork(state: ExecutionHostWorkState) {\n if (state.localQuiescent) {\n tasks.clear();\n unattributedWork = false;\n // Idle slots do not prove a recorded process group has exited; the\n // receipt stays non-quiescent until every recorded tree is gone.\n const liveTrees = owner.ownedProcessTrees.filter(\n isOwnedProcessTreeAlive\n );\n update({\n localQuiescent: liveTrees.length === 0,\n processEvidenceComplete: true,\n ownedProcessTrees: liveTrees,\n });\n return;\n }\n const running = new Set(state.runningTaskIds);\n for (const taskId of tasks.keys()) {\n if (!running.has(taskId)) {\n tasks.delete(taskId);\n }\n }\n for (const taskId of running) {\n if (!tasks.has(taskId)) {\n tasks.set(taskId, {\n activeInvocations: 0,\n unrecordedLaunches: 0,\n completedInvocation: false,\n });\n }\n }\n unattributedWork = state.unattributedWork;\n update({\n localQuiescent: false,\n processEvidenceComplete: evidenceComplete(),\n });\n },\n // Called before a provider invocation can launch anything, so the\n // durable receipt is incomplete first; a failed write refuses it.\n observeProviderInvocation(event: ProviderInvocationEvent) {\n const task = tasks.get(event.taskId);\n if (!task) {\n return;\n }\n if (event.phase === \"started\") {\n task.activeInvocations += 1;\n task.unrecordedLaunches += 1;\n } else {\n task.activeInvocations = Math.max(0, task.activeInvocations - 1);\n if (task.activeInvocations === 0) {\n task.unrecordedLaunches = 0;\n task.completedInvocation = true;\n }\n }\n update({ processEvidenceComplete: evidenceComplete() });\n },\n observeOwnedProcess(event: OwnedProcessEvent) {\n const task = tasks.get(event.taskId);\n if (event.phase === \"process_spawned\") {\n if (event.processId === null) {\n return;\n }\n const processStartedAt =\n readProcessStartIdentity(event.processId) ??\n `fallback:${event.processId}:unknown`;\n if (task && task.activeInvocations > 0) {\n task.unrecordedLaunches = Math.max(0, task.unrecordedLaunches - 1);\n }\n update({\n localQuiescent: false,\n processEvidenceComplete: evidenceComplete(),\n ownedProcessTrees: [\n ...owner.ownedProcessTrees.filter(\n (process) => process.pid !== event.processId\n ),\n {\n pid: event.processId,\n processStartedAt,\n signalTarget: event.signalTarget,\n },\n ],\n });\n return;\n }\n if (event.processId === null) {\n return;\n }\n // A running invocation may launch again after a recorded process\n // exits, such as a context-heal retry.\n if (task && task.activeInvocations > 0) {\n task.unrecordedLaunches += 1;\n }\n update({\n processEvidenceComplete: evidenceComplete(),\n ownedProcessTrees: owner.ownedProcessTrees.filter(\n (process) =>\n process.pid !== event.processId ||\n isOwnedProcessTreeAlive(process)\n ),\n });\n },\n release: () => releaseLock(lock),\n };\n } catch (error) {\n await releaseLock(lock);\n throw error;\n }\n}\n\nasync function acquireProcessOwnerLock(input: {\n hostInstanceId: string;\n ownerUserId: string;\n stateRoot: string;\n}) {\n try {\n return await acquireLock({\n openMeldProfileId: \"service-execution-host\",\n key: \"process-owner\",\n pathResolution: {\n env: { ...process.env, OPENMELD_HOME: input.stateRoot },\n },\n meta: {\n hostInstanceId: input.hostInstanceId,\n ownerUserId: input.ownerUserId,\n },\n });\n } catch (error) {\n if (!(isOpenMeldLockError(error) && error.contentionState === \"active\")) {\n throw error;\n }\n if (typeof error.meta?.pid === \"number\") {\n throw new ExecutionHostError(\n \"host.previous_work_running\",\n \"Another execution host for this installation is still running. This Host starts after it exits; no task will be restarted automatically.\"\n );\n }\n // A lock briefly has no owner entry while it is published or released.\n // Past the lock's own recovery grace, there is no process to wait for.\n if (await isOwnerLockHandoffPossible(error.lockPath)) {\n throw new ExecutionHostError(\n \"host.previous_work_running\",\n \"Another execution host for this installation is starting or stopping. This Host checks again shortly; no task will be restarted automatically.\"\n );\n }\n throw new ExecutionHostError(\n \"host.owner_lock_unverified\",\n \"The execution host lock for this installation has no identifiable owner. Preserve it for diagnostics; automatic replacement is refused.\"\n );\n }\n}\n\nasync function isOwnerLockHandoffPossible(lockPath: string): Promise<boolean> {\n try {\n const stats = await lstat(lockPath);\n return Date.now() - stats.mtimeMs < MALFORMED_LOCK_RECOVERY_GRACE_MS;\n } catch (error) {\n return isNodeError(error, \"ENOENT\");\n }\n}\n\n// Waiting can clear only a fence whose recorded processes are still alive.\n// Incomplete or legacy evidence, including a non-quiescent V2 receipt whose\n// completeness was Host-wide, stays unconfirmed however long it is retried.\nfunction assertPreviousOwnerReplaceableOnSameBoot(\n previous: NonNullable<ReturnType<typeof readOwner>>\n): void {\n if (\n previous.schema !== \"service-execution-host-owner-v3\" ||\n !previous.processEvidenceComplete\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 if (\n isProcessIdentityAlive({\n ownerPid: previous.pid,\n ownerProcessStartedAt: previous.processStartedAt,\n }) ||\n previous.ownedProcessTrees.some(isOwnedProcessTreeAlive)\n ) {\n throw new ExecutionHostError(\n \"host.previous_work_running\",\n \"Local agent work recorded by the previous execution host is still running. This Host starts after that work exits; no task will be restarted automatically.\"\n );\n }\n}\n\nfunction isOwnedProcessTreeAlive(input: {\n pid: number;\n processStartedAt: string;\n signalTarget: \"process\" | \"process_group\";\n}): boolean {\n if (input.signalTarget === \"process_group\" && process.platform !== \"win32\") {\n try {\n process.kill(-input.pid, 0);\n return true;\n } catch (error) {\n return !isNodeError(error, \"ESRCH\");\n }\n }\n return isProcessIdentityAlive({\n ownerPid: input.pid,\n ownerProcessStartedAt: input.processStartedAt,\n });\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return (\n error instanceof Error && \"code\" in error && String(error.code) === code\n );\n}\n\nfunction readOwner(path: string) {\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return null;\n }\n throw new ExecutionHostError(\n \"host.owner_corrupt\",\n `The Host ownership record cannot be read (${error instanceof Error ? error.message : String(error)}). Preserve it for diagnostics; automatic replacement is refused.`\n );\n }\n try {\n const parsed = serviceExecutionHostOwnerSchema.safeParse(JSON.parse(raw));\n if (parsed.success) {\n return parsed.data;\n }\n } catch {\n // Unreadable JSON is as unverifiable as a record with the wrong shape.\n }\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","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 const attempt = (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 observeOwnedProcess: (event) =>\n verifiedOwnership.observeOwnedProcess(event),\n observeProviderInvocation: (event) =>\n verifiedOwnership.observeProviderInvocation(event),\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: (state) =>\n verifiedOwnership.observeWork(state),\n });\n });\n })();\n initializing = attempt;\n attempt.catch((error: unknown) => {\n // Ownership was refused before any runtime state opened. The\n // supervising Service asks again once the recorded work may have exited.\n if (\n initializing === attempt &&\n error instanceof ExecutionHostError &&\n error.code === \"host.previous_work_running\"\n ) {\n initializing = null;\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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"}
@@ -2,8 +2,8 @@
2
2
 
3
3
  import { T as updateConfiguredSkillsConfig, g as getConfiguredSkillsConfig, y as resolveRuntimeSkillsCustomTargetId } from "./base-url-BOr6HWCA.js";
4
4
  import { V as skillsDir } from "./paths-De9xdA2h.js";
5
- import { Ht as detectInstalledSkillsAgents, Ut as resolveSkillsAgentRegistry, Vt as canManageRegistryAgentSkillTargets } from "./prepare-provider-runtime-CQ7ZJMG8.js";
6
- import { n as resolveSkillsInstallStates, r as ensureLocalSkills, t as resolveSkillInstallStateForTarget } from "./state-MwOfpQOL.js";
5
+ import { Ht as detectInstalledSkillsAgents, Ut as resolveSkillsAgentRegistry, Vt as canManageRegistryAgentSkillTargets } from "./prepare-provider-runtime-Cdm1_kJt.js";
6
+ import { n as resolveSkillsInstallStates, r as ensureLocalSkills, t as resolveSkillInstallStateForTarget } from "./state-Dz2UWXBu.js";
7
7
  import { stat } from "node:fs/promises";
8
8
  //#region src/skills/installation-inventory.ts
9
9
  async function collectSkillsReadinessSnapshot() {
@@ -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-BBR228VY.js.map
243
+ //# sourceMappingURL=installation-inventory-C8O-r8eI.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"installation-inventory-BBR228VY.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-C8O-r8eI.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-MwOfpQOL.js";
3
+ import { c as replaceSkillDirectory, f as withSkillsInstallLock, o as writeOpenMeldSkillMarker, s as recoverSkillReplacement, t as resolveSkillInstallStateForTarget } from "./state-Dz2UWXBu.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-D4dGpL9N.js.map
125
+ //# sourceMappingURL=installer-B_Vvfk67.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"installer-D4dGpL9N.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-B_Vvfk67.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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"}
@@ -34,6 +34,52 @@ const openMeldToolsUpdateRequestSourceSchema = enumFactory([
34
34
  "web"
35
35
  ]);
36
36
  const OPEN_MELD_TOOLS_UPDATE_FAILURE_DETAIL_MAX_CHARS = 2048;
37
+ const openMeldToolsUpdateStepSchema = enumFactory([
38
+ "awaiting_worker",
39
+ "maintenance_preflight",
40
+ "worker_claimed",
41
+ "checking_release",
42
+ "planning_download",
43
+ "downloading_cli",
44
+ "verifying_cli",
45
+ "preparing_process_helper",
46
+ "installing_cli",
47
+ "npm_install",
48
+ "aligning_service",
49
+ "preparing_service_bundle",
50
+ "downloading_service_artifact",
51
+ "staging_service_artifact",
52
+ "verifying_service_artifact",
53
+ "preparing_service_helper",
54
+ "scheduling_service",
55
+ "service_job_pending",
56
+ "waiting_to_replace_service",
57
+ "service_inspect",
58
+ "service_backup",
59
+ "service_stop_or_drain",
60
+ "service_wait_stopped",
61
+ "service_unregister",
62
+ "service_wait_absent",
63
+ "service_prepare_bundle",
64
+ "service_install_bundle",
65
+ "service_write_contract",
66
+ "service_register_service",
67
+ "service_restore_runtime_data",
68
+ "service_start_if_desired",
69
+ "service_wait_running",
70
+ "service_verify_final_inventory"
71
+ ]);
72
+ const updateStepPrefix = "cli.update.step.";
73
+ function openMeldToolsUpdateStepCode(step) {
74
+ return updateStepPrefix + step;
75
+ }
76
+ const openMeldToolsUpdateCheckpointSchema = strictObject({
77
+ operationId: nonEmptyStringSchema.max(128),
78
+ requestedAt: iso.datetime({ offset: true }),
79
+ targetCliVersion: nonEmptyStringSchema.max(64),
80
+ targetServiceVersion: nonEmptyStringSchema.max(64),
81
+ step: openMeldToolsUpdateStepSchema
82
+ });
37
83
  const openMeldToolsUpdateFailureCodeSchema = enumFactory([
38
84
  "cli.update.download_stalled",
39
85
  "cli.update.download_timed_out",
@@ -346,6 +392,6 @@ function formatLocalSetupActionDescription(action) {
346
392
  }
347
393
  }
348
394
  //#endregion
349
- export { openMeldToolsUpdateAttemptSchema as A, localSkillsComponentProjectionSchema as C, openMeldToolsControlResultSchema as D, openMeldToolsControlRequestSchema as E, openMeldToolsUpdateRequestResultSchema as F, openMeldToolsUpdateRequestSourceSchema as I, resolveOpenMeldToolsUpdateTargetVersions as L, openMeldToolsUpdateOperationPhaseSchema as M, openMeldToolsUpdateOperationSchema as N, openMeldToolsMaintenanceMutationResultSchema as O, openMeldToolsUpdateProcessFailureFrameSchema as P, localSetupEntrypointSchema as S, openMeldToolsControlCapabilitySchema as T, localComponentsReleaseManifestSchema as _, formatLocalSetupActionLabel as a, localServiceComponentUpdateProjectionSchema as b, localCliComponentUpdateProjectionSchema as c, localComponentUpdatePolicySchema as d, localComponentUpdateProjectionSchema as f, localComponentsManifestSchema as g, localComponentsInstallationSourceSchema as h, formatLocalSetupActionDescription as i, openMeldToolsUpdateFailureCodeSchema as j, openMeldToolsMaintenanceProjectionSchema as k, localComponentProjectionSchema as l, localComponentsBinaryReleasePolicySchema as m, formatLocalComponentsSummaryDescription as n, installedLocalComponentsSnapshotSchema as o, localComponentUpdateStatusSchema as p, formatLocalComponentsSummaryLabel as r, localCliComponentProjectionSchema as s, OPEN_MELD_TOOLS_UPDATE_FAILURE_DETAIL_MAX_CHARS as t, localComponentStatusSchema as u, localComponentsStatusSchema as v, localSkillsComponentUpdateProjectionSchema as w, localSetupActionSchema as x, localServiceComponentProjectionSchema as y };
395
+ export { openMeldToolsUpdateAttemptSchema as A, localSkillsComponentProjectionSchema as C, openMeldToolsControlResultSchema as D, openMeldToolsControlRequestSchema as E, openMeldToolsUpdateProcessFailureFrameSchema as F, openMeldToolsUpdateRequestResultSchema as I, openMeldToolsUpdateRequestSourceSchema as L, openMeldToolsUpdateFailureCodeSchema as M, openMeldToolsUpdateOperationPhaseSchema as N, openMeldToolsMaintenanceMutationResultSchema as O, openMeldToolsUpdateOperationSchema as P, openMeldToolsUpdateStepCode as R, localSetupEntrypointSchema as S, openMeldToolsControlCapabilitySchema as T, localComponentsReleaseManifestSchema as _, formatLocalSetupActionLabel as a, localServiceComponentUpdateProjectionSchema as b, localCliComponentUpdateProjectionSchema as c, localComponentUpdatePolicySchema as d, localComponentUpdateProjectionSchema as f, localComponentsManifestSchema as g, localComponentsInstallationSourceSchema as h, formatLocalSetupActionDescription as i, openMeldToolsUpdateCheckpointSchema as j, openMeldToolsMaintenanceProjectionSchema as k, localComponentProjectionSchema as l, localComponentsBinaryReleasePolicySchema as m, formatLocalComponentsSummaryDescription as n, installedLocalComponentsSnapshotSchema as o, localComponentUpdateStatusSchema as p, formatLocalComponentsSummaryLabel as r, localCliComponentProjectionSchema as s, OPEN_MELD_TOOLS_UPDATE_FAILURE_DETAIL_MAX_CHARS as t, localComponentStatusSchema as u, localComponentsStatusSchema as v, localSkillsComponentUpdateProjectionSchema as w, localSetupActionSchema as x, localServiceComponentProjectionSchema as y, resolveOpenMeldToolsUpdateTargetVersions as z };
350
396
 
351
- //# sourceMappingURL=local-components-DlEpUgN3.js.map
397
+ //# sourceMappingURL=local-components-BpA9Lc4v.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-components-BpA9Lc4v.js","names":[],"sources":["../../../packages/schemas/dist/schemas/local-components.js"],"sourcesContent":["import { array, boolean, discriminatedUnion, enum as enumFactory, iso, literal, number, strictObject, string } from \"../lazy-zod.js\";\n//#region src/schemas/local-components.ts\nconst LOCAL_COMPONENTS_SCHEMA_VERSION = 1;\nconst nonEmptyStringSchema = string().trim().min(1);\nconst nullableNonEmptyStringSchema = nonEmptyStringSchema.nullable();\nconst localComponentStatusSchema = enumFactory([\n\t\"ok\",\n\t\"update_available\",\n\t\"update_required\"\n]);\nconst localComponentUpdatePolicySchema = enumFactory([\n\t\"ok\",\n\t\"available\",\n\t\"required\"\n]);\nconst localComponentUpdateStatusSchema = enumFactory([\n\t\"current\",\n\t\"update_available\",\n\t\"update_required\",\n\t\"unknown\"\n]);\nconst openMeldToolsUpdateOperationPhaseSchema = enumFactory([\n\t\"waiting_for_work\",\n\t\"updating\",\n\t\"updated\",\n\t\"restored\",\n\t\"needs_help\"\n]);\nconst openMeldToolsUpdateRequestSourceSchema = enumFactory([\n\t\"automatic\",\n\t\"center_agent\",\n\t\"cli\",\n\t\"web\"\n]);\nconst OPEN_MELD_TOOLS_UPDATE_FAILURE_DETAIL_MAX_CHARS = 2048;\nconst openMeldToolsUpdateStepSchema = enumFactory([\n\t\"awaiting_worker\",\n\t\"maintenance_preflight\",\n\t\"worker_claimed\",\n\t\"checking_release\",\n\t\"planning_download\",\n\t\"downloading_cli\",\n\t\"verifying_cli\",\n\t\"preparing_process_helper\",\n\t\"installing_cli\",\n\t\"npm_install\",\n\t\"aligning_service\",\n\t\"preparing_service_bundle\",\n\t\"downloading_service_artifact\",\n\t\"staging_service_artifact\",\n\t\"verifying_service_artifact\",\n\t\"preparing_service_helper\",\n\t\"scheduling_service\",\n\t\"service_job_pending\",\n\t\"waiting_to_replace_service\",\n\t\"service_inspect\",\n\t\"service_backup\",\n\t\"service_stop_or_drain\",\n\t\"service_wait_stopped\",\n\t\"service_unregister\",\n\t\"service_wait_absent\",\n\t\"service_prepare_bundle\",\n\t\"service_install_bundle\",\n\t\"service_write_contract\",\n\t\"service_register_service\",\n\t\"service_restore_runtime_data\",\n\t\"service_start_if_desired\",\n\t\"service_wait_running\",\n\t\"service_verify_final_inventory\"\n]);\nconst updateStepPrefix = \"cli.update.step.\";\nfunction openMeldToolsUpdateStepCode(step) {\n\treturn updateStepPrefix + step;\n}\nfunction findOpenMeldToolsUpdateStep(codes) {\n\tfor (const code of codes) if (code.startsWith(updateStepPrefix)) {\n\t\tconst parsed = openMeldToolsUpdateStepSchema.safeParse(code.slice(16));\n\t\tif (parsed.success) return parsed.data;\n\t}\n\treturn null;\n}\nconst openMeldToolsUpdateCheckpointSchema = strictObject({\n\toperationId: nonEmptyStringSchema.max(128),\n\trequestedAt: iso.datetime({ offset: true }),\n\ttargetCliVersion: nonEmptyStringSchema.max(64),\n\ttargetServiceVersion: nonEmptyStringSchema.max(64),\n\tstep: openMeldToolsUpdateStepSchema\n});\nconst openMeldToolsUpdateFailureCodeSchema = enumFactory([\n\t\"cli.update.download_stalled\",\n\t\"cli.update.download_timed_out\",\n\t\"cli.update.download_failed\",\n\t\"cli.update.integrity_check_failed\",\n\t\"cli.update.install_failed\",\n\t\"cli.update.service_alignment_failed\",\n\t\"cli.update.failed\"\n]);\nconst openMeldToolsUpdateProcessFailureFrameSchema = strictObject({\n\tdetail: nonEmptyStringSchema.max(OPEN_MELD_TOOLS_UPDATE_FAILURE_DETAIL_MAX_CHARS),\n\tfailureCode: openMeldToolsUpdateFailureCodeSchema,\n\tschema: literal(\"openmeld-tools-update-process-failure-v1\"),\n\tv: literal(1)\n});\nconst openMeldToolsUpdateOperationSchema = strictObject({\n\toperationId: nonEmptyStringSchema,\n\tphase: openMeldToolsUpdateOperationPhaseSchema,\n\trequestSource: openMeldToolsUpdateRequestSourceSchema,\n\trequestedAt: iso.datetime({ offset: true }),\n\ttargetCliVersion: nonEmptyStringSchema.optional(),\n\ttargetServiceVersion: nonEmptyStringSchema.optional(),\n\ttargetVersion: nonEmptyStringSchema,\n\tupdatedAt: iso.datetime({ offset: true }),\n\turgency: enumFactory([\"available\", \"required\"])\n});\nfunction resolveOpenMeldToolsUpdateTargetVersions(operation) {\n\treturn {\n\t\tcliVersion: operation.targetCliVersion ?? operation.targetVersion,\n\t\tserviceVersion: operation.targetServiceVersion ?? operation.targetVersion\n\t};\n}\nconst openMeldToolsMaintenanceProjectionSchema = strictObject({\n\tautomaticUpdatesEnabled: boolean(),\n\tstatus: enumFactory([\"ready\", \"needs_help\"])\n});\nconst openMeldToolsControlCapabilitySchema = strictObject({\n\trequestAutomaticUpdate: literal(true).optional(),\n\trequestUpdate: literal(true).optional(),\n\tsetAutomaticUpdates: literal(true).optional()\n});\nconst openMeldToolsUpdateRequestResultSchema = discriminatedUnion(\"status\", [\n\tstrictObject({ status: literal(\"disabled\") }),\n\tstrictObject({ status: literal(\"unavailable\") }),\n\tstrictObject({\n\t\tcurrentVersion: nonEmptyStringSchema,\n\t\tstatus: literal(\"current\")\n\t}),\n\tstrictObject({\n\t\toperation: openMeldToolsUpdateOperationSchema,\n\t\tstatus: enumFactory([\"started\", \"already_running\"])\n\t})\n]);\nconst openMeldToolsMaintenanceMutationResultSchema = strictObject({\n\tautomaticUpdatesEnabled: boolean(),\n\tstatus: enumFactory([\"updated\", \"unchanged\"])\n});\nconst openMeldToolsControlRequestSchema = discriminatedUnion(\"operation\", [strictObject({\n\toperation: literal(\"request_update\"),\n\trequestSource: enumFactory([\n\t\t\"automatic\",\n\t\t\"center_agent\",\n\t\t\"web\"\n\t])\n}), strictObject({\n\tautomaticUpdatesEnabled: boolean(),\n\toperation: literal(\"set_automatic_updates\"),\n\trequestSource: enumFactory([\"center_agent\", \"web\"])\n})]);\nconst openMeldToolsControlResultSchema = discriminatedUnion(\"operation\", [strictObject({\n\toperation: literal(\"request_update\"),\n\tresult: openMeldToolsUpdateRequestResultSchema\n}), strictObject({\n\toperation: literal(\"set_automatic_updates\"),\n\tresult: openMeldToolsMaintenanceMutationResultSchema\n})]);\nconst openMeldToolsUpdateAttemptSchema = strictObject({\n\tv: literal(1),\n\tattempts: number().int().nonnegative(),\n\terrorMessage: nullableNonEmptyStringSchema,\n\toperation: openMeldToolsUpdateOperationSchema\n});\nconst localSetupActionSchema = enumFactory([\n\t\"none\",\n\t\"connect_service\",\n\t\"reconnect_service\",\n\t\"update_service\",\n\t\"connect_local_agent\",\n\t\"update_skills\",\n\t\"update_cli\"\n]);\nconst localSetupEntrypointSchema = literal(\"setup\");\nconst localComponentsManifestSchema = strictObject({\n\tschemaVersion: literal(1),\n\topenMeldReleaseVersion: nonEmptyStringSchema,\n\tcli: strictObject({\n\t\tpackageVersion: nonEmptyStringSchema,\n\t\tcommandContractVersion: nonEmptyStringSchema\n\t}),\n\tservice: strictObject({\n\t\tbundleHash: nullableNonEmptyStringSchema,\n\t\tbundleVersion: nonEmptyStringSchema,\n\t\truntimeContractEpoch: nonEmptyStringSchema,\n\t\tserviceContractVersion: nonEmptyStringSchema\n\t}),\n\tskills: strictObject({\n\t\tbundleHash: nullableNonEmptyStringSchema,\n\t\tskillContractVersion: nonEmptyStringSchema,\n\t\tskillIds: array(nonEmptyStringSchema)\n\t})\n});\nconst localComponentsReleaseManifestSchema = strictObject({\n\tschemaVersion: literal(1),\n\tupdatedAt: iso.datetime({ offset: true }),\n\tcomponents: strictObject({\n\t\tcli: strictObject({\n\t\t\tpackageVersion: nonEmptyStringSchema,\n\t\t\tcommandContractVersion: nonEmptyStringSchema,\n\t\t\tupdatePolicy: localComponentUpdatePolicySchema,\n\t\t\treason: nonEmptyStringSchema\n\t\t}),\n\t\tservice: strictObject({\n\t\t\tbundleHash: nullableNonEmptyStringSchema,\n\t\t\tportableBundleHash: nullableNonEmptyStringSchema.optional(),\n\t\t\tbundleVersion: nonEmptyStringSchema,\n\t\t\truntimeContractEpoch: nonEmptyStringSchema,\n\t\t\tserviceContractVersion: nonEmptyStringSchema,\n\t\t\tupdatePolicy: localComponentUpdatePolicySchema,\n\t\t\treason: nonEmptyStringSchema\n\t\t}),\n\t\tskills: strictObject({\n\t\t\tbundleHash: nullableNonEmptyStringSchema,\n\t\t\tskillContractVersion: nonEmptyStringSchema,\n\t\t\tskillIds: array(nonEmptyStringSchema),\n\t\t\tupdatePolicy: localComponentUpdatePolicySchema,\n\t\t\treason: nonEmptyStringSchema\n\t\t})\n\t})\n});\nconst localComponentsInstallationSourceSchema = strictObject({\n\tdistribution: enumFactory([\"binary\", \"npm\"]),\n\tchannel: enumFactory([\"stable\", \"windows-preview\"]),\n\tplatform: nonEmptyStringSchema\n}).superRefine((source, context) => {\n\tif (source.distribution === \"npm\" && source.channel !== \"stable\") context.addIssue({\n\t\tcode: \"custom\",\n\t\tmessage: \"npm uses the stable channel\"\n\t});\n});\nconst localComponentsBinaryReleasePolicySchema = strictObject({\n\tcli: localComponentsReleaseManifestSchema.shape.components.shape.cli,\n\tservice: localComponentsReleaseManifestSchema.shape.components.shape.service\n});\nconst localComponentsAvailabilityCatalogSchema = strictObject({\n\tschemaVersion: literal(1),\n\tentries: array(strictObject({\n\t\tchannel: enumFactory([\"stable\", \"windows-preview\"]),\n\t\tplatform: nonEmptyStringSchema,\n\t\tpolicy: localComponentsBinaryReleasePolicySchema\n\t}))\n}).superRefine((catalog, context) => {\n\tconst selectors = /* @__PURE__ */ new Set();\n\tfor (const entry of catalog.entries) {\n\t\tconst selector = `${entry.channel}:${entry.platform}`;\n\t\tif (selectors.has(selector)) context.addIssue({\n\t\t\tcode: \"custom\",\n\t\t\tmessage: \"duplicate binary release selector\"\n\t\t});\n\t\tselectors.add(selector);\n\t}\n});\nconst installedLocalComponentsSnapshotSchema = strictObject({\n\tschemaVersion: literal(1),\n\tinstalledAt: iso.datetime({ offset: true }),\n\tsource: enumFactory([\n\t\t\"setup\",\n\t\t\"repair\",\n\t\t\"manual\"\n\t]),\n\tmanifest: localComponentsManifestSchema\n});\nconst localComponentProjectionSchema = strictObject({\n\treasonCodes: array(nonEmptyStringSchema),\n\tstatus: localComponentStatusSchema\n});\nconst localCliComponentProjectionSchema = localComponentProjectionSchema.extend({\n\tcommandContractVersion: nonEmptyStringSchema,\n\tlatestPackageVersion: nullableNonEmptyStringSchema,\n\tpackageVersion: nonEmptyStringSchema,\n\trequiredCommandContractVersion: nullableNonEmptyStringSchema\n});\nconst localServiceComponentProjectionSchema = localComponentProjectionSchema.extend({\n\texpectedBundleHash: nullableNonEmptyStringSchema,\n\texpectedBundleVersion: nonEmptyStringSchema,\n\tinstalledBundleHash: nullableNonEmptyStringSchema,\n\tinstalledBundleVersion: nullableNonEmptyStringSchema,\n\truntimeContractEpoch: nonEmptyStringSchema,\n\tserviceContractVersion: nonEmptyStringSchema\n});\nconst localSkillsComponentProjectionSchema = localComponentProjectionSchema.extend({\n\tcontentRelease: strictObject({\n\t\trevision: number().int().positive(),\n\t\tminimumCliVersion: string().regex(/^\\d+\\.\\d+\\.\\d+$/)\n\t}).optional(),\n\texpectedBundleHash: nullableNonEmptyStringSchema,\n\tinstalledBundleHash: nullableNonEmptyStringSchema,\n\tskillContractVersion: nonEmptyStringSchema,\n\ttargetCount: number().int().nonnegative()\n});\nconst localComponentsStatusSchema = strictObject({\n\tinstallationSource: localComponentsInstallationSourceSchema.optional(),\n\tschemaVersion: literal(1),\n\tgeneratedAt: iso.datetime({ offset: true }),\n\tentrypoint: localSetupEntrypointSchema,\n\tsummaryLabel: nonEmptyStringSchema,\n\tsummaryDescription: nonEmptyStringSchema,\n\tsetupAction: localSetupActionSchema,\n\tsetupActionLabel: nonEmptyStringSchema,\n\tsetupActionDescription: nonEmptyStringSchema,\n\tmaintenance: openMeldToolsMaintenanceProjectionSchema.optional(),\n\tupdateOperation: openMeldToolsUpdateOperationSchema.optional(),\n\tcli: localCliComponentProjectionSchema,\n\tservice: localServiceComponentProjectionSchema,\n\tskills: localSkillsComponentProjectionSchema\n});\nconst localServiceComponentUpdateProjectionSchema = strictObject({\n\tinstalledVersion: nullableNonEmptyStringSchema,\n\tlatestVersion: nullableNonEmptyStringSchema,\n\treasonCodes: array(nonEmptyStringSchema),\n\trequiredVersion: nullableNonEmptyStringSchema,\n\tstatus: localComponentUpdateStatusSchema,\n\tupdatePolicy: localComponentUpdatePolicySchema,\n\twakeBlocked: boolean()\n});\nconst localCliComponentUpdateProjectionSchema = strictObject({\n\tcommandContractVersion: nullableNonEmptyStringSchema,\n\tinstalledPackageVersion: nullableNonEmptyStringSchema,\n\tlatestPackageVersion: nullableNonEmptyStringSchema,\n\treasonCodes: array(nonEmptyStringSchema),\n\trequiredCommandContractVersion: nullableNonEmptyStringSchema,\n\tstatus: localComponentUpdateStatusSchema,\n\tupdatePolicy: localComponentUpdatePolicySchema,\n\twakeBlocked: boolean()\n});\nconst localSkillsComponentUpdateProjectionSchema = strictObject({\n\texpectedBundleHash: nullableNonEmptyStringSchema,\n\texpectedTargetCount: number().int().nonnegative(),\n\tinstalledBundleHash: nullableNonEmptyStringSchema,\n\treasonCodes: array(nonEmptyStringSchema),\n\tskillContractVersion: nullableNonEmptyStringSchema,\n\tstatus: localComponentUpdateStatusSchema,\n\ttargetCount: number().int().nonnegative().nullable(),\n\tupdatePolicy: localComponentUpdatePolicySchema,\n\twakeBlocked: boolean()\n});\nconst localComponentUpdateProjectionSchema = strictObject({\n\tschemaVersion: literal(1),\n\tgeneratedAt: iso.datetime({ offset: true }),\n\tsetupAction: localSetupActionSchema,\n\tsetupActionLabel: nonEmptyStringSchema,\n\tsetupActionDescription: nonEmptyStringSchema,\n\thumanSetupCommand: nonEmptyStringSchema,\n\tagentSetupCommand: nonEmptyStringSchema,\n\tmaintenance: openMeldToolsMaintenanceProjectionSchema.optional(),\n\tupdateOperation: openMeldToolsUpdateOperationSchema.optional(),\n\tcli: localCliComponentUpdateProjectionSchema,\n\tservice: localServiceComponentUpdateProjectionSchema,\n\tskills: localSkillsComponentUpdateProjectionSchema\n});\nfunction formatLocalSetupActionLabel(action) {\n\tswitch (action) {\n\t\tcase \"connect_service\": return \"Connect Computer\";\n\t\tcase \"reconnect_service\": return \"Reconnect Computer\";\n\t\tcase \"update_service\": return \"Update OpenMeld on Computer\";\n\t\tcase \"connect_local_agent\": return \"Connect local agent\";\n\t\tcase \"update_skills\": return \"Update OpenMeld skills\";\n\t\tcase \"update_cli\": return \"Update OpenMeld CLI\";\n\t\tcase \"none\": return \"Everything is up to date\";\n\t\tdefault: return action;\n\t}\n}\nfunction formatOpenMeldToolsUpdateFailureMessage(code) {\n\tswitch (code) {\n\t\tcase \"cli.update.download_stalled\": return \"The update download stopped making progress. Check this computer's connection and try again.\";\n\t\tcase \"cli.update.download_timed_out\": return \"The update download exceeded its recovery time. Check this computer's connection and try again.\";\n\t\tcase \"cli.update.download_failed\": return \"The update could not be downloaded. Check this computer's connection and try again.\";\n\t\tcase \"cli.update.integrity_check_failed\": return \"The downloaded update did not pass integrity checks, so it was not installed.\";\n\t\tcase \"cli.update.install_failed\": return \"The update could not be installed.\";\n\t\tcase \"cli.update.service_alignment_failed\": return \"OpenMeld Service could not finish updating.\";\n\t\tcase \"cli.update.failed\": return \"The update could not be completed. Try again or update manually.\";\n\t\tdefault: return code;\n\t}\n}\nfunction findOpenMeldToolsUpdateFailureCode(reasonCodes) {\n\tfor (const reasonCode of reasonCodes) {\n\t\tconst parsed = openMeldToolsUpdateFailureCodeSchema.safeParse(reasonCode);\n\t\tif (parsed.success) return parsed.data;\n\t}\n\treturn null;\n}\nfunction formatLocalComponentsSummaryLabel(input) {\n\tif (input.setupAction !== \"none\") return formatLocalSetupActionLabel(input.setupAction);\n\tswitch (input.cliStatus) {\n\t\tcase \"update_required\": return \"Update OpenMeld CLI\";\n\t\tcase \"update_available\": return \"OpenMeld CLI update available\";\n\t\tcase \"ok\": return \"Everything is up to date\";\n\t\tdefault: return input.cliStatus;\n\t}\n}\nfunction formatLocalComponentsSummaryDescription(input) {\n\tif (input.setupAction !== \"none\") return formatLocalSetupActionDescription(input.setupAction);\n\tswitch (input.cliStatus) {\n\t\tcase \"update_required\": return \"Update OpenMeld CLI before running this setup flow.\";\n\t\tcase \"update_available\": return \"OpenMeld CLI can be updated, but this setup flow can continue.\";\n\t\tcase \"ok\": return \"OpenMeld local components are aligned for this computer.\";\n\t\tdefault: return input.cliStatus;\n\t}\n}\nfunction formatLocalSetupActionDescription(action) {\n\tswitch (action) {\n\t\tcase \"connect_service\": return \"Connect this computer to OpenMeld so local agents can reply in Spaces.\";\n\t\tcase \"reconnect_service\": return \"Reconnect this computer to the current OpenMeld account.\";\n\t\tcase \"update_service\": return \"Update OpenMeld on this computer.\";\n\t\tcase \"connect_local_agent\": return \"Connect this Agent Profile to a local agent runtime on this computer.\";\n\t\tcase \"update_skills\": return \"Update OpenMeld skills through setup on this computer.\";\n\t\tcase \"update_cli\": return \"Update OpenMeld CLI before running this setup flow.\";\n\t\tcase \"none\": return \"OpenMeld local components are aligned for this computer.\";\n\t\tdefault: return action;\n\t}\n}\n//#endregion\nexport { LOCAL_COMPONENTS_SCHEMA_VERSION, OPEN_MELD_TOOLS_UPDATE_FAILURE_DETAIL_MAX_CHARS, findOpenMeldToolsUpdateFailureCode, findOpenMeldToolsUpdateStep, formatLocalComponentsSummaryDescription, formatLocalComponentsSummaryLabel, formatLocalSetupActionDescription, formatLocalSetupActionLabel, formatOpenMeldToolsUpdateFailureMessage, installedLocalComponentsSnapshotSchema, localCliComponentProjectionSchema, localCliComponentUpdateProjectionSchema, localComponentProjectionSchema, localComponentStatusSchema, localComponentUpdatePolicySchema, localComponentUpdateProjectionSchema, localComponentUpdateStatusSchema, localComponentsAvailabilityCatalogSchema, localComponentsBinaryReleasePolicySchema, localComponentsInstallationSourceSchema, localComponentsManifestSchema, localComponentsReleaseManifestSchema, localComponentsStatusSchema, localServiceComponentProjectionSchema, localServiceComponentUpdateProjectionSchema, localSetupActionSchema, localSetupEntrypointSchema, localSkillsComponentProjectionSchema, localSkillsComponentUpdateProjectionSchema, openMeldToolsControlCapabilitySchema, openMeldToolsControlRequestSchema, openMeldToolsControlResultSchema, openMeldToolsMaintenanceMutationResultSchema, openMeldToolsMaintenanceProjectionSchema, openMeldToolsUpdateAttemptSchema, openMeldToolsUpdateCheckpointSchema, openMeldToolsUpdateFailureCodeSchema, openMeldToolsUpdateOperationPhaseSchema, openMeldToolsUpdateOperationSchema, openMeldToolsUpdateProcessFailureFrameSchema, openMeldToolsUpdateRequestResultSchema, openMeldToolsUpdateRequestSourceSchema, openMeldToolsUpdateStepCode, openMeldToolsUpdateStepSchema, resolveOpenMeldToolsUpdateTargetVersions };\n\n//# sourceMappingURL=local-components.js.map"],"mappings":"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"}