openmeld 0.3.222 → 0.3.224
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{add-me-membership-Wc69O6rA.js → add-me-membership-CGISMRPF.js} +2 -2
- package/dist/{add-me-membership-Wc69O6rA.js.map → add-me-membership-CGISMRPF.js.map} +1 -1
- package/dist/{agents-B8zhQnGw.js → agents-CR7BebgO.js} +12 -12
- package/dist/{agents-B8zhQnGw.js.map → agents-CR7BebgO.js.map} +1 -1
- package/dist/{api-client-foundation-DTiFoGpI.js → api-client-foundation-CqbIn_de.js} +1 -1
- package/dist/{api-client-foundation-DnJ_JYli.js → api-client-foundation-DpVwrgh-.js} +3 -3
- package/dist/{api-client-foundation-DnJ_JYli.js.map → api-client-foundation-DpVwrgh-.js.map} +1 -1
- package/dist/auth-session-BJfKu74u.js +4 -0
- package/dist/{auth-session-nhS8jyux.js → auth-session-uEk_Tx6T.js} +8 -8
- package/dist/auth-session-uEk_Tx6T.js.map +1 -0
- package/dist/{base-url-CMBApK1J.js → base-url-DXrUiSMI.js} +1 -1
- package/dist/{base-url-D7uE_xTo.js → base-url-DvjOkKPs.js} +2 -2
- package/dist/{base-url-D7uE_xTo.js.map → base-url-DvjOkKPs.js.map} +1 -1
- package/dist/{channel-ggx0o_aG.js → channel-B2fD2_be.js} +4 -4
- package/dist/{channel-ggx0o_aG.js.map → channel-B2fD2_be.js.map} +1 -1
- package/dist/{cli-binary-manifest-DiUulkp0.js → cli-binary-manifest-CT5X05lk.js} +30 -4
- package/dist/cli-binary-manifest-CT5X05lk.js.map +1 -0
- package/dist/{command-Bz9x7V2T.js → command-CQ9XRwqf.js} +22 -165
- package/dist/command-CQ9XRwqf.js.map +1 -0
- package/dist/{computer-connection-M3N6plkj.js → computer-connection-Dm7iTnRK.js} +2 -2
- package/dist/{computer-connection-M3N6plkj.js.map → computer-connection-Dm7iTnRK.js.map} +1 -1
- package/dist/{computer-connection-review-DY5BK_27.js → computer-connection-review-RHAoddSS.js} +6 -6
- package/dist/{computer-connection-review-DY5BK_27.js.map → computer-connection-review-RHAoddSS.js.map} +1 -1
- package/dist/{computer-disconnect-DR1WDSPK.js → computer-disconnect-BWRsge_2.js} +10 -10
- package/dist/{computer-disconnect-DR1WDSPK.js.map → computer-disconnect-BWRsge_2.js.map} +1 -1
- package/dist/{computer-setup-continuation-2gs8z-nB.js → computer-setup-continuation-BOCRH0qq.js} +4 -4
- package/dist/{computer-setup-continuation-2gs8z-nB.js.map → computer-setup-continuation-BOCRH0qq.js.map} +1 -1
- package/dist/context-Bdh3nAzw.js +162 -0
- package/dist/context-Bdh3nAzw.js.map +1 -0
- package/dist/{control-plane-e3W6PD2M.js → control-plane-rTE2rHZ5.js} +2 -2
- package/dist/{control-plane-e3W6PD2M.js.map → control-plane-rTE2rHZ5.js.map} +1 -1
- package/dist/{daemon-device-id-DWO9_QW6.js → daemon-device-id-B1Af2Zmn.js} +344 -36
- package/dist/daemon-device-id-B1Af2Zmn.js.map +1 -0
- package/dist/{daemon-frame-transport-D2-tazuK.js → daemon-frame-transport-WiB73yhT.js} +519 -12
- package/dist/daemon-frame-transport-WiB73yhT.js.map +1 -0
- package/dist/{daemon-lifecycle-journal-DyKx1xzm.js → daemon-lifecycle-journal-CDZLWgMj.js} +11 -11
- package/dist/daemon-lifecycle-journal-CDZLWgMj.js.map +1 -0
- package/dist/{daemon-runtime-lease-BUr4qsLo.js → daemon-runtime-lease-1LMeZ6IS.js} +2 -2
- package/dist/{daemon-runtime-lease-BUr4qsLo.js.map → daemon-runtime-lease-1LMeZ6IS.js.map} +1 -1
- package/dist/{daemon-runtime-lease-C9X8xV_F.js → daemon-runtime-lease-Bz0ucJj3.js} +1 -1
- package/dist/{daemon-service-contract-BpOBMGX0.js → daemon-service-contract-GLmAxsq-.js} +4 -4
- package/dist/{daemon-service-contract-BpOBMGX0.js.map → daemon-service-contract-GLmAxsq-.js.map} +1 -1
- package/dist/{daemon-service-manager-HL4VKbIU.js → daemon-service-manager-C8RUCMDo.js} +9 -7
- package/dist/daemon-service-manager-C8RUCMDo.js.map +1 -0
- package/dist/{daemon-service-manager-B-QrDe5p.js → daemon-service-manager-CU-79a4z.js} +1 -1
- package/dist/{daemon-service-runtime-bKt0YjC7.js → daemon-service-runtime-CBJtgM4P.js} +397 -51
- package/dist/daemon-service-runtime-CBJtgM4P.js.map +1 -0
- package/dist/{daemon-service-update-coordinator-D8O1uTtu.js → daemon-service-update-coordinator-0LB_XGVZ.js} +48 -33
- package/dist/daemon-service-update-coordinator-0LB_XGVZ.js.map +1 -0
- package/dist/{daemon-state-B44aq2nm.js → daemon-state-Ca0WK5x0.js} +3 -3
- package/dist/{daemon-state-B44aq2nm.js.map → daemon-state-Ca0WK5x0.js.map} +1 -1
- package/dist/{dist-B07ziN_u.js → dist-BeJcIdCZ.js} +25 -17
- package/dist/dist-BeJcIdCZ.js.map +1 -0
- package/dist/dist-C32frPV2.js +4 -0
- package/dist/{dist-B2EauBG6.js → dist-YbTZ-Y-2.js} +16 -12
- package/dist/dist-YbTZ-Y-2.js.map +1 -0
- package/dist/{elapsed-time-Ooo4IC25.js → elapsed-time-q8lSPcfm.js} +6 -6
- package/dist/{elapsed-time-Ooo4IC25.js.map → elapsed-time-q8lSPcfm.js.map} +1 -1
- package/dist/{entry-DeIRMCiW.js → entry-CpS6tnIk.js} +12 -12
- package/dist/{entry-DeIRMCiW.js.map → entry-CpS6tnIk.js.map} +1 -1
- package/dist/{installation-inventory-DThnBEhV.js → installation-inventory-C5FsAvrf.js} +5 -5
- package/dist/{installation-inventory-DThnBEhV.js.map → installation-inventory-C5FsAvrf.js.map} +1 -1
- package/dist/{installer-D2bWZT88.js → installer-054NLJg6.js} +2 -2
- package/dist/{installer-D2bWZT88.js.map → installer-054NLJg6.js.map} +1 -1
- package/dist/io-DT66typ4.js +16 -0
- package/dist/io-DT66typ4.js.map +1 -0
- package/dist/{local-components-B6SCXZf9.js → local-components-DleLEzSU.js} +2 -1
- package/dist/local-components-DleLEzSU.js.map +1 -0
- package/dist/{lock-Bsl_ElWy.js → lock-iue1J2xy.js} +8 -5
- package/dist/lock-iue1J2xy.js.map +1 -0
- package/dist/{cli-space-api-CQtKu9Zt.js → meta-api-B1k3mwHN.js} +203 -19
- package/dist/meta-api-B1k3mwHN.js.map +1 -0
- package/dist/{openmeld-BQy0nMox.js → openmeld-BFO3sfC_.js} +93 -1027
- package/dist/openmeld-BFO3sfC_.js.map +1 -0
- package/dist/openmeld-dev.js +1 -1
- package/dist/{openmeld-environment-target-B6HqY0_a.js → openmeld-environment-target-BBn5Ko6p.js} +3 -3
- package/dist/{openmeld-environment-target-B6HqY0_a.js.map → openmeld-environment-target-BBn5Ko6p.js.map} +1 -1
- package/dist/{openmeld-maintenance-worker-BSODPHbn.js → openmeld-maintenance-worker-Ce4ehQ-c.js} +15 -14
- package/dist/openmeld-maintenance-worker-Ce4ehQ-c.js.map +1 -0
- package/dist/{openmeld-tools-update-join-BfY0GnDs.js → openmeld-tools-update-join-D24llJ9L.js} +4 -4
- package/dist/{openmeld-tools-update-join-BfY0GnDs.js.map → openmeld-tools-update-join-D24llJ9L.js.map} +1 -1
- package/dist/{openmeld-tools-update-process-frame-B-XB4dmO.js → openmeld-tools-update-process-frame-BtFKp70p.js} +2 -2
- package/dist/{openmeld-tools-update-process-frame-B-XB4dmO.js.map → openmeld-tools-update-process-frame-BtFKp70p.js.map} +1 -1
- package/dist/{openmeld-tools-update-process-frame-j-RXwFsK.js → openmeld-tools-update-process-frame-DbEZ3fEh.js} +1 -1
- package/dist/openmeld.js +9 -5
- package/dist/openmeld.js.map +1 -1
- package/dist/{prepare-provider-runtime-CWZcuMF6.js → prepare-provider-runtime-MB-BxOgt.js} +3342 -1327
- package/dist/prepare-provider-runtime-MB-BxOgt.js.map +1 -0
- package/dist/{prepare-session-executor-CkDxstsf.js → prepare-session-executor-zvSZ6jqy.js} +29 -28
- package/dist/prepare-session-executor-zvSZ6jqy.js.map +1 -0
- package/dist/{presenter-BcxiQyJg.js → presenter-MJ5YgsOT.js} +3 -13
- package/dist/presenter-MJ5YgsOT.js.map +1 -0
- package/dist/{process-channel-BQwtOlRc.js → process-channel-CgbduFCz.js} +2 -2
- package/dist/{process-channel-BQwtOlRc.js.map → process-channel-CgbduFCz.js.map} +1 -1
- package/dist/process-environment-BWSFeUu6.js +49 -0
- package/dist/process-environment-BWSFeUu6.js.map +1 -0
- package/dist/process-identity-BQLdaZdB.js +190 -0
- package/dist/process-identity-BQLdaZdB.js.map +1 -0
- package/dist/process-launch-B0pHlkV_.js +173 -0
- package/dist/process-launch-B0pHlkV_.js.map +1 -0
- package/dist/{published-production-safety-dp-fOmmB.js → published-production-safety-C40hKrBA.js} +2 -2
- package/dist/{published-production-safety-dp-fOmmB.js.map → published-production-safety-C40hKrBA.js.map} +1 -1
- package/dist/{runtime-BYaFkkLK.js → runtime-D6jItuQ-.js} +155 -702
- package/dist/runtime-D6jItuQ-.js.map +1 -0
- package/dist/{runtime-agent-controller-reporting-submission-BUUub9_1.js → runtime-agent-controller-reporting-submission-D9ysbi7R.js} +9 -9
- package/dist/{runtime-agent-controller-reporting-submission-BUUub9_1.js.map → runtime-agent-controller-reporting-submission-D9ysbi7R.js.map} +1 -1
- package/dist/{runtime-reporting-health-state-BgwfrH7f.js → runtime-reporting-health-state-DA-_vW-n.js} +2210 -60
- package/dist/runtime-reporting-health-state-DA-_vW-n.js.map +1 -0
- package/dist/{runtime-transport-Cc_RN-PL.js → runtime-transport-YIYHSJPn.js} +99 -14
- package/dist/runtime-transport-YIYHSJPn.js.map +1 -0
- package/dist/{service-CfO38_a-.js → service-Dz2MsvGr.js} +126 -550
- package/dist/service-Dz2MsvGr.js.map +1 -0
- package/dist/{service-account-admission-Dy2W3n3_.js → service-account-admission-BfdJ-kKR.js} +18 -10
- package/dist/service-account-admission-BfdJ-kKR.js.map +1 -0
- package/dist/{service-account-authorization-DKpIpxXo.js → service-account-authorization-DZbUOD29.js} +6 -6
- package/dist/{service-account-authorization-DKpIpxXo.js.map → service-account-authorization-DZbUOD29.js.map} +1 -1
- package/dist/{service-account-control-CCPQAZzn.js → service-account-control-DCMOKXDT.js} +16 -16
- package/dist/service-account-control-DCMOKXDT.js.map +1 -0
- package/dist/{service-control-capabilities-C9UHSMPz.js → service-control-capabilities-3_bdeHXu.js} +1 -1
- package/dist/{service-control-capabilities-xGylBNoH.js → service-control-capabilities-Bb738e_d.js} +19 -15
- package/dist/service-control-capabilities-Bb738e_d.js.map +1 -0
- package/dist/{service-control-carrier-capability-DDNyE5cB.js → service-control-carrier-capability-gMk5gMKU.js} +11 -4
- package/dist/service-control-carrier-capability-gMk5gMKU.js.map +1 -0
- package/dist/{state-CQG3k9eh.js → state-GxF_KAM1.js} +4 -4
- package/dist/{state-CQG3k9eh.js.map → state-GxF_KAM1.js.map} +1 -1
- package/dist/{upgrade-D5FxGbh1.js → upgrade-DfJwCD5H.js} +52 -32
- package/dist/upgrade-DfJwCD5H.js.map +1 -0
- package/dist/upgrade-DgmYWeNu.js +4 -0
- package/dist/windows/openmeld-windows-process.exe +0 -0
- package/dist/windows-artifact-DJ9DKjfc.js +16 -0
- package/dist/windows-artifact-DJ9DKjfc.js.map +1 -0
- package/dist/windows-task-command-COu_6Ke3.js +74 -0
- package/dist/windows-task-command-COu_6Ke3.js.map +1 -0
- package/dist/windows-task-entry-CtRpUbiK.js +50 -0
- package/dist/windows-task-entry-CtRpUbiK.js.map +1 -0
- package/dist/{windows-user-task-Bx2yYnOM.js → windows-user-task-B8NcRg_u.js} +1 -1
- package/dist/{windows-user-task-CRGbKggi.js → windows-user-task-Io5QuEVR.js} +108 -51
- package/dist/windows-user-task-Io5QuEVR.js.map +1 -0
- package/package.json +12 -12
- package/skills/openmeld-cli/playbooks/space-ops.md +9 -3
- package/skills/openmeld-cli/references/commands.md +0 -1
- package/dist/auth-session-D8dbMpaK.js +0 -4
- package/dist/auth-session-nhS8jyux.js.map +0 -1
- package/dist/cli-binary-manifest-DiUulkp0.js.map +0 -1
- package/dist/cli-space-api-CQtKu9Zt.js.map +0 -1
- package/dist/command-Bz9x7V2T.js.map +0 -1
- package/dist/context-l_31Mn4X.js +0 -473
- package/dist/context-l_31Mn4X.js.map +0 -1
- package/dist/daemon-device-id-DWO9_QW6.js.map +0 -1
- package/dist/daemon-frame-transport-D2-tazuK.js.map +0 -1
- package/dist/daemon-lifecycle-journal-DyKx1xzm.js.map +0 -1
- package/dist/daemon-service-manager-HL4VKbIU.js.map +0 -1
- package/dist/daemon-service-runtime-bKt0YjC7.js.map +0 -1
- package/dist/daemon-service-update-coordinator-D8O1uTtu.js.map +0 -1
- package/dist/dist-B07ziN_u.js.map +0 -1
- package/dist/dist-B2EauBG6.js.map +0 -1
- package/dist/dist-DhWI1iyi.js +0 -4
- package/dist/local-components-B6SCXZf9.js.map +0 -1
- package/dist/lock-Bsl_ElWy.js.map +0 -1
- package/dist/openmeld-BQy0nMox.js.map +0 -1
- package/dist/openmeld-maintenance-worker-BSODPHbn.js.map +0 -1
- package/dist/prepare-provider-runtime-CWZcuMF6.js.map +0 -1
- package/dist/prepare-session-executor-CkDxstsf.js.map +0 -1
- package/dist/presenter-BcxiQyJg.js.map +0 -1
- package/dist/process-identity-CNus0e6E.js +0 -146
- package/dist/process-identity-CNus0e6E.js.map +0 -1
- package/dist/runtime-BYaFkkLK.js.map +0 -1
- package/dist/runtime-reporting-health-state-BgwfrH7f.js.map +0 -1
- package/dist/runtime-transport-Cc_RN-PL.js.map +0 -1
- package/dist/service-CfO38_a-.js.map +0 -1
- package/dist/service-account-admission-Dy2W3n3_.js.map +0 -1
- package/dist/service-account-control-CCPQAZzn.js.map +0 -1
- package/dist/service-control-capabilities-xGylBNoH.js.map +0 -1
- package/dist/service-control-carrier-capability-DDNyE5cB.js.map +0 -1
- package/dist/upgrade-D5FxGbh1.js.map +0 -1
- package/dist/upgrade-DhFEu0k6.js +0 -4
- package/dist/windows-user-task-CRGbKggi.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-CQG3k9eh.js","names":["getErrorCode"],"sources":["../../../packages/schemas/dist/official-cli-skill.js","../src/skills/bundled.ts","../src/skills/bundled-assets-fs.ts","../src/skills/bundled-assets.ts","../src/skills/content-hash.ts","../src/skills/install-lock.ts","../src/skills/official-release.ts","../src/skills/replace-directory.ts","../src/skills/store.ts","../src/skills/state.ts"],"sourcesContent":["import * as z$1 from \"zod/v4\";\n//#region src/official-cli-skill.ts\nconst OFFICIAL_CLI_SKILL_CONTRACT = \"openmeld-skills-contract-2026-09-explicit-space-recipients-v1\";\nconst OFFICIAL_CLI_SKILL_URL = \"https://openmeld.ai/skills/openmeld-cli/SKILL.md\";\nconst OFFICIAL_CLI_SKILL_MAX_BYTES = 1048576;\nconst OFFICIAL_CLI_SKILL_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAFZjFHrQ/QLsJQpHkAbKBRG57fEazhm7zc0dMa54ilWQ=\n-----END PUBLIC KEY-----\n`;\nconst officialCliSkillPayloadSchema = z$1.object({\n\tschemaVersion: z$1.literal(1),\n\trevision: z$1.number().int().positive(),\n\tminimumCliVersion: z$1.string().regex(/^\\d+\\.\\d+\\.\\d+$/),\n\tcontractVersion: z$1.string().min(1).max(128),\n\tfiles: z$1.array(z$1.object({\n\t\tpath: z$1.string().regex(/^(?:SKILL\\.md|(?:playbooks|references)\\/[a-z0-9-]+\\.md)$/),\n\t\tcontent: z$1.string().min(1).max(131072)\n\t}).strict()).min(1).max(32)\n}).strict().superRefine((value, context) => {\n\tconst paths = value.files.map((file) => file.path);\n\tif (!paths.includes(\"SKILL.md\") || new Set(paths).size !== paths.length) context.addIssue({\n\t\tcode: \"custom\",\n\t\tmessage: \"Skill entry is required and paths must be unique\"\n\t});\n});\nconst officialCliSkillReleaseSchema = z$1.object({\n\tpayload: z$1.string().min(1).max(524288),\n\tsignature: z$1.string().regex(/^[A-Za-z0-9+/]{86}==$/)\n}).strict();\nconst officialCliSkillChannelSchema = z$1.object({\n\tschemaVersion: z$1.literal(1),\n\treleases: z$1.array(officialCliSkillReleaseSchema).min(1).max(16)\n}).strict();\n//#endregion\nexport { OFFICIAL_CLI_SKILL_CONTRACT, OFFICIAL_CLI_SKILL_MAX_BYTES, OFFICIAL_CLI_SKILL_PUBLIC_KEY, OFFICIAL_CLI_SKILL_URL, officialCliSkillChannelSchema, officialCliSkillPayloadSchema, officialCliSkillReleaseSchema };\n\n//# sourceMappingURL=official-cli-skill.js.map","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst CLI_PACKAGE_JSON = \"package.json\";\n\nexport type BundledSkillsLocation = {\n cliRootDir: string;\n skillsRootDir: string;\n};\n\n/**\n * Locate the on-disk bundled skills directory for the npm distribution by\n * walking up from this module to the CLI package root (a directory that has\n * both package.json and skills/). Returns null under the binary distribution,\n * where import.meta.url is a virtual path and the skills are embedded instead —\n * callers in that mode go through bundled-assets.ts, not this function.\n */\nexport function resolveBundledSkillsLocation(): BundledSkillsLocation | null {\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const cliRootDir = resolveCliRootDir(moduleDir);\n if (!cliRootDir) {\n return null;\n }\n return {\n cliRootDir,\n skillsRootDir: path.join(cliRootDir, \"skills\"),\n };\n}\n\nfunction resolveCliRootDir(fromDir: string): string | null {\n let current = fromDir;\n for (;;) {\n const packageJsonPath = path.join(current, CLI_PACKAGE_JSON);\n const hasPackageJson = existsSync(packageJsonPath);\n const hasSkillsDir = existsSync(path.join(current, \"skills\"));\n if (hasPackageJson && hasSkillsDir) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { resolveBundledSkillsLocation } from \"./bundled\";\nimport type { BundledSkillAsset } from \"./bundled-assets\";\n\n/**\n * npm-distribution source: read the bundled skills from the on-disk `skills/`\n * directory next to the CLI package. Assets are sorted by relative path so the\n * order (and therefore any content hash computed from them) is stable and\n * matches the embedded distribution.\n */\nexport async function loadFsBundledSkillAssets(): Promise<BundledSkillAsset[]> {\n const location = resolveBundledSkillsLocation();\n if (!location) {\n throw new Error(\"unable to resolve bundled OpenMeld skills directory\");\n }\n const assets = await collectSkillAssets(\n location.skillsRootDir,\n location.skillsRootDir\n );\n return sortBundledSkillAssets(assets);\n}\n\nexport function sortBundledSkillAssets(\n assets: BundledSkillAsset[]\n): BundledSkillAsset[] {\n return [...assets].sort((left, right) =>\n left.relativePath.localeCompare(right.relativePath)\n );\n}\n\nasync function collectSkillAssets(\n dir: string,\n rootDir: string\n): Promise<BundledSkillAsset[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const assets: BundledSkillAsset[] = [];\n for (const entry of entries) {\n const absolutePath = join(dir, entry.name);\n if (entry.isDirectory()) {\n assets.push(...(await collectSkillAssets(absolutePath, rootDir)));\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n assets.push({\n relativePath: toPosixRelativePath(relative(rootDir, absolutePath)),\n content: await readFile(absolutePath),\n });\n }\n return assets;\n}\n\nfunction toPosixRelativePath(value: string): string {\n return value.split(\"\\\\\").join(\"/\");\n}\n","import { createHash } from \"node:crypto\";\nimport { isBinaryDistribution } from \"../runtime/distribution\";\nimport { loadFsBundledSkillAssets } from \"./bundled-assets-fs\";\n\n/**\n * One bundled skill file, addressed by its POSIX path relative to the skills/\n * root (e.g. \"README.md\", \"openmeld-cli/SKILL.md\"). This is the single shape\n * both distribution forms produce, so downstream skill install and bundle-hash\n * logic never branches on how the files were sourced.\n */\nexport type BundledSkillAsset = {\n relativePath: string;\n content: Buffer;\n};\n\n/**\n * Load the OpenMeld-managed skill files that ship with this CLI build.\n *\n * - npm distribution: read from the on-disk `skills/` directory.\n * - binary distribution: read from files embedded into the single binary at\n * compile time. The embedded module is a Bun-only island resolved only by\n * `bun build --compile`; the npm build never reaches this branch and marks\n * the module external, so its `with { type: \"file\" }` imports are never\n * parsed by tsdown.\n */\nexport async function loadBundledSkillAssets(): Promise<BundledSkillAsset[]> {\n if (isBinaryDistribution()) {\n const embedded = await import(\"./bundled-assets-embedded\");\n return embedded.loadEmbeddedBundledSkillAssets();\n }\n return loadFsBundledSkillAssets();\n}\n\n/**\n * Content hash over an ordered list of skill assets. Byte-for-byte compatible\n * with `computeDirectoryContentHash` (same `file:<relativePath>\\n<content>\\n`\n * framing) so the embedded and on-disk sources produce identical hashes as long\n * as `assets` is sorted by relative path (as `loadBundledSkillAssets` returns\n * it). This is the single skills-hash algorithm for both distribution forms.\n */\nexport function hashBundledSkillAssets(assets: BundledSkillAsset[]): string {\n const hash = createHash(\"sha256\");\n for (const asset of assets) {\n hash.update(`file:${asset.relativePath}\\n`);\n hash.update(asset.content);\n hash.update(\"\\n\");\n }\n return hash.digest(\"hex\");\n}\n\nconst OPENMELD_CLI_SKILL_ID = \"openmeld-cli\";\nconst OPENMELD_CLI_SKILL_FILE = \"SKILL.md\";\n\n/**\n * Read one OpenMeld CLI skill document by its path relative to the skill root\n * (e.g. \"SKILL.md\", \"references/commands.md\"). Works in both distribution forms\n * via loadBundledSkillAssets, so `openmeld prompt --raw` renders the bundled\n * markdown from the embedded binary too.\n */\nexport async function readBundledOpenMeldCliSkillDocumentByPath(\n skillRelativePath: string\n): Promise<string> {\n const targetPath = `${OPENMELD_CLI_SKILL_ID}/${skillRelativePath}`;\n const assets = await loadBundledSkillAssets();\n const asset = assets.find((item) => item.relativePath === targetPath);\n if (!asset) {\n throw new Error(\n `bundled OpenMeld CLI skill document is missing: ${skillRelativePath}`\n );\n }\n return asset.content.toString(\"utf8\");\n}\n\nexport function readBundledOpenMeldCliSkillDocument(): Promise<string> {\n return readBundledOpenMeldCliSkillDocumentByPath(OPENMELD_CLI_SKILL_FILE);\n}\n","import { createHash } from \"node:crypto\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\n\nexport async function computeDirectoryContentHash(input: {\n rootDir: string;\n ignoredNames?: string[];\n}): Promise<string> {\n const ignoredNames = new Set(input.ignoredNames ?? []);\n const files = await collectFiles({\n dir: input.rootDir,\n rootDir: input.rootDir,\n ignoredNames,\n });\n const hash = createHash(\"sha256\");\n for (const file of files) {\n hash.update(`file:${file.relativePath}\\n`);\n hash.update(file.content);\n hash.update(\"\\n\");\n }\n return hash.digest(\"hex\");\n}\n\nasync function collectFiles(input: {\n dir: string;\n rootDir: string;\n ignoredNames: Set<string>;\n}): Promise<Array<{ relativePath: string; content: Buffer }>> {\n const entries = await readdir(input.dir, { withFileTypes: true }).catch(\n (error: unknown) => {\n if (getErrorCode(error) === \"ENOENT\") {\n return [];\n }\n warnDirectoryReadError(input.dir, error);\n throw error;\n }\n );\n entries.sort((a, b) => a.name.localeCompare(b.name));\n\n const files: Array<{ relativePath: string; content: Buffer }> = [];\n for (const entry of entries) {\n if (input.ignoredNames.has(entry.name)) {\n continue;\n }\n const absolutePath = join(input.dir, entry.name);\n if (entry.isDirectory()) {\n files.push(\n ...(await collectFiles({\n dir: absolutePath,\n rootDir: input.rootDir,\n ignoredNames: input.ignoredNames,\n }))\n );\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n const content = await readFile(absolutePath);\n files.push({\n relativePath: normalizeRelativePath(\n relative(input.rootDir, absolutePath)\n ),\n content,\n });\n }\n return files;\n}\n\nfunction normalizeRelativePath(value: string): string {\n return value.split(\"\\\\\").join(\"/\");\n}\n\nfunction getErrorCode(error: unknown): string | undefined {\n if (!error || typeof error !== \"object\") {\n return undefined;\n }\n const code = (error as { code?: unknown }).code;\n return typeof code === \"string\" ? code : undefined;\n}\n\nfunction warnDirectoryReadError(dir: string, error: unknown): void {\n const reason = error instanceof Error ? error.message : String(error);\n process.stderr.write(\n `[openmeld] failed to read directory while hashing skills content (${dir}): ${reason}\\n`\n );\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { mkdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { runtimeLogsDir } from \"../config/paths\";\n\nconst heldLock = new AsyncLocalStorage<boolean>();\nconst pendingLocks = new Map<string, Promise<unknown>>();\nexport function withSkillsInstallLock<T>(run: () => Promise<T>): Promise<T> {\n if (heldLock.getStore()) {\n return run();\n }\n const key = runtimeLogsDir();\n const previous = pendingLocks.get(key) ?? Promise.resolve();\n const current = previous\n .catch(() => undefined)\n .then(() => acquireSkillsInstallLock(() => heldLock.run(true, run)));\n pendingLocks.set(key, current);\n return current.finally(() => {\n if (pendingLocks.get(key) === current) {\n pendingLocks.delete(key);\n }\n });\n}\n\nconst LOCK_FILE_NAME = \"skills-install.lock\";\nconst LOCK_ACQUIRE_MAX_ATTEMPTS = 3;\n\nasync function acquireSkillsInstallLock<T>(run: () => Promise<T>): Promise<T> {\n const logsDir = runtimeLogsDir();\n await mkdir(logsDir, { recursive: true });\n const lockPath = join(logsDir, LOCK_FILE_NAME);\n\n let acquired = false;\n const lockContents = `${JSON.stringify({\n pid: process.pid,\n createdAt: new Date().toISOString(),\n })}\\n`;\n for (let attempt = 0; attempt < LOCK_ACQUIRE_MAX_ATTEMPTS; attempt += 1) {\n try {\n await writeFile(lockPath, lockContents, {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n acquired = true;\n break;\n } catch (error) {\n if (getErrorCode(error) !== \"EEXIST\") {\n throw error;\n }\n\n const recovered = await recoverStaleSkillsInstallLock(lockPath);\n if (!recovered) {\n throw new Error(\n \"another skills installation is already running; retry after it finishes\"\n );\n }\n\n try {\n await writeFile(lockPath, lockContents, {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n acquired = true;\n break;\n } catch (retryError) {\n if (getErrorCode(retryError) !== \"EEXIST\") {\n throw retryError;\n }\n }\n }\n }\n\n if (!acquired) {\n throw new Error(\n \"another skills installation is already running; retry after it finishes\"\n );\n }\n\n try {\n return await run();\n } finally {\n await rm(lockPath, { force: true }).catch(() => undefined);\n }\n}\n\nasync function recoverStaleSkillsInstallLock(\n lockPath: string\n): Promise<boolean> {\n const lockRaw = await readFile(lockPath, \"utf8\").catch((error: unknown) => {\n if (getErrorCode(error) === \"ENOENT\") {\n return \"\";\n }\n throw error;\n });\n if (!lockRaw) {\n return true;\n }\n\n const parsed = parseLockMeta(lockRaw);\n const pid = resolveLockPid(parsed);\n if (!pid) {\n const metadata = await stat(lockPath).catch(() => null);\n if (metadata && Date.now() - metadata.mtimeMs < 30_000) {\n return false;\n }\n }\n if (pid && isPidAlive(pid)) {\n return false;\n }\n\n const latestLockRaw = await readFile(lockPath, \"utf8\").catch(\n (error: unknown) => {\n if (getErrorCode(error) === \"ENOENT\") {\n return \"\";\n }\n throw error;\n }\n );\n if (!latestLockRaw) {\n return true;\n }\n const latestParsed = parseLockMeta(latestLockRaw);\n const latestPid = resolveLockPid(latestParsed);\n if (\n !isSameLockSnapshot({\n beforeRaw: lockRaw,\n beforePid: pid,\n afterRaw: latestLockRaw,\n afterPid: latestPid,\n })\n ) {\n return false;\n }\n\n await rm(lockPath, { force: true }).catch((error: unknown) => {\n if (getErrorCode(error) === \"ENOENT\") {\n return undefined;\n }\n throw error;\n });\n return true;\n}\n\nfunction parseLockMeta(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n}\n\nfunction resolveLockPid(meta: unknown): number | null {\n if (!meta || typeof meta !== \"object\") {\n return null;\n }\n const pid = (meta as Record<string, unknown>).pid;\n return typeof pid === \"number\" && Number.isInteger(pid) && pid > 0\n ? pid\n : null;\n}\n\nfunction isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return getErrorCode(error) !== \"ESRCH\";\n }\n}\n\nfunction getErrorCode(error: unknown): string | undefined {\n if (!error || typeof error !== \"object\") {\n return undefined;\n }\n const code = (error as { code?: unknown }).code;\n return typeof code === \"string\" ? code : undefined;\n}\n\nfunction isSameLockSnapshot(input: {\n beforeRaw: string;\n beforePid: number | null;\n afterRaw: string;\n afterPid: number | null;\n}): boolean {\n if (input.beforeRaw !== input.afterRaw) {\n return false;\n }\n return input.beforePid === input.afterPid;\n}\n","import { randomUUID, verify } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n OFFICIAL_CLI_SKILL_CONTRACT,\n OFFICIAL_CLI_SKILL_MAX_BYTES,\n OFFICIAL_CLI_SKILL_PUBLIC_KEY,\n type OfficialCliSkillPayload,\n type OfficialCliSkillRelease,\n officialCliSkillChannelSchema,\n officialCliSkillPayloadSchema,\n officialCliSkillReleaseSchema,\n} from \"@openmeld/schemas\";\nimport { openMeldRootDir, resolveOpenMeldEnvPreset } from \"../config/paths\";\nimport { compareSemver } from \"../config/version-state\";\nimport { OPENMELD_VERSION } from \"../runtime/version\";\nimport { loadBundledSkillAssets } from \"./bundled-assets\";\nimport { withSkillsInstallLock } from \"./install-lock\";\n\nconst CACHE_FILE = \"official-cli-skill.json\";\n\nexport function verifyOfficialSkillRelease(value: unknown): {\n release: OfficialCliSkillRelease;\n payload: OfficialCliSkillPayload;\n} {\n const envelope = officialCliSkillReleaseSchema.safeParse(value);\n if (\n !(\n envelope.success &&\n verify(\n null,\n Buffer.from(envelope.data.payload),\n OFFICIAL_CLI_SKILL_PUBLIC_KEY,\n Buffer.from(envelope.data.signature, \"base64\")\n )\n )\n ) {\n throw new Error(\"OpenMeld Skill signature is invalid\");\n }\n const payload = officialCliSkillPayloadSchema.safeParse(\n JSON.parse(envelope.data.payload)\n );\n if (!payload.success) {\n throw new Error(\"OpenMeld Skill content is invalid\");\n }\n return { release: envelope.data, payload: payload.data };\n}\n\nfunction isCompatible(\n payload: OfficialCliSkillPayload,\n cliVersion = OPENMELD_VERSION\n): boolean {\n return (\n payload.contractVersion === OFFICIAL_CLI_SKILL_CONTRACT &&\n compareSemver(cliVersion, payload.minimumCliVersion) >= 0\n );\n}\n\nexport function selectOfficialSkillRelease(\n value: unknown,\n cliVersion = OPENMELD_VERSION\n) {\n const channel = officialCliSkillChannelSchema.safeParse(value);\n if (!channel.success) {\n throw new Error(\"OpenMeld Skill channel is invalid\");\n }\n return (\n channel.data.releases\n .map(verifyOfficialSkillRelease)\n .filter(({ payload }) => isCompatible(payload, cliVersion))\n .sort((a, b) => b.payload.revision - a.payload.revision)[0] ?? null\n );\n}\n\nasync function readCachedRelease() {\n const raw = await readFile(join(openMeldRootDir(), CACHE_FILE), \"utf8\").catch(\n (error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n );\n if (!raw) {\n return null;\n }\n try {\n return verifyOfficialSkillRelease(JSON.parse(raw));\n } catch (error) {\n process.stderr.write(\n `[openmeld] cached Skill rejected: ${error instanceof Error ? error.message : String(error)}\\n`\n );\n return null;\n }\n}\n\n// Local-only selection is shared by install, prompt, and component status.\nexport async function loadSelectedSkillAssets() {\n const cached = await readCachedRelease();\n if (!(cached && isCompatible(cached.payload))) {\n return {\n assets: await loadBundledSkillAssets(),\n version: OPENMELD_VERSION,\n };\n }\n return {\n assets: [\n ...cached.payload.files.map((file) => ({\n relativePath: `openmeld-cli/${file.path}`,\n content: Buffer.from(file.content),\n })),\n ].sort((a, b) => a.relativePath.localeCompare(b.relativePath)),\n version: `skill-r${cached.payload.revision}`,\n contentRelease: {\n revision: cached.payload.revision,\n minimumCliVersion: cached.payload.minimumCliVersion,\n },\n };\n}\n\nexport async function readSelectedSkillDocument(path: string): Promise<string> {\n const { assets } = await loadSelectedSkillAssets();\n const asset = assets.find(\n (file) => file.relativePath === `openmeld-cli/${path}`\n );\n if (!asset) {\n throw new Error(`OpenMeld Skill document is missing: ${path}`);\n }\n return asset.content.toString(\"utf8\");\n}\n\nexport function resolveOfficialSkillChannelUrl(): string | null {\n if (resolveOpenMeldEnvPreset() === \"prod\") {\n return \"https://openmeld.ai/skills/openmeld-cli/channel.json\";\n }\n const override = process.env.OPENMELD_CLI_SKILL_CHANNEL_URL;\n if (!(override && process.env.OPENMELD_HOME)) {\n return null;\n }\n const url = new URL(override);\n if (\n url.protocol !== \"http:\" ||\n ![\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname) ||\n url.username ||\n url.password\n ) {\n throw new Error(\"Isolated Skill updates require an explicit localhost URL\");\n }\n return url.href;\n}\n\nexport async function downloadOfficialSkillUpdate(): Promise<\n \"updated\" | \"current\" | \"incompatible\" | \"lane_isolated\"\n> {\n const url = resolveOfficialSkillChannelUrl();\n if (!url) {\n return \"lane_isolated\";\n }\n const response = await fetch(url, {\n signal: AbortSignal.timeout(5000),\n redirect: \"error\",\n });\n if (!(response.ok && response.body)) {\n throw new Error(`OpenMeld Skill download failed (HTTP ${response.status})`);\n }\n const chunks: Uint8Array[] = [];\n let size = 0;\n for await (const chunk of response.body) {\n size += chunk.byteLength;\n if (size > OFFICIAL_CLI_SKILL_MAX_BYTES) {\n throw new Error(\"OpenMeld Skill download exceeds the size limit\");\n }\n chunks.push(chunk);\n }\n const selected = selectOfficialSkillRelease(\n JSON.parse(Buffer.concat(chunks).toString(\"utf8\"))\n );\n if (!selected) {\n return \"incompatible\";\n }\n return withSkillsInstallLock(async () => {\n const cached = await readCachedRelease();\n if (cached && cached.payload.revision >= selected.payload.revision) {\n return \"current\";\n }\n await mkdir(openMeldRootDir(), { recursive: true });\n const cache = join(openMeldRootDir(), CACHE_FILE);\n const staged = `${cache}.${randomUUID()}.tmp`;\n try {\n await writeFile(staged, JSON.stringify(selected.release), {\n flag: \"wx\",\n mode: 0o600,\n });\n await rename(staged, cache);\n } finally {\n await rm(staged, { force: true });\n }\n return \"updated\";\n });\n}\n","import { randomUUID } from \"node:crypto\";\nimport { lstat, readFile, readlink, rename, rm } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\n\n// Callers hold the skills install lock. Recover a process exit between renames.\nexport async function recoverSkillReplacement(target: string): Promise<void> {\n const previous = join(\n dirname(target),\n `.${basename(target)}.openmeld-previous`\n );\n if (!(await exists(previous))) {\n return;\n }\n if (!(await isManagedReplacement(previous, basename(target)))) {\n throw new Error(\"OpenMeld Skill backup conflicts with an unmanaged path\");\n }\n if (await exists(target)) {\n if (!(await isManagedReplacement(target, basename(target)))) {\n throw new Error(\"OpenMeld Skill recovery would affect an unmanaged path\");\n }\n await rm(previous, { recursive: true, force: true });\n } else {\n await rename(previous, target);\n }\n}\n\nexport async function replaceSkillDirectory(\n target: string,\n prepare: (staged: string) => Promise<void>\n): Promise<void> {\n await recoverSkillReplacement(target);\n const staged = join(\n dirname(target),\n `.${basename(target)}.openmeld-staged-${randomUUID()}`\n );\n const previous = join(\n dirname(target),\n `.${basename(target)}.openmeld-previous`\n );\n try {\n await prepare(staged);\n const hadPrevious = await exists(target);\n if (hadPrevious) {\n await rename(target, previous);\n }\n try {\n await rename(staged, target);\n } catch (error) {\n if (hadPrevious) {\n await rename(previous, target);\n }\n throw error;\n }\n // A cleanup failure must not roll back a committed replacement.\n await rm(previous, { recursive: true, force: true }).catch(() => undefined);\n } finally {\n await rm(staged, { recursive: true, force: true }).catch(() => undefined);\n }\n}\n\nasync function isManagedReplacement(\n path: string,\n skillId: string\n): Promise<boolean> {\n const raw = await readFile(join(path, \".openmeld-skill.json\"), \"utf8\").catch(\n () => null\n );\n if (raw) {\n try {\n const marker = JSON.parse(raw);\n return marker.managedBy === \"openmeld\" && marker.skillId === skillId;\n } catch {\n return false;\n }\n }\n // Legacy dangling links have no readable marker and carry no directory data.\n if ((await lstat(path)).isSymbolicLink()) {\n const destination = resolve(dirname(path), await readlink(path));\n return basename(destination) === skillId && !(await exists(destination));\n }\n return false;\n}\n\nfunction exists(path: string): Promise<boolean> {\n return lstat(path).then(\n () => true,\n (error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n );\n}\n","import { lstat, mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport path, { dirname, join, relative } from \"node:path\";\nimport { skillsDir } from \"../config/paths\";\nimport {\n type BundledSkillAsset,\n hashBundledSkillAssets,\n} from \"./bundled-assets\";\nimport { sortBundledSkillAssets } from \"./bundled-assets-fs\";\nimport { computeDirectoryContentHash } from \"./content-hash\";\nimport { withSkillsInstallLock } from \"./install-lock\";\nimport { loadSelectedSkillAssets } from \"./official-release\";\nimport {\n recoverSkillReplacement,\n replaceSkillDirectory,\n} from \"./replace-directory\";\n\nexport const OPENMELD_SKILL_MARKER_FILE = \".openmeld-skill.json\";\n\nexport type OpenMeldSkillMarker = {\n managedBy: \"openmeld\";\n skillId: string;\n mode: \"source\" | \"symlink\" | \"copy\";\n contentHash?: string;\n version?: string;\n updatedAt: string;\n};\n\nexport type LocalSkill = {\n id: string;\n name: string;\n absolutePath: string;\n relativePath: string;\n contentHash?: string;\n version?: string;\n};\n\nconst OPENMELD_CLI_SKILL_FILE = \"SKILL.md\";\nconst SKILL_NAME_REGEX = /^name:\\s*(.+)$/m;\n\nexport function ensureLocalSkills(): Promise<LocalSkill[]> {\n return withSkillsInstallLock(ensureLocalSkillsLocked);\n}\n\nasync function ensureLocalSkillsLocked(): Promise<LocalSkill[]> {\n const storePath = skillsDir();\n await mkdir(storePath, { recursive: true });\n\n const { assets, version: bundledVersion } = await loadSelectedSkillAssets();\n if (assets.length === 0) {\n return listLocalSkills();\n }\n const skillGroups = groupAssetsBySkill(assets);\n\n for (const [skillId, skillAssets] of skillGroups) {\n const targetDir = join(storePath, skillId);\n await recoverSkillReplacement(targetDir);\n const sourceContentHash = hashBundledSkillAssets(skillAssets);\n const existingMarker = await readOpenMeldSkillMarker(targetDir);\n const existing = await lstat(targetDir).catch(\n (error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n );\n if (existing && (!existingMarker || existing.isSymbolicLink())) {\n throw new Error(\n `OpenMeld Skill source conflicts with an unmanaged path: ${targetDir}`\n );\n }\n const isUpToDate =\n existingMarker?.managedBy === \"openmeld\" &&\n existingMarker.skillId === skillId &&\n existingMarker.mode === \"source\" &&\n existingMarker.contentHash === sourceContentHash &&\n existingMarker.version === bundledVersion &&\n (await computeDirectoryContentHash({\n rootDir: targetDir,\n ignoredNames: [OPENMELD_SKILL_MARKER_FILE],\n })) === sourceContentHash;\n if (isUpToDate) {\n continue;\n }\n\n await replaceSkillDirectory(targetDir, async (stagedDir) => {\n for (const asset of skillAssets) {\n const filePath = join(stagedDir, asset.relativePath);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, asset.content);\n }\n await writeOpenMeldSkillMarker({\n skillDir: stagedDir,\n skillId,\n mode: \"source\",\n contentHash: sourceContentHash,\n version: bundledVersion,\n });\n });\n }\n\n return listLocalSkills();\n}\n\n// Group loaded assets by their first path segment (the skill id). Top-level\n// files (e.g. skills/README.md) belong to no skill and are dropped, and a group\n// without a SKILL.md is dropped too — matching the previous \"only install skill\n// directories that contain SKILL.md\" behavior. Each group's paths are made\n// skill-relative and sorted so the per-skill hash matches the source tree.\nfunction groupAssetsBySkill(\n assets: BundledSkillAsset[]\n): Map<string, BundledSkillAsset[]> {\n const groups = new Map<string, BundledSkillAsset[]>();\n for (const asset of assets) {\n const slashIndex = asset.relativePath.indexOf(\"/\");\n if (slashIndex < 0) {\n continue;\n }\n const skillId = asset.relativePath.slice(0, slashIndex);\n const skillRelativePath = asset.relativePath.slice(slashIndex + 1);\n const group = groups.get(skillId) ?? [];\n group.push({ relativePath: skillRelativePath, content: asset.content });\n groups.set(skillId, group);\n }\n for (const [skillId, group] of [...groups.entries()]) {\n if (group.some((asset) => asset.relativePath === OPENMELD_CLI_SKILL_FILE)) {\n groups.set(skillId, sortBundledSkillAssets(group));\n } else {\n groups.delete(skillId);\n }\n }\n return groups;\n}\n\nexport async function listLocalSkills(): Promise<LocalSkill[]> {\n const storePath = skillsDir();\n const skillDirs = await discoverSkillDirs(storePath, 0, 6);\n const skills: LocalSkill[] = [];\n\n for (const skillDir of skillDirs) {\n const skillFile = join(skillDir, \"SKILL.md\");\n const raw = await readFile(skillFile, \"utf8\").catch(() => \"\");\n if (!raw) {\n continue;\n }\n const skillId = path.basename(skillDir);\n const skillName = readSkillName(raw) ?? skillId;\n const marker = await readOpenMeldSkillMarker(skillDir);\n skills.push({\n id: skillId,\n name: skillName,\n absolutePath: skillDir,\n relativePath: relative(storePath, skillDir) || skillId,\n ...(marker?.contentHash ? { contentHash: marker.contentHash } : {}),\n ...(marker?.version ? { version: marker.version } : {}),\n });\n }\n\n skills.sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n return skills;\n}\n\nexport async function writeOpenMeldSkillMarker(input: {\n skillDir: string;\n skillId: string;\n mode: \"source\" | \"symlink\" | \"copy\";\n contentHash?: string;\n version?: string;\n}): Promise<void> {\n const markerPath = join(input.skillDir, OPENMELD_SKILL_MARKER_FILE);\n const marker: OpenMeldSkillMarker = {\n managedBy: \"openmeld\",\n skillId: input.skillId,\n mode: input.mode,\n ...(input.contentHash ? { contentHash: input.contentHash } : {}),\n ...(input.version ? { version: input.version } : {}),\n updatedAt: new Date().toISOString(),\n };\n await writeFile(markerPath, `${JSON.stringify(marker, null, 2)}\\n`, \"utf8\");\n}\n\nexport async function isOpenMeldManagedSkillDir(\n skillDir: string\n): Promise<boolean> {\n const marker = await readOpenMeldSkillMarker(skillDir);\n return marker?.managedBy === \"openmeld\";\n}\n\nexport async function readOpenMeldSkillMarker(\n skillDir: string\n): Promise<OpenMeldSkillMarker | null> {\n const markerPath = join(skillDir, OPENMELD_SKILL_MARKER_FILE);\n const raw = await readFile(markerPath, \"utf8\").catch(() => null);\n if (!raw) {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as Partial<OpenMeldSkillMarker>;\n if (parsed.managedBy !== \"openmeld\") {\n return null;\n }\n if (\n typeof parsed.skillId !== \"string\" ||\n parsed.skillId.trim().length === 0\n ) {\n return null;\n }\n if (\n parsed.mode !== \"source\" &&\n parsed.mode !== \"symlink\" &&\n parsed.mode !== \"copy\"\n ) {\n return null;\n }\n return {\n managedBy: \"openmeld\",\n skillId: parsed.skillId.trim(),\n mode: parsed.mode,\n ...(typeof parsed.contentHash === \"string\" &&\n parsed.contentHash.trim().length > 0\n ? { contentHash: parsed.contentHash.trim() }\n : {}),\n ...(typeof parsed.version === \"string\" && parsed.version.trim().length > 0\n ? { version: parsed.version.trim() }\n : {}),\n updatedAt:\n typeof parsed.updatedAt === \"string\" &&\n parsed.updatedAt.trim().length > 0\n ? parsed.updatedAt\n : new Date().toISOString(),\n };\n } catch {\n return null;\n }\n}\n\nasync function discoverSkillDirs(\n dir: string,\n depth: number,\n maxDepth: number\n): Promise<string[]> {\n if (depth > maxDepth) {\n return [];\n }\n\n const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);\n if (entries.length === 0) {\n return [];\n }\n\n const hasSkill = entries.some(\n (entry) => entry.isFile() && entry.name === \"SKILL.md\"\n );\n if (hasSkill) {\n return [dir];\n }\n\n const nested = await Promise.all(\n entries\n .filter(\n (entry) => entry.isDirectory() && !entry.name.includes(\".openmeld-\")\n )\n .map((entry) =>\n discoverSkillDirs(join(dir, entry.name), depth + 1, maxDepth)\n )\n );\n\n return nested.flat();\n}\n\nfunction readSkillName(rawSkillFile: string): string | undefined {\n const match = rawSkillFile.match(SKILL_NAME_REGEX);\n if (!match) {\n return undefined;\n }\n const candidate = match[1]?.trim();\n return candidate && candidate.length > 0 ? candidate : undefined;\n}\n","import { lstat, readlink } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { computeDirectoryContentHash } from \"./content-hash\";\nimport type { SkillsInstallTarget } from \"./installer\";\nimport {\n type LocalSkill,\n type OpenMeldSkillMarker,\n readOpenMeldSkillMarker,\n} from \"./store\";\n\nexport type SkillInstallState =\n | \"missing\"\n | \"outdated\"\n | \"up_to_date\"\n | \"external_conflict\";\n\nexport type SkillInstallStateResult = {\n targetId: string;\n targetDir: string;\n targetType: \"agent\" | \"custom\";\n skillId: string;\n skillDir: string;\n state: SkillInstallState;\n targetMode?: OpenMeldSkillMarker[\"mode\"];\n sourceHash?: string;\n targetHash?: string;\n sourceVersion?: string;\n targetVersion?: string;\n reason?: string;\n};\n\ntype SourceSnapshot = {\n hash?: string;\n version?: string;\n};\n\ntype TargetSnapshot =\n | {\n exists: false;\n }\n | {\n exists: true;\n isSymlink: boolean;\n marker: OpenMeldSkillMarker | null;\n symlinkTargetPath: string;\n destinationExists: boolean;\n };\n\nexport async function resolveSkillsInstallStates(input: {\n skills: LocalSkill[];\n targets: SkillsInstallTarget[];\n}): Promise<SkillInstallStateResult[]> {\n const states: SkillInstallStateResult[] = [];\n for (const target of input.targets) {\n for (const skill of input.skills) {\n states.push(\n await resolveSkillInstallStateForTarget({\n skill,\n target,\n })\n );\n }\n }\n return states;\n}\n\nexport async function resolveSkillInstallStateForTarget(input: {\n skill: LocalSkill;\n target: SkillsInstallTarget;\n}): Promise<SkillInstallStateResult> {\n const base = createBaseResult(input);\n const source = await resolveSourceSnapshot(input.skill);\n const target = await resolveTargetSnapshot(base.skillDir);\n\n if (!target.exists) {\n return createStateResult({\n base,\n source,\n state: \"missing\",\n });\n }\n\n if (target.marker?.managedBy !== \"openmeld\") {\n if (\n isLegacyOpenMeldSkillSymlink({\n skillId: input.skill.id,\n target,\n })\n ) {\n return createStateResult({\n base,\n source,\n state: \"outdated\",\n targetMode: \"symlink\",\n reason: \"legacy OpenMeld skill link found; update required\",\n });\n }\n\n return createStateResult({\n base,\n source,\n state: \"external_conflict\",\n reason:\n \"existing non-OpenMeld skill detected; skipped to avoid overwrite\",\n });\n }\n\n if (!target.isSymlink && target.marker.contentHash) {\n const entry = await lstat(join(base.skillDir, \"SKILL.md\")).catch(\n () => null\n );\n if (!entry?.isFile()) {\n return createStateResult({\n base,\n source,\n state: \"outdated\",\n targetMarker: target.marker,\n reason: \"OpenMeld Skill entry is missing\",\n });\n }\n const actualHash = await computeDirectoryContentHash({\n rootDir: base.skillDir,\n ignoredNames: [\".openmeld-skill.json\"],\n });\n if (actualHash !== target.marker.contentHash) {\n return createStateResult({\n base,\n source,\n state: \"external_conflict\",\n targetMarker: target.marker,\n reason: \"OpenMeld Skill files were modified locally; kept your changes\",\n });\n }\n }\n\n const upToDate = isUpToDate({\n source,\n targetMarker: target.marker,\n isSymlink: target.isSymlink,\n symlinkTargetPath: target.symlinkTargetPath,\n sourceSkillDir: input.skill.absolutePath,\n });\n if (upToDate) {\n return createStateResult({\n base,\n source,\n targetMarker: target.marker,\n state: \"up_to_date\",\n reason: \"already up-to-date\",\n });\n }\n\n return createStateResult({\n base,\n source,\n targetMarker: target.marker,\n state: \"outdated\",\n reason: target.isSymlink\n ? \"OpenMeld skill link points to a different OpenMeld skills store; update required\"\n : \"OpenMeld skill content changed; update required\",\n });\n}\n\nfunction createBaseResult(input: {\n skill: LocalSkill;\n target: SkillsInstallTarget;\n}): Omit<SkillInstallStateResult, \"state\"> {\n const skillDir = join(input.target.dir, input.skill.id);\n return {\n targetId: input.target.id,\n targetDir: input.target.dir,\n targetType: input.target.type,\n skillId: input.skill.id,\n skillDir,\n };\n}\n\nasync function resolveSourceSnapshot(\n skill: LocalSkill\n): Promise<SourceSnapshot> {\n const sourceMarker = await readOpenMeldSkillMarker(skill.absolutePath);\n return {\n ...((skill.contentHash ?? sourceMarker?.contentHash)\n ? { hash: skill.contentHash ?? sourceMarker?.contentHash }\n : {}),\n ...((skill.version ?? sourceMarker?.version)\n ? { version: skill.version ?? sourceMarker?.version }\n : {}),\n };\n}\n\nasync function resolveTargetSnapshot(\n skillDir: string\n): Promise<TargetSnapshot> {\n const stats = await lstat(skillDir).catch(() => null);\n if (!stats) {\n return { exists: false };\n }\n\n let marker = await readOpenMeldSkillMarker(skillDir);\n let symlinkTargetPath = \"\";\n if (stats.isSymbolicLink()) {\n symlinkTargetPath = await resolveSymlinkTarget(skillDir).catch(() => \"\");\n if (!marker && symlinkTargetPath) {\n marker = await readOpenMeldSkillMarker(symlinkTargetPath);\n }\n }\n\n return {\n exists: true,\n isSymlink: stats.isSymbolicLink(),\n marker,\n symlinkTargetPath,\n destinationExists: symlinkTargetPath\n ? Boolean(await lstat(symlinkTargetPath).catch(() => null))\n : true,\n };\n}\n\nfunction isLegacyOpenMeldSkillSymlink(input: {\n skillId: string;\n target: Extract<TargetSnapshot, { exists: true }>;\n}): boolean {\n if (\n !(input.target.isSymlink && input.target.symlinkTargetPath) ||\n input.target.destinationExists\n ) {\n return false;\n }\n\n return basename(input.target.symlinkTargetPath) === input.skillId;\n}\n\nfunction isUpToDate(input: {\n source: SourceSnapshot;\n targetMarker: OpenMeldSkillMarker;\n isSymlink: boolean;\n symlinkTargetPath: string;\n sourceSkillDir: string;\n}): boolean {\n if (input.isSymlink) {\n // A symlinked target mirrors whatever store it points at, and its marker is\n // read through the link, so a matching hash/version only proves that other\n // store's state. The link is current only when it resolves to this store's\n // skill directory; anything else must be reinstalled before the foreign\n // store drifts or disappears.\n return (\n input.symlinkTargetPath.length > 0 &&\n pathsEqual(input.symlinkTargetPath, input.sourceSkillDir)\n );\n }\n return hasMatchingHashAndVersion(input.source, input.targetMarker);\n}\n\nfunction hasMatchingHashAndVersion(\n source: SourceSnapshot,\n targetMarker: OpenMeldSkillMarker\n): boolean {\n if (\n !(\n source.hash &&\n targetMarker.contentHash &&\n source.hash === targetMarker.contentHash\n )\n ) {\n return false;\n }\n return (\n !(source.version && targetMarker.version) ||\n source.version === targetMarker.version\n );\n}\n\nfunction createStateResult(input: {\n base: Omit<SkillInstallStateResult, \"state\">;\n source: SourceSnapshot;\n state: SkillInstallState;\n targetMode?: OpenMeldSkillMarker[\"mode\"];\n targetMarker?: OpenMeldSkillMarker;\n reason?: string;\n}): SkillInstallStateResult {\n return {\n ...input.base,\n state: input.state,\n ...(input.source.hash ? { sourceHash: input.source.hash } : {}),\n ...(input.source.version ? { sourceVersion: input.source.version } : {}),\n ...(input.targetMarker?.contentHash\n ? { targetHash: input.targetMarker.contentHash }\n : {}),\n ...(input.targetMarker?.mode\n ? { targetMode: input.targetMarker.mode }\n : {}),\n ...(input.targetMode ? { targetMode: input.targetMode } : {}),\n ...(input.targetMarker?.version\n ? { targetVersion: input.targetMarker.version }\n : {}),\n ...(input.reason ? { reason: input.reason } : {}),\n };\n}\n\nasync function resolveSymlinkTarget(linkPath: string): Promise<string> {\n const target = await readlink(linkPath);\n return resolve(dirname(linkPath), target);\n}\n\nfunction pathsEqual(left: string, right: string): boolean {\n return resolve(left) === resolve(right);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"state-GxF_KAM1.js","names":["getErrorCode"],"sources":["../../../packages/schemas/dist/official-cli-skill.js","../src/skills/bundled.ts","../src/skills/bundled-assets-fs.ts","../src/skills/bundled-assets.ts","../src/skills/content-hash.ts","../src/skills/install-lock.ts","../src/skills/official-release.ts","../src/skills/replace-directory.ts","../src/skills/store.ts","../src/skills/state.ts"],"sourcesContent":["import * as z$1 from \"zod/v4\";\n//#region src/official-cli-skill.ts\nconst OFFICIAL_CLI_SKILL_CONTRACT = \"openmeld-skills-contract-2026-09-explicit-space-recipients-v1\";\nconst OFFICIAL_CLI_SKILL_URL = \"https://openmeld.ai/skills/openmeld-cli/SKILL.md\";\nconst OFFICIAL_CLI_SKILL_MAX_BYTES = 1048576;\nconst OFFICIAL_CLI_SKILL_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAFZjFHrQ/QLsJQpHkAbKBRG57fEazhm7zc0dMa54ilWQ=\n-----END PUBLIC KEY-----\n`;\nconst officialCliSkillPayloadSchema = z$1.object({\n\tschemaVersion: z$1.literal(1),\n\trevision: z$1.number().int().positive(),\n\tminimumCliVersion: z$1.string().regex(/^\\d+\\.\\d+\\.\\d+$/),\n\tcontractVersion: z$1.string().min(1).max(128),\n\tfiles: z$1.array(z$1.object({\n\t\tpath: z$1.string().regex(/^(?:SKILL\\.md|(?:playbooks|references)\\/[a-z0-9-]+\\.md)$/),\n\t\tcontent: z$1.string().min(1).max(131072)\n\t}).strict()).min(1).max(32)\n}).strict().superRefine((value, context) => {\n\tconst paths = value.files.map((file) => file.path);\n\tif (!paths.includes(\"SKILL.md\") || new Set(paths).size !== paths.length) context.addIssue({\n\t\tcode: \"custom\",\n\t\tmessage: \"Skill entry is required and paths must be unique\"\n\t});\n});\nconst officialCliSkillReleaseSchema = z$1.object({\n\tpayload: z$1.string().min(1).max(524288),\n\tsignature: z$1.string().regex(/^[A-Za-z0-9+/]{86}==$/)\n}).strict();\nconst officialCliSkillChannelSchema = z$1.object({\n\tschemaVersion: z$1.literal(1),\n\treleases: z$1.array(officialCliSkillReleaseSchema).min(1).max(16)\n}).strict();\n//#endregion\nexport { OFFICIAL_CLI_SKILL_CONTRACT, OFFICIAL_CLI_SKILL_MAX_BYTES, OFFICIAL_CLI_SKILL_PUBLIC_KEY, OFFICIAL_CLI_SKILL_URL, officialCliSkillChannelSchema, officialCliSkillPayloadSchema, officialCliSkillReleaseSchema };\n\n//# sourceMappingURL=official-cli-skill.js.map","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst CLI_PACKAGE_JSON = \"package.json\";\n\nexport type BundledSkillsLocation = {\n cliRootDir: string;\n skillsRootDir: string;\n};\n\n/**\n * Locate the on-disk bundled skills directory for the npm distribution by\n * walking up from this module to the CLI package root (a directory that has\n * both package.json and skills/). Returns null under the binary distribution,\n * where import.meta.url is a virtual path and the skills are embedded instead —\n * callers in that mode go through bundled-assets.ts, not this function.\n */\nexport function resolveBundledSkillsLocation(): BundledSkillsLocation | null {\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const cliRootDir = resolveCliRootDir(moduleDir);\n if (!cliRootDir) {\n return null;\n }\n return {\n cliRootDir,\n skillsRootDir: path.join(cliRootDir, \"skills\"),\n };\n}\n\nfunction resolveCliRootDir(fromDir: string): string | null {\n let current = fromDir;\n for (;;) {\n const packageJsonPath = path.join(current, CLI_PACKAGE_JSON);\n const hasPackageJson = existsSync(packageJsonPath);\n const hasSkillsDir = existsSync(path.join(current, \"skills\"));\n if (hasPackageJson && hasSkillsDir) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { resolveBundledSkillsLocation } from \"./bundled\";\nimport type { BundledSkillAsset } from \"./bundled-assets\";\n\n/**\n * npm-distribution source: read the bundled skills from the on-disk `skills/`\n * directory next to the CLI package. Assets are sorted by relative path so the\n * order (and therefore any content hash computed from them) is stable and\n * matches the embedded distribution.\n */\nexport async function loadFsBundledSkillAssets(): Promise<BundledSkillAsset[]> {\n const location = resolveBundledSkillsLocation();\n if (!location) {\n throw new Error(\"unable to resolve bundled OpenMeld skills directory\");\n }\n const assets = await collectSkillAssets(\n location.skillsRootDir,\n location.skillsRootDir\n );\n return sortBundledSkillAssets(assets);\n}\n\nexport function sortBundledSkillAssets(\n assets: BundledSkillAsset[]\n): BundledSkillAsset[] {\n return [...assets].sort((left, right) =>\n left.relativePath.localeCompare(right.relativePath)\n );\n}\n\nasync function collectSkillAssets(\n dir: string,\n rootDir: string\n): Promise<BundledSkillAsset[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const assets: BundledSkillAsset[] = [];\n for (const entry of entries) {\n const absolutePath = join(dir, entry.name);\n if (entry.isDirectory()) {\n assets.push(...(await collectSkillAssets(absolutePath, rootDir)));\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n assets.push({\n relativePath: toPosixRelativePath(relative(rootDir, absolutePath)),\n content: await readFile(absolutePath),\n });\n }\n return assets;\n}\n\nfunction toPosixRelativePath(value: string): string {\n return value.split(\"\\\\\").join(\"/\");\n}\n","import { createHash } from \"node:crypto\";\nimport { isBinaryDistribution } from \"../runtime/distribution\";\nimport { loadFsBundledSkillAssets } from \"./bundled-assets-fs\";\n\n/**\n * One bundled skill file, addressed by its POSIX path relative to the skills/\n * root (e.g. \"README.md\", \"openmeld-cli/SKILL.md\"). This is the single shape\n * both distribution forms produce, so downstream skill install and bundle-hash\n * logic never branches on how the files were sourced.\n */\nexport type BundledSkillAsset = {\n relativePath: string;\n content: Buffer;\n};\n\n/**\n * Load the OpenMeld-managed skill files that ship with this CLI build.\n *\n * - npm distribution: read from the on-disk `skills/` directory.\n * - binary distribution: read from files embedded into the single binary at\n * compile time. The embedded module is a Bun-only island resolved only by\n * `bun build --compile`; the npm build never reaches this branch and marks\n * the module external, so its `with { type: \"file\" }` imports are never\n * parsed by tsdown.\n */\nexport async function loadBundledSkillAssets(): Promise<BundledSkillAsset[]> {\n if (isBinaryDistribution()) {\n const embedded = await import(\"./bundled-assets-embedded\");\n return embedded.loadEmbeddedBundledSkillAssets();\n }\n return loadFsBundledSkillAssets();\n}\n\n/**\n * Content hash over an ordered list of skill assets. Byte-for-byte compatible\n * with `computeDirectoryContentHash` (same `file:<relativePath>\\n<content>\\n`\n * framing) so the embedded and on-disk sources produce identical hashes as long\n * as `assets` is sorted by relative path (as `loadBundledSkillAssets` returns\n * it). This is the single skills-hash algorithm for both distribution forms.\n */\nexport function hashBundledSkillAssets(assets: BundledSkillAsset[]): string {\n const hash = createHash(\"sha256\");\n for (const asset of assets) {\n hash.update(`file:${asset.relativePath}\\n`);\n hash.update(asset.content);\n hash.update(\"\\n\");\n }\n return hash.digest(\"hex\");\n}\n\nconst OPENMELD_CLI_SKILL_ID = \"openmeld-cli\";\nconst OPENMELD_CLI_SKILL_FILE = \"SKILL.md\";\n\n/**\n * Read one OpenMeld CLI skill document by its path relative to the skill root\n * (e.g. \"SKILL.md\", \"references/commands.md\"). Works in both distribution forms\n * via loadBundledSkillAssets, so `openmeld prompt --raw` renders the bundled\n * markdown from the embedded binary too.\n */\nexport async function readBundledOpenMeldCliSkillDocumentByPath(\n skillRelativePath: string\n): Promise<string> {\n const targetPath = `${OPENMELD_CLI_SKILL_ID}/${skillRelativePath}`;\n const assets = await loadBundledSkillAssets();\n const asset = assets.find((item) => item.relativePath === targetPath);\n if (!asset) {\n throw new Error(\n `bundled OpenMeld CLI skill document is missing: ${skillRelativePath}`\n );\n }\n return asset.content.toString(\"utf8\");\n}\n\nexport function readBundledOpenMeldCliSkillDocument(): Promise<string> {\n return readBundledOpenMeldCliSkillDocumentByPath(OPENMELD_CLI_SKILL_FILE);\n}\n","import { createHash } from \"node:crypto\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\n\nexport async function computeDirectoryContentHash(input: {\n rootDir: string;\n ignoredNames?: string[];\n}): Promise<string> {\n const ignoredNames = new Set(input.ignoredNames ?? []);\n const files = await collectFiles({\n dir: input.rootDir,\n rootDir: input.rootDir,\n ignoredNames,\n });\n const hash = createHash(\"sha256\");\n for (const file of files) {\n hash.update(`file:${file.relativePath}\\n`);\n hash.update(file.content);\n hash.update(\"\\n\");\n }\n return hash.digest(\"hex\");\n}\n\nasync function collectFiles(input: {\n dir: string;\n rootDir: string;\n ignoredNames: Set<string>;\n}): Promise<Array<{ relativePath: string; content: Buffer }>> {\n const entries = await readdir(input.dir, { withFileTypes: true }).catch(\n (error: unknown) => {\n if (getErrorCode(error) === \"ENOENT\") {\n return [];\n }\n warnDirectoryReadError(input.dir, error);\n throw error;\n }\n );\n entries.sort((a, b) => a.name.localeCompare(b.name));\n\n const files: Array<{ relativePath: string; content: Buffer }> = [];\n for (const entry of entries) {\n if (input.ignoredNames.has(entry.name)) {\n continue;\n }\n const absolutePath = join(input.dir, entry.name);\n if (entry.isDirectory()) {\n files.push(\n ...(await collectFiles({\n dir: absolutePath,\n rootDir: input.rootDir,\n ignoredNames: input.ignoredNames,\n }))\n );\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n const content = await readFile(absolutePath);\n files.push({\n relativePath: normalizeRelativePath(\n relative(input.rootDir, absolutePath)\n ),\n content,\n });\n }\n return files;\n}\n\nfunction normalizeRelativePath(value: string): string {\n return value.split(\"\\\\\").join(\"/\");\n}\n\nfunction getErrorCode(error: unknown): string | undefined {\n if (!error || typeof error !== \"object\") {\n return undefined;\n }\n const code = (error as { code?: unknown }).code;\n return typeof code === \"string\" ? code : undefined;\n}\n\nfunction warnDirectoryReadError(dir: string, error: unknown): void {\n const reason = error instanceof Error ? error.message : String(error);\n process.stderr.write(\n `[openmeld] failed to read directory while hashing skills content (${dir}): ${reason}\\n`\n );\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { mkdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { runtimeLogsDir } from \"../config/paths\";\n\nconst heldLock = new AsyncLocalStorage<boolean>();\nconst pendingLocks = new Map<string, Promise<unknown>>();\nexport function withSkillsInstallLock<T>(run: () => Promise<T>): Promise<T> {\n if (heldLock.getStore()) {\n return run();\n }\n const key = runtimeLogsDir();\n const previous = pendingLocks.get(key) ?? Promise.resolve();\n const current = previous\n .catch(() => undefined)\n .then(() => acquireSkillsInstallLock(() => heldLock.run(true, run)));\n pendingLocks.set(key, current);\n return current.finally(() => {\n if (pendingLocks.get(key) === current) {\n pendingLocks.delete(key);\n }\n });\n}\n\nconst LOCK_FILE_NAME = \"skills-install.lock\";\nconst LOCK_ACQUIRE_MAX_ATTEMPTS = 3;\n\nasync function acquireSkillsInstallLock<T>(run: () => Promise<T>): Promise<T> {\n const logsDir = runtimeLogsDir();\n await mkdir(logsDir, { recursive: true });\n const lockPath = join(logsDir, LOCK_FILE_NAME);\n\n let acquired = false;\n const lockContents = `${JSON.stringify({\n pid: process.pid,\n createdAt: new Date().toISOString(),\n })}\\n`;\n for (let attempt = 0; attempt < LOCK_ACQUIRE_MAX_ATTEMPTS; attempt += 1) {\n try {\n await writeFile(lockPath, lockContents, {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n acquired = true;\n break;\n } catch (error) {\n if (getErrorCode(error) !== \"EEXIST\") {\n throw error;\n }\n\n const recovered = await recoverStaleSkillsInstallLock(lockPath);\n if (!recovered) {\n throw new Error(\n \"another skills installation is already running; retry after it finishes\"\n );\n }\n\n try {\n await writeFile(lockPath, lockContents, {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n acquired = true;\n break;\n } catch (retryError) {\n if (getErrorCode(retryError) !== \"EEXIST\") {\n throw retryError;\n }\n }\n }\n }\n\n if (!acquired) {\n throw new Error(\n \"another skills installation is already running; retry after it finishes\"\n );\n }\n\n try {\n return await run();\n } finally {\n await rm(lockPath, { force: true }).catch(() => undefined);\n }\n}\n\nasync function recoverStaleSkillsInstallLock(\n lockPath: string\n): Promise<boolean> {\n const lockRaw = await readFile(lockPath, \"utf8\").catch((error: unknown) => {\n if (getErrorCode(error) === \"ENOENT\") {\n return \"\";\n }\n throw error;\n });\n if (!lockRaw) {\n return true;\n }\n\n const parsed = parseLockMeta(lockRaw);\n const pid = resolveLockPid(parsed);\n if (!pid) {\n const metadata = await stat(lockPath).catch(() => null);\n if (metadata && Date.now() - metadata.mtimeMs < 30_000) {\n return false;\n }\n }\n if (pid && isPidAlive(pid)) {\n return false;\n }\n\n const latestLockRaw = await readFile(lockPath, \"utf8\").catch(\n (error: unknown) => {\n if (getErrorCode(error) === \"ENOENT\") {\n return \"\";\n }\n throw error;\n }\n );\n if (!latestLockRaw) {\n return true;\n }\n const latestParsed = parseLockMeta(latestLockRaw);\n const latestPid = resolveLockPid(latestParsed);\n if (\n !isSameLockSnapshot({\n beforeRaw: lockRaw,\n beforePid: pid,\n afterRaw: latestLockRaw,\n afterPid: latestPid,\n })\n ) {\n return false;\n }\n\n await rm(lockPath, { force: true }).catch((error: unknown) => {\n if (getErrorCode(error) === \"ENOENT\") {\n return undefined;\n }\n throw error;\n });\n return true;\n}\n\nfunction parseLockMeta(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n}\n\nfunction resolveLockPid(meta: unknown): number | null {\n if (!meta || typeof meta !== \"object\") {\n return null;\n }\n const pid = (meta as Record<string, unknown>).pid;\n return typeof pid === \"number\" && Number.isInteger(pid) && pid > 0\n ? pid\n : null;\n}\n\nfunction isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return getErrorCode(error) !== \"ESRCH\";\n }\n}\n\nfunction getErrorCode(error: unknown): string | undefined {\n if (!error || typeof error !== \"object\") {\n return undefined;\n }\n const code = (error as { code?: unknown }).code;\n return typeof code === \"string\" ? code : undefined;\n}\n\nfunction isSameLockSnapshot(input: {\n beforeRaw: string;\n beforePid: number | null;\n afterRaw: string;\n afterPid: number | null;\n}): boolean {\n if (input.beforeRaw !== input.afterRaw) {\n return false;\n }\n return input.beforePid === input.afterPid;\n}\n","import { randomUUID, verify } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n OFFICIAL_CLI_SKILL_CONTRACT,\n OFFICIAL_CLI_SKILL_MAX_BYTES,\n OFFICIAL_CLI_SKILL_PUBLIC_KEY,\n type OfficialCliSkillPayload,\n type OfficialCliSkillRelease,\n officialCliSkillChannelSchema,\n officialCliSkillPayloadSchema,\n officialCliSkillReleaseSchema,\n} from \"@openmeld/schemas\";\nimport { openMeldRootDir, resolveOpenMeldEnvPreset } from \"../config/paths\";\nimport { compareSemver } from \"../config/version-state\";\nimport { OPENMELD_VERSION } from \"../runtime/version\";\nimport { loadBundledSkillAssets } from \"./bundled-assets\";\nimport { withSkillsInstallLock } from \"./install-lock\";\n\nconst CACHE_FILE = \"official-cli-skill.json\";\n\nexport function verifyOfficialSkillRelease(value: unknown): {\n release: OfficialCliSkillRelease;\n payload: OfficialCliSkillPayload;\n} {\n const envelope = officialCliSkillReleaseSchema.safeParse(value);\n if (\n !(\n envelope.success &&\n verify(\n null,\n Buffer.from(envelope.data.payload),\n OFFICIAL_CLI_SKILL_PUBLIC_KEY,\n Buffer.from(envelope.data.signature, \"base64\")\n )\n )\n ) {\n throw new Error(\"OpenMeld Skill signature is invalid\");\n }\n const payload = officialCliSkillPayloadSchema.safeParse(\n JSON.parse(envelope.data.payload)\n );\n if (!payload.success) {\n throw new Error(\"OpenMeld Skill content is invalid\");\n }\n return { release: envelope.data, payload: payload.data };\n}\n\nfunction isCompatible(\n payload: OfficialCliSkillPayload,\n cliVersion = OPENMELD_VERSION\n): boolean {\n return (\n payload.contractVersion === OFFICIAL_CLI_SKILL_CONTRACT &&\n compareSemver(cliVersion, payload.minimumCliVersion) >= 0\n );\n}\n\nexport function selectOfficialSkillRelease(\n value: unknown,\n cliVersion = OPENMELD_VERSION\n) {\n const channel = officialCliSkillChannelSchema.safeParse(value);\n if (!channel.success) {\n throw new Error(\"OpenMeld Skill channel is invalid\");\n }\n return (\n channel.data.releases\n .map(verifyOfficialSkillRelease)\n .filter(({ payload }) => isCompatible(payload, cliVersion))\n .sort((a, b) => b.payload.revision - a.payload.revision)[0] ?? null\n );\n}\n\nasync function readCachedRelease() {\n const raw = await readFile(join(openMeldRootDir(), CACHE_FILE), \"utf8\").catch(\n (error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n );\n if (!raw) {\n return null;\n }\n try {\n return verifyOfficialSkillRelease(JSON.parse(raw));\n } catch (error) {\n process.stderr.write(\n `[openmeld] cached Skill rejected: ${error instanceof Error ? error.message : String(error)}\\n`\n );\n return null;\n }\n}\n\n// Local-only selection is shared by install, prompt, and component status.\nexport async function loadSelectedSkillAssets() {\n const cached = await readCachedRelease();\n if (!(cached && isCompatible(cached.payload))) {\n return {\n assets: await loadBundledSkillAssets(),\n version: OPENMELD_VERSION,\n };\n }\n return {\n assets: [\n ...cached.payload.files.map((file) => ({\n relativePath: `openmeld-cli/${file.path}`,\n content: Buffer.from(file.content),\n })),\n ].sort((a, b) => a.relativePath.localeCompare(b.relativePath)),\n version: `skill-r${cached.payload.revision}`,\n contentRelease: {\n revision: cached.payload.revision,\n minimumCliVersion: cached.payload.minimumCliVersion,\n },\n };\n}\n\nexport async function readSelectedSkillDocument(path: string): Promise<string> {\n const { assets } = await loadSelectedSkillAssets();\n const asset = assets.find(\n (file) => file.relativePath === `openmeld-cli/${path}`\n );\n if (!asset) {\n throw new Error(`OpenMeld Skill document is missing: ${path}`);\n }\n return asset.content.toString(\"utf8\");\n}\n\nexport function resolveOfficialSkillChannelUrl(): string | null {\n if (resolveOpenMeldEnvPreset() === \"prod\") {\n return \"https://openmeld.ai/skills/openmeld-cli/channel.json\";\n }\n const override = process.env.OPENMELD_CLI_SKILL_CHANNEL_URL;\n if (!(override && process.env.OPENMELD_HOME)) {\n return null;\n }\n const url = new URL(override);\n if (\n url.protocol !== \"http:\" ||\n ![\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname) ||\n url.username ||\n url.password\n ) {\n throw new Error(\"Isolated Skill updates require an explicit localhost URL\");\n }\n return url.href;\n}\n\nexport async function downloadOfficialSkillUpdate(): Promise<\n \"updated\" | \"current\" | \"incompatible\" | \"lane_isolated\"\n> {\n const url = resolveOfficialSkillChannelUrl();\n if (!url) {\n return \"lane_isolated\";\n }\n const response = await fetch(url, {\n signal: AbortSignal.timeout(5000),\n redirect: \"error\",\n });\n if (!(response.ok && response.body)) {\n throw new Error(`OpenMeld Skill download failed (HTTP ${response.status})`);\n }\n const chunks: Uint8Array[] = [];\n let size = 0;\n for await (const chunk of response.body) {\n size += chunk.byteLength;\n if (size > OFFICIAL_CLI_SKILL_MAX_BYTES) {\n throw new Error(\"OpenMeld Skill download exceeds the size limit\");\n }\n chunks.push(chunk);\n }\n const selected = selectOfficialSkillRelease(\n JSON.parse(Buffer.concat(chunks).toString(\"utf8\"))\n );\n if (!selected) {\n return \"incompatible\";\n }\n return withSkillsInstallLock(async () => {\n const cached = await readCachedRelease();\n if (cached && cached.payload.revision >= selected.payload.revision) {\n return \"current\";\n }\n await mkdir(openMeldRootDir(), { recursive: true });\n const cache = join(openMeldRootDir(), CACHE_FILE);\n const staged = `${cache}.${randomUUID()}.tmp`;\n try {\n await writeFile(staged, JSON.stringify(selected.release), {\n flag: \"wx\",\n mode: 0o600,\n });\n await rename(staged, cache);\n } finally {\n await rm(staged, { force: true });\n }\n return \"updated\";\n });\n}\n","import { randomUUID } from \"node:crypto\";\nimport { lstat, readFile, readlink, rename, rm } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\n\n// Callers hold the skills install lock. Recover a process exit between renames.\nexport async function recoverSkillReplacement(target: string): Promise<void> {\n const previous = join(\n dirname(target),\n `.${basename(target)}.openmeld-previous`\n );\n if (!(await exists(previous))) {\n return;\n }\n if (!(await isManagedReplacement(previous, basename(target)))) {\n throw new Error(\"OpenMeld Skill backup conflicts with an unmanaged path\");\n }\n if (await exists(target)) {\n if (!(await isManagedReplacement(target, basename(target)))) {\n throw new Error(\"OpenMeld Skill recovery would affect an unmanaged path\");\n }\n await rm(previous, { recursive: true, force: true });\n } else {\n await rename(previous, target);\n }\n}\n\nexport async function replaceSkillDirectory(\n target: string,\n prepare: (staged: string) => Promise<void>\n): Promise<void> {\n await recoverSkillReplacement(target);\n const staged = join(\n dirname(target),\n `.${basename(target)}.openmeld-staged-${randomUUID()}`\n );\n const previous = join(\n dirname(target),\n `.${basename(target)}.openmeld-previous`\n );\n try {\n await prepare(staged);\n const hadPrevious = await exists(target);\n if (hadPrevious) {\n await rename(target, previous);\n }\n try {\n await rename(staged, target);\n } catch (error) {\n if (hadPrevious) {\n await rename(previous, target);\n }\n throw error;\n }\n // A cleanup failure must not roll back a committed replacement.\n await rm(previous, { recursive: true, force: true }).catch(() => undefined);\n } finally {\n await rm(staged, { recursive: true, force: true }).catch(() => undefined);\n }\n}\n\nasync function isManagedReplacement(\n path: string,\n skillId: string\n): Promise<boolean> {\n const raw = await readFile(join(path, \".openmeld-skill.json\"), \"utf8\").catch(\n () => null\n );\n if (raw) {\n try {\n const marker = JSON.parse(raw);\n return marker.managedBy === \"openmeld\" && marker.skillId === skillId;\n } catch {\n return false;\n }\n }\n // Legacy dangling links have no readable marker and carry no directory data.\n if ((await lstat(path)).isSymbolicLink()) {\n const destination = resolve(dirname(path), await readlink(path));\n return basename(destination) === skillId && !(await exists(destination));\n }\n return false;\n}\n\nfunction exists(path: string): Promise<boolean> {\n return lstat(path).then(\n () => true,\n (error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n );\n}\n","import { lstat, mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport path, { dirname, join, relative } from \"node:path\";\nimport { skillsDir } from \"../config/paths\";\nimport {\n type BundledSkillAsset,\n hashBundledSkillAssets,\n} from \"./bundled-assets\";\nimport { sortBundledSkillAssets } from \"./bundled-assets-fs\";\nimport { computeDirectoryContentHash } from \"./content-hash\";\nimport { withSkillsInstallLock } from \"./install-lock\";\nimport { loadSelectedSkillAssets } from \"./official-release\";\nimport {\n recoverSkillReplacement,\n replaceSkillDirectory,\n} from \"./replace-directory\";\n\nexport const OPENMELD_SKILL_MARKER_FILE = \".openmeld-skill.json\";\n\nexport type OpenMeldSkillMarker = {\n managedBy: \"openmeld\";\n skillId: string;\n mode: \"source\" | \"symlink\" | \"copy\";\n contentHash?: string;\n version?: string;\n updatedAt: string;\n};\n\nexport type LocalSkill = {\n id: string;\n name: string;\n absolutePath: string;\n relativePath: string;\n contentHash?: string;\n version?: string;\n};\n\nconst OPENMELD_CLI_SKILL_FILE = \"SKILL.md\";\nconst SKILL_NAME_REGEX = /^name:\\s*(.+)$/m;\n\nexport function ensureLocalSkills(): Promise<LocalSkill[]> {\n return withSkillsInstallLock(ensureLocalSkillsLocked);\n}\n\nasync function ensureLocalSkillsLocked(): Promise<LocalSkill[]> {\n const storePath = skillsDir();\n await mkdir(storePath, { recursive: true });\n\n const { assets, version: bundledVersion } = await loadSelectedSkillAssets();\n if (assets.length === 0) {\n return listLocalSkills();\n }\n const skillGroups = groupAssetsBySkill(assets);\n\n for (const [skillId, skillAssets] of skillGroups) {\n const targetDir = join(storePath, skillId);\n await recoverSkillReplacement(targetDir);\n const sourceContentHash = hashBundledSkillAssets(skillAssets);\n const existingMarker = await readOpenMeldSkillMarker(targetDir);\n const existing = await lstat(targetDir).catch(\n (error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n );\n if (existing && (!existingMarker || existing.isSymbolicLink())) {\n throw new Error(\n `OpenMeld Skill source conflicts with an unmanaged path: ${targetDir}`\n );\n }\n const isUpToDate =\n existingMarker?.managedBy === \"openmeld\" &&\n existingMarker.skillId === skillId &&\n existingMarker.mode === \"source\" &&\n existingMarker.contentHash === sourceContentHash &&\n existingMarker.version === bundledVersion &&\n (await computeDirectoryContentHash({\n rootDir: targetDir,\n ignoredNames: [OPENMELD_SKILL_MARKER_FILE],\n })) === sourceContentHash;\n if (isUpToDate) {\n continue;\n }\n\n await replaceSkillDirectory(targetDir, async (stagedDir) => {\n for (const asset of skillAssets) {\n const filePath = join(stagedDir, asset.relativePath);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, asset.content);\n }\n await writeOpenMeldSkillMarker({\n skillDir: stagedDir,\n skillId,\n mode: \"source\",\n contentHash: sourceContentHash,\n version: bundledVersion,\n });\n });\n }\n\n return listLocalSkills();\n}\n\n// Group loaded assets by their first path segment (the skill id). Top-level\n// files (e.g. skills/README.md) belong to no skill and are dropped, and a group\n// without a SKILL.md is dropped too — matching the previous \"only install skill\n// directories that contain SKILL.md\" behavior. Each group's paths are made\n// skill-relative and sorted so the per-skill hash matches the source tree.\nfunction groupAssetsBySkill(\n assets: BundledSkillAsset[]\n): Map<string, BundledSkillAsset[]> {\n const groups = new Map<string, BundledSkillAsset[]>();\n for (const asset of assets) {\n const slashIndex = asset.relativePath.indexOf(\"/\");\n if (slashIndex < 0) {\n continue;\n }\n const skillId = asset.relativePath.slice(0, slashIndex);\n const skillRelativePath = asset.relativePath.slice(slashIndex + 1);\n const group = groups.get(skillId) ?? [];\n group.push({ relativePath: skillRelativePath, content: asset.content });\n groups.set(skillId, group);\n }\n for (const [skillId, group] of [...groups.entries()]) {\n if (group.some((asset) => asset.relativePath === OPENMELD_CLI_SKILL_FILE)) {\n groups.set(skillId, sortBundledSkillAssets(group));\n } else {\n groups.delete(skillId);\n }\n }\n return groups;\n}\n\nexport async function listLocalSkills(): Promise<LocalSkill[]> {\n const storePath = skillsDir();\n const skillDirs = await discoverSkillDirs(storePath, 0, 6);\n const skills: LocalSkill[] = [];\n\n for (const skillDir of skillDirs) {\n const skillFile = join(skillDir, \"SKILL.md\");\n const raw = await readFile(skillFile, \"utf8\").catch(() => \"\");\n if (!raw) {\n continue;\n }\n const skillId = path.basename(skillDir);\n const skillName = readSkillName(raw) ?? skillId;\n const marker = await readOpenMeldSkillMarker(skillDir);\n skills.push({\n id: skillId,\n name: skillName,\n absolutePath: skillDir,\n relativePath: relative(storePath, skillDir) || skillId,\n ...(marker?.contentHash ? { contentHash: marker.contentHash } : {}),\n ...(marker?.version ? { version: marker.version } : {}),\n });\n }\n\n skills.sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n return skills;\n}\n\nexport async function writeOpenMeldSkillMarker(input: {\n skillDir: string;\n skillId: string;\n mode: \"source\" | \"symlink\" | \"copy\";\n contentHash?: string;\n version?: string;\n}): Promise<void> {\n const markerPath = join(input.skillDir, OPENMELD_SKILL_MARKER_FILE);\n const marker: OpenMeldSkillMarker = {\n managedBy: \"openmeld\",\n skillId: input.skillId,\n mode: input.mode,\n ...(input.contentHash ? { contentHash: input.contentHash } : {}),\n ...(input.version ? { version: input.version } : {}),\n updatedAt: new Date().toISOString(),\n };\n await writeFile(markerPath, `${JSON.stringify(marker, null, 2)}\\n`, \"utf8\");\n}\n\nexport async function isOpenMeldManagedSkillDir(\n skillDir: string\n): Promise<boolean> {\n const marker = await readOpenMeldSkillMarker(skillDir);\n return marker?.managedBy === \"openmeld\";\n}\n\nexport async function readOpenMeldSkillMarker(\n skillDir: string\n): Promise<OpenMeldSkillMarker | null> {\n const markerPath = join(skillDir, OPENMELD_SKILL_MARKER_FILE);\n const raw = await readFile(markerPath, \"utf8\").catch(() => null);\n if (!raw) {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as Partial<OpenMeldSkillMarker>;\n if (parsed.managedBy !== \"openmeld\") {\n return null;\n }\n if (\n typeof parsed.skillId !== \"string\" ||\n parsed.skillId.trim().length === 0\n ) {\n return null;\n }\n if (\n parsed.mode !== \"source\" &&\n parsed.mode !== \"symlink\" &&\n parsed.mode !== \"copy\"\n ) {\n return null;\n }\n return {\n managedBy: \"openmeld\",\n skillId: parsed.skillId.trim(),\n mode: parsed.mode,\n ...(typeof parsed.contentHash === \"string\" &&\n parsed.contentHash.trim().length > 0\n ? { contentHash: parsed.contentHash.trim() }\n : {}),\n ...(typeof parsed.version === \"string\" && parsed.version.trim().length > 0\n ? { version: parsed.version.trim() }\n : {}),\n updatedAt:\n typeof parsed.updatedAt === \"string\" &&\n parsed.updatedAt.trim().length > 0\n ? parsed.updatedAt\n : new Date().toISOString(),\n };\n } catch {\n return null;\n }\n}\n\nasync function discoverSkillDirs(\n dir: string,\n depth: number,\n maxDepth: number\n): Promise<string[]> {\n if (depth > maxDepth) {\n return [];\n }\n\n const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);\n if (entries.length === 0) {\n return [];\n }\n\n const hasSkill = entries.some(\n (entry) => entry.isFile() && entry.name === \"SKILL.md\"\n );\n if (hasSkill) {\n return [dir];\n }\n\n const nested = await Promise.all(\n entries\n .filter(\n (entry) => entry.isDirectory() && !entry.name.includes(\".openmeld-\")\n )\n .map((entry) =>\n discoverSkillDirs(join(dir, entry.name), depth + 1, maxDepth)\n )\n );\n\n return nested.flat();\n}\n\nfunction readSkillName(rawSkillFile: string): string | undefined {\n const match = rawSkillFile.match(SKILL_NAME_REGEX);\n if (!match) {\n return undefined;\n }\n const candidate = match[1]?.trim();\n return candidate && candidate.length > 0 ? candidate : undefined;\n}\n","import { lstat, readlink } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { computeDirectoryContentHash } from \"./content-hash\";\nimport type { SkillsInstallTarget } from \"./installer\";\nimport {\n type LocalSkill,\n type OpenMeldSkillMarker,\n readOpenMeldSkillMarker,\n} from \"./store\";\n\nexport type SkillInstallState =\n | \"missing\"\n | \"outdated\"\n | \"up_to_date\"\n | \"external_conflict\";\n\nexport type SkillInstallStateResult = {\n targetId: string;\n targetDir: string;\n targetType: \"agent\" | \"custom\";\n skillId: string;\n skillDir: string;\n state: SkillInstallState;\n targetMode?: OpenMeldSkillMarker[\"mode\"];\n sourceHash?: string;\n targetHash?: string;\n sourceVersion?: string;\n targetVersion?: string;\n reason?: string;\n};\n\ntype SourceSnapshot = {\n hash?: string;\n version?: string;\n};\n\ntype TargetSnapshot =\n | {\n exists: false;\n }\n | {\n exists: true;\n isSymlink: boolean;\n marker: OpenMeldSkillMarker | null;\n symlinkTargetPath: string;\n destinationExists: boolean;\n };\n\nexport async function resolveSkillsInstallStates(input: {\n skills: LocalSkill[];\n targets: SkillsInstallTarget[];\n}): Promise<SkillInstallStateResult[]> {\n const states: SkillInstallStateResult[] = [];\n for (const target of input.targets) {\n for (const skill of input.skills) {\n states.push(\n await resolveSkillInstallStateForTarget({\n skill,\n target,\n })\n );\n }\n }\n return states;\n}\n\nexport async function resolveSkillInstallStateForTarget(input: {\n skill: LocalSkill;\n target: SkillsInstallTarget;\n}): Promise<SkillInstallStateResult> {\n const base = createBaseResult(input);\n const source = await resolveSourceSnapshot(input.skill);\n const target = await resolveTargetSnapshot(base.skillDir);\n\n if (!target.exists) {\n return createStateResult({\n base,\n source,\n state: \"missing\",\n });\n }\n\n if (target.marker?.managedBy !== \"openmeld\") {\n if (\n isLegacyOpenMeldSkillSymlink({\n skillId: input.skill.id,\n target,\n })\n ) {\n return createStateResult({\n base,\n source,\n state: \"outdated\",\n targetMode: \"symlink\",\n reason: \"legacy OpenMeld skill link found; update required\",\n });\n }\n\n return createStateResult({\n base,\n source,\n state: \"external_conflict\",\n reason:\n \"existing non-OpenMeld skill detected; skipped to avoid overwrite\",\n });\n }\n\n if (!target.isSymlink && target.marker.contentHash) {\n const entry = await lstat(join(base.skillDir, \"SKILL.md\")).catch(\n () => null\n );\n if (!entry?.isFile()) {\n return createStateResult({\n base,\n source,\n state: \"outdated\",\n targetMarker: target.marker,\n reason: \"OpenMeld Skill entry is missing\",\n });\n }\n const actualHash = await computeDirectoryContentHash({\n rootDir: base.skillDir,\n ignoredNames: [\".openmeld-skill.json\"],\n });\n if (actualHash !== target.marker.contentHash) {\n return createStateResult({\n base,\n source,\n state: \"external_conflict\",\n targetMarker: target.marker,\n reason: \"OpenMeld Skill files were modified locally; kept your changes\",\n });\n }\n }\n\n const upToDate = isUpToDate({\n source,\n targetMarker: target.marker,\n isSymlink: target.isSymlink,\n symlinkTargetPath: target.symlinkTargetPath,\n sourceSkillDir: input.skill.absolutePath,\n });\n if (upToDate) {\n return createStateResult({\n base,\n source,\n targetMarker: target.marker,\n state: \"up_to_date\",\n reason: \"already up-to-date\",\n });\n }\n\n return createStateResult({\n base,\n source,\n targetMarker: target.marker,\n state: \"outdated\",\n reason: target.isSymlink\n ? \"OpenMeld skill link points to a different OpenMeld skills store; update required\"\n : \"OpenMeld skill content changed; update required\",\n });\n}\n\nfunction createBaseResult(input: {\n skill: LocalSkill;\n target: SkillsInstallTarget;\n}): Omit<SkillInstallStateResult, \"state\"> {\n const skillDir = join(input.target.dir, input.skill.id);\n return {\n targetId: input.target.id,\n targetDir: input.target.dir,\n targetType: input.target.type,\n skillId: input.skill.id,\n skillDir,\n };\n}\n\nasync function resolveSourceSnapshot(\n skill: LocalSkill\n): Promise<SourceSnapshot> {\n const sourceMarker = await readOpenMeldSkillMarker(skill.absolutePath);\n return {\n ...((skill.contentHash ?? sourceMarker?.contentHash)\n ? { hash: skill.contentHash ?? sourceMarker?.contentHash }\n : {}),\n ...((skill.version ?? sourceMarker?.version)\n ? { version: skill.version ?? sourceMarker?.version }\n : {}),\n };\n}\n\nasync function resolveTargetSnapshot(\n skillDir: string\n): Promise<TargetSnapshot> {\n const stats = await lstat(skillDir).catch(() => null);\n if (!stats) {\n return { exists: false };\n }\n\n let marker = await readOpenMeldSkillMarker(skillDir);\n let symlinkTargetPath = \"\";\n if (stats.isSymbolicLink()) {\n symlinkTargetPath = await resolveSymlinkTarget(skillDir).catch(() => \"\");\n if (!marker && symlinkTargetPath) {\n marker = await readOpenMeldSkillMarker(symlinkTargetPath);\n }\n }\n\n return {\n exists: true,\n isSymlink: stats.isSymbolicLink(),\n marker,\n symlinkTargetPath,\n destinationExists: symlinkTargetPath\n ? Boolean(await lstat(symlinkTargetPath).catch(() => null))\n : true,\n };\n}\n\nfunction isLegacyOpenMeldSkillSymlink(input: {\n skillId: string;\n target: Extract<TargetSnapshot, { exists: true }>;\n}): boolean {\n if (\n !(input.target.isSymlink && input.target.symlinkTargetPath) ||\n input.target.destinationExists\n ) {\n return false;\n }\n\n return basename(input.target.symlinkTargetPath) === input.skillId;\n}\n\nfunction isUpToDate(input: {\n source: SourceSnapshot;\n targetMarker: OpenMeldSkillMarker;\n isSymlink: boolean;\n symlinkTargetPath: string;\n sourceSkillDir: string;\n}): boolean {\n if (input.isSymlink) {\n // A symlinked target mirrors whatever store it points at, and its marker is\n // read through the link, so a matching hash/version only proves that other\n // store's state. The link is current only when it resolves to this store's\n // skill directory; anything else must be reinstalled before the foreign\n // store drifts or disappears.\n return (\n input.symlinkTargetPath.length > 0 &&\n pathsEqual(input.symlinkTargetPath, input.sourceSkillDir)\n );\n }\n return hasMatchingHashAndVersion(input.source, input.targetMarker);\n}\n\nfunction hasMatchingHashAndVersion(\n source: SourceSnapshot,\n targetMarker: OpenMeldSkillMarker\n): boolean {\n if (\n !(\n source.hash &&\n targetMarker.contentHash &&\n source.hash === targetMarker.contentHash\n )\n ) {\n return false;\n }\n return (\n !(source.version && targetMarker.version) ||\n source.version === targetMarker.version\n );\n}\n\nfunction createStateResult(input: {\n base: Omit<SkillInstallStateResult, \"state\">;\n source: SourceSnapshot;\n state: SkillInstallState;\n targetMode?: OpenMeldSkillMarker[\"mode\"];\n targetMarker?: OpenMeldSkillMarker;\n reason?: string;\n}): SkillInstallStateResult {\n return {\n ...input.base,\n state: input.state,\n ...(input.source.hash ? { sourceHash: input.source.hash } : {}),\n ...(input.source.version ? { sourceVersion: input.source.version } : {}),\n ...(input.targetMarker?.contentHash\n ? { targetHash: input.targetMarker.contentHash }\n : {}),\n ...(input.targetMarker?.mode\n ? { targetMode: input.targetMarker.mode }\n : {}),\n ...(input.targetMode ? { targetMode: input.targetMode } : {}),\n ...(input.targetMarker?.version\n ? { targetVersion: input.targetMarker.version }\n : {}),\n ...(input.reason ? { reason: input.reason } : {}),\n };\n}\n\nasync function resolveSymlinkTarget(linkPath: string): Promise<string> {\n const target = await readlink(linkPath);\n return resolve(dirname(linkPath), target);\n}\n\nfunction pathsEqual(left: string, right: string): boolean {\n return resolve(left) === resolve(right);\n}\n"],"mappings":"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"}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { lt as resolveOpenMeldEnvPreset } from "./lock-iue1J2xy.js";
|
|
4
|
+
import { dt as DEFAULT_CLI_BINARY_DOWNLOAD_POLICY, ft as allowUnsignedWindowsInternalPreview, gt as verifyCliBinaryCodeSignature, ht as resolveCliBinaryUpdatePlan, it as hasIndependentMaintenanceRegistration, mt as prepareCliBinaryProcessHelper, pt as downloadCliBinaryUpdateArtifact } from "./daemon-service-runtime-CBJtgM4P.js";
|
|
5
|
+
import { Dt as resolveVersionChangeDirection, Ft as resolveServiceUpdateUrgency, Pt as resolveCurrentDaemonExpectedVersion, Tt as resolveDaemonServiceAlignmentDecision, f as formatDaemonFailureContextText, ft as inspectDaemonServiceInventory, n as scheduleDaemonServiceUpdate, nt as createOpenMeldToolsUpdateCoordinator, rt as readOpenMeldToolsUpdateContextFromEnv, wt as buildDaemonServiceTargetSpec } from "./daemon-service-update-coordinator-0LB_XGVZ.js";
|
|
5
6
|
import { t as isBinaryDistribution } from "./distribution-BDQT2ilb.js";
|
|
6
7
|
import { a as formatOpenMeldCliTextBlock, t as formatInlineOpenMeldCliCommands } from "./cli-entry-command-CR_9QU1i.js";
|
|
7
|
-
import { _ as writeVersionState, g as readVersionState, l as OPENMELD_VERSION, m as fetchLatestPackageInfo, p as fetchLatestCliBinaryRelease, u as buildNextVersionState } from "./daemon-lifecycle-journal-
|
|
8
|
-
import { n as resolveRuntimeContext } from "./context-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { c as
|
|
12
|
-
import {
|
|
8
|
+
import { _ as writeVersionState, g as readVersionState, l as OPENMELD_VERSION, m as fetchLatestPackageInfo, p as fetchLatestCliBinaryRelease, u as buildNextVersionState } from "./daemon-lifecycle-journal-CDZLWgMj.js";
|
|
9
|
+
import { n as resolveRuntimeContext } from "./context-Bdh3nAzw.js";
|
|
10
|
+
import { n as outJsonLine } from "./io-DT66typ4.js";
|
|
11
|
+
import { t as createPresenter } from "./presenter-MJ5YgsOT.js";
|
|
12
|
+
import { X as getCommandEntryContract, Y as createUpgradeConfirmationGuideError, a as formatDaemonServiceDowngradeBlockedRecommendation, c as formatDaemonServiceMissingRecommendation, g as canUseInteractivePrompts, n as resolveElapsedTimeMs, t as formatElapsedTime, xt as buildAgentOverviewFromContract } from "./elapsed-time-q8lSPcfm.js";
|
|
13
|
+
import { c as withOpenMeldToolsUpdateFailure, i as OpenMeldToolsUpdateFailureError, r as parseOpenMeldToolsUpdateFailureFrame } from "./openmeld-tools-update-process-frame-BtFKp70p.js";
|
|
14
|
+
import { t as resolveExternalOpenMeldToolsUpdate } from "./openmeld-tools-update-join-D24llJ9L.js";
|
|
13
15
|
import { tmpdir } from "node:os";
|
|
14
16
|
import { basename, dirname, join } from "node:path";
|
|
15
17
|
import { chmod, mkdtemp, realpath, rm, stat, writeFile } from "node:fs/promises";
|
|
@@ -175,9 +177,9 @@ function resolveTopLevelEntryName(command) {
|
|
|
175
177
|
//#endregion
|
|
176
178
|
//#region src/commands/upgrade.ts
|
|
177
179
|
const OPENMELD_PACKAGE_NAME = "openmeld";
|
|
178
|
-
const
|
|
180
|
+
const BINARY_UPGRADE_RECOVERY_URL = "https://openmeld.ai";
|
|
179
181
|
const STAGING_BINARY_MANIFEST_URL = "https://staging.openmeld.ai/cli/manifest.json";
|
|
180
|
-
const
|
|
182
|
+
const STAGING_BINARY_UPGRADE_RECOVERY_URL = "https://staging.openmeld.ai";
|
|
181
183
|
const INSTALL_SELF_JSON_LINE_SPLIT_RE = /\r?\n/u;
|
|
182
184
|
const SERVICE_CHECK_STARTED_TEXT = "Checking OpenMeld Service";
|
|
183
185
|
const SERVICE_CHECK_COMPLETED_TEXT = "OpenMeld Service check finished.";
|
|
@@ -240,12 +242,12 @@ async function runUpgradeWithRuntime(input, runtime) {
|
|
|
240
242
|
}
|
|
241
243
|
const allowPrompt = canUseInteractivePrompts(runtime);
|
|
242
244
|
const currentVersion = OPENMELD_VERSION;
|
|
243
|
-
const { currentGlobalInstall,
|
|
245
|
+
const { currentGlobalInstall, manualUpgradeRecovery } = await resolveUpgradeInstallContext();
|
|
244
246
|
const previousVersionState = await readVersionState();
|
|
245
247
|
if (!previousVersionState) handleMissingVersionMetadata({
|
|
246
248
|
presenter,
|
|
247
249
|
resolvedView: runtime.resolvedView,
|
|
248
|
-
|
|
250
|
+
manualUpgradeRecovery
|
|
249
251
|
});
|
|
250
252
|
const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
251
253
|
const checkingStage = startUpgradeStage({
|
|
@@ -298,7 +300,7 @@ async function runUpgradeWithRuntime(input, runtime) {
|
|
|
298
300
|
presenter,
|
|
299
301
|
resolvedView: runtime.resolvedView,
|
|
300
302
|
upgradeStatus,
|
|
301
|
-
|
|
303
|
+
manualUpgradeRecovery
|
|
302
304
|
});
|
|
303
305
|
const installableUpgradeStatus = requireInstallableUpgradeStatus(upgradeStatus);
|
|
304
306
|
if (!currentUpdate && await hasIndependentMaintenanceRegistration()) {
|
|
@@ -312,7 +314,7 @@ async function runUpgradeWithRuntime(input, runtime) {
|
|
|
312
314
|
await installAndReconcileBinaryUpgrade({
|
|
313
315
|
upgradeStatus: installableUpgradeStatus,
|
|
314
316
|
previousVersionState,
|
|
315
|
-
|
|
317
|
+
manualUpgradeRecovery,
|
|
316
318
|
resolvedView: runtime.resolvedView,
|
|
317
319
|
currentVersion,
|
|
318
320
|
presenter
|
|
@@ -323,7 +325,7 @@ async function runUpgradeWithRuntime(input, runtime) {
|
|
|
323
325
|
upgradeStatus: installableUpgradeStatus,
|
|
324
326
|
previousVersionState,
|
|
325
327
|
currentGlobalInstall,
|
|
326
|
-
|
|
328
|
+
manualUpgradeRecovery,
|
|
327
329
|
resolvedView: runtime.resolvedView,
|
|
328
330
|
currentVersion,
|
|
329
331
|
presenter
|
|
@@ -462,7 +464,7 @@ async function installAndReconcileBinaryUpgrade(input) {
|
|
|
462
464
|
startedText: `Downloading and installing OpenMeld CLI (about ${bytesToRoundedMb(updatePlan.downloadSizeBytes)} MB)`,
|
|
463
465
|
completedText: `OpenMeld CLI ${input.upgradeStatus.latestVersion} installed.`,
|
|
464
466
|
data: {
|
|
465
|
-
|
|
467
|
+
recoveryUrl: input.manualUpgradeRecovery.value,
|
|
466
468
|
downloadSizeBytes: updatePlan.downloadSizeBytes,
|
|
467
469
|
distribution: input.upgradeStatus.distribution,
|
|
468
470
|
preferredTransport: updatePlan.transport
|
|
@@ -470,7 +472,7 @@ async function installAndReconcileBinaryUpgrade(input) {
|
|
|
470
472
|
failureCode: "cli.update.install_failed",
|
|
471
473
|
run: async () => await installLatestCliBinary({
|
|
472
474
|
release: binaryRelease,
|
|
473
|
-
|
|
475
|
+
manualUpgradeRecovery: input.manualUpgradeRecovery,
|
|
474
476
|
updatePlan
|
|
475
477
|
})
|
|
476
478
|
});
|
|
@@ -515,14 +517,14 @@ async function installAndReconcileNpmUpgrade(input) {
|
|
|
515
517
|
startedText: "Downloading and installing OpenMeld CLI with npm",
|
|
516
518
|
completedText: `OpenMeld CLI ${input.upgradeStatus.latestVersion} installed.`,
|
|
517
519
|
data: {
|
|
518
|
-
command: input.
|
|
520
|
+
command: input.manualUpgradeRecovery.value,
|
|
519
521
|
distribution: input.upgradeStatus.distribution
|
|
520
522
|
},
|
|
521
523
|
failureCode: "cli.update.install_failed",
|
|
522
524
|
run: async () => await installLatestPackage({
|
|
523
525
|
npmCommandSpec,
|
|
524
526
|
currentGlobalInstall: input.currentGlobalInstall,
|
|
525
|
-
manualUpgradeCommand: input.
|
|
527
|
+
manualUpgradeCommand: input.manualUpgradeRecovery.value
|
|
526
528
|
})
|
|
527
529
|
});
|
|
528
530
|
const latestVersion = input.upgradeStatus.latestVersion;
|
|
@@ -556,7 +558,10 @@ async function installAndReconcileNpmUpgrade(input) {
|
|
|
556
558
|
async function resolveUpgradeInstallContext() {
|
|
557
559
|
if (isBinaryDistribution()) return {
|
|
558
560
|
currentGlobalInstall: null,
|
|
559
|
-
|
|
561
|
+
manualUpgradeRecovery: {
|
|
562
|
+
kind: "web",
|
|
563
|
+
value: resolveBinaryUpgradeRecoveryUrl()
|
|
564
|
+
}
|
|
560
565
|
};
|
|
561
566
|
const currentGlobalInstall = await resolveCurrentNpmGlobalPackageInstall({
|
|
562
567
|
packageName: OPENMELD_PACKAGE_NAME,
|
|
@@ -565,26 +570,32 @@ async function resolveUpgradeInstallContext() {
|
|
|
565
570
|
if (process.env.OPENMELD_INTERNAL_MAINTENANCE_WORKER === "1" && !currentGlobalInstall) throw new Error("OpenMeld could not identify the original npm installation. Automatic update stopped to preserve the current installation.");
|
|
566
571
|
return {
|
|
567
572
|
currentGlobalInstall,
|
|
568
|
-
|
|
573
|
+
manualUpgradeRecovery: {
|
|
574
|
+
kind: "command",
|
|
575
|
+
value: buildManualOpenMeldUpgradeCommand({ globalPrefixPath: currentGlobalInstall?.globalPrefixPath ?? null })
|
|
576
|
+
}
|
|
569
577
|
};
|
|
570
578
|
}
|
|
571
|
-
function
|
|
572
|
-
return env.OPENMELD_ENV_PRESET === "canary" && env.OPENMELD_CLI_BINARY_MANIFEST_URL === STAGING_BINARY_MANIFEST_URL ?
|
|
579
|
+
function resolveBinaryUpgradeRecoveryUrl(env = process.env) {
|
|
580
|
+
return env.OPENMELD_ENV_PRESET === "canary" && env.OPENMELD_CLI_BINARY_MANIFEST_URL === STAGING_BINARY_MANIFEST_URL ? STAGING_BINARY_UPGRADE_RECOVERY_URL : BINARY_UPGRADE_RECOVERY_URL;
|
|
581
|
+
}
|
|
582
|
+
function formatManualUpgradeRecovery(recovery) {
|
|
583
|
+
return recovery.kind === "web" ? `Open ${recovery.value}, go to Computers, and use Update manually or Connect Computer to get a fresh setup command. Run that command on this Mac.` : `Run \`${recovery.value}\`.`;
|
|
573
584
|
}
|
|
574
585
|
function handleMissingVersionMetadata(input) {
|
|
575
|
-
const errorMessage = formatOpenMeldCliTextBlock(`OpenMeld version metadata is missing, so automatic upgrade cannot continue.\nManual fallback:
|
|
586
|
+
const errorMessage = formatOpenMeldCliTextBlock(`OpenMeld version metadata is missing, so automatic upgrade cannot continue.\nManual fallback: ${formatManualUpgradeRecovery(input.manualUpgradeRecovery)}\nIf you want to repair local OpenMeld state first, run \`openmeld reset --yes\` before \`openmeld upgrade\`.`);
|
|
576
587
|
if (input.resolvedView === "agent") {
|
|
577
588
|
input.presenter.data({
|
|
578
589
|
code: "upgrade.metadata.missing",
|
|
579
590
|
payload: {
|
|
580
591
|
summary: "Local OpenMeld version metadata is missing, so automatic upgrade cannot verify downgrade safety.",
|
|
581
592
|
nextSteps: [
|
|
582
|
-
input.
|
|
593
|
+
formatManualUpgradeRecovery(input.manualUpgradeRecovery),
|
|
583
594
|
"openmeld-dev reset --yes --view agent",
|
|
584
595
|
"openmeld-dev start",
|
|
585
596
|
"openmeld-dev upgrade --check --view agent"
|
|
586
597
|
],
|
|
587
|
-
humanActionRequired:
|
|
598
|
+
humanActionRequired: input.manualUpgradeRecovery.kind === "web"
|
|
588
599
|
}
|
|
589
600
|
});
|
|
590
601
|
throw new UpgradeOutputHandledError(errorMessage);
|
|
@@ -592,18 +603,18 @@ function handleMissingVersionMetadata(input) {
|
|
|
592
603
|
throw new Error(errorMessage);
|
|
593
604
|
}
|
|
594
605
|
function handleUpgradeCheckFailure(input) {
|
|
595
|
-
const errorMessage = formatOpenMeldCliTextBlock(`Version check failed (${input.upgradeStatus.error}). Upgrade stopped because downgrade protection requires confirming that ${formatUpgradeLatestSource(input.upgradeStatus.distribution)} is newer than the current CLI.\nManual fallback:
|
|
606
|
+
const errorMessage = formatOpenMeldCliTextBlock(`Version check failed (${input.upgradeStatus.error}). Upgrade stopped because downgrade protection requires confirming that ${formatUpgradeLatestSource(input.upgradeStatus.distribution)} is newer than the current CLI.\nManual fallback: ${formatManualUpgradeRecovery(input.manualUpgradeRecovery)}`);
|
|
596
607
|
if (input.resolvedView === "agent") {
|
|
597
608
|
input.presenter.data({
|
|
598
609
|
code: "upgrade.check_failed",
|
|
599
610
|
payload: {
|
|
600
611
|
...input.upgradeStatus,
|
|
601
612
|
nextSteps: [
|
|
602
|
-
input.
|
|
613
|
+
formatManualUpgradeRecovery(input.manualUpgradeRecovery),
|
|
603
614
|
"openmeld-dev upgrade --check --view agent",
|
|
604
615
|
"openmeld-dev upgrade --yes --view agent"
|
|
605
616
|
],
|
|
606
|
-
humanActionRequired:
|
|
617
|
+
humanActionRequired: input.manualUpgradeRecovery.kind === "web"
|
|
607
618
|
}
|
|
608
619
|
});
|
|
609
620
|
throw new UpgradeOutputHandledError(errorMessage);
|
|
@@ -695,10 +706,19 @@ async function installLatestCliBinary(input) {
|
|
|
695
706
|
await writeFile(artifactPath, artifactBytes);
|
|
696
707
|
await chmod(artifactPath, 493);
|
|
697
708
|
await verifyCliBinaryCodeSignature({
|
|
709
|
+
allowUnsignedPreview: allowUnsignedWindowsInternalPreview(),
|
|
698
710
|
artifactPath,
|
|
711
|
+
allowUnsignedForDevelopment: resolveOpenMeldEnvPreset() === "dev-local",
|
|
699
712
|
release: input.release,
|
|
700
713
|
runCommand
|
|
701
714
|
});
|
|
715
|
+
await prepareCliBinaryProcessHelper({
|
|
716
|
+
allowUnsignedPreview: allowUnsignedWindowsInternalPreview(),
|
|
717
|
+
artifactPath,
|
|
718
|
+
release: input.release,
|
|
719
|
+
downloadPolicy: DEFAULT_CLI_BINARY_DOWNLOAD_POLICY,
|
|
720
|
+
fetchImpl: fetch
|
|
721
|
+
});
|
|
702
722
|
const installResult = await runCommand(artifactPath, [
|
|
703
723
|
"install-self",
|
|
704
724
|
"--force",
|
|
@@ -706,7 +726,7 @@ async function installLatestCliBinary(input) {
|
|
|
706
726
|
]);
|
|
707
727
|
if (installResult.code !== 0) {
|
|
708
728
|
const details = installResult.stderr.trim() || installResult.stdout.trim();
|
|
709
|
-
throw new Error(formatOpenMeldCliTextBlock(`binary install-self failed (exit ${installResult.code})${details ? `: ${details}` : ""}\nManual fallback:
|
|
729
|
+
throw new Error(formatOpenMeldCliTextBlock(`binary install-self failed (exit ${installResult.code})${details ? `: ${details}` : ""}\nManual fallback: ${formatManualUpgradeRecovery(input.manualUpgradeRecovery)}`));
|
|
710
730
|
}
|
|
711
731
|
const installed = parseInstallSelfJsonOutput(installResult.stdout);
|
|
712
732
|
if (installed.version !== input.release.version) throw new Error(`binary install-self returned version ${installed.version}, expected ${input.release.version}`);
|
|
@@ -1090,6 +1110,6 @@ function toErrorMessage(error) {
|
|
|
1090
1110
|
return String(error);
|
|
1091
1111
|
}
|
|
1092
1112
|
//#endregion
|
|
1093
|
-
export { runUpgrade as a, OPENMELD_UPGRADE_FAILURE_HINTS as c, runMaintenanceUpgrade as i, OPENMELD_UPGRADE_METADATA_RECOVERY_HINTS as l, isUpgradeOutputHandledError as n, emitTopLevelAgentOverview as o,
|
|
1113
|
+
export { runUpgrade as a, OPENMELD_UPGRADE_FAILURE_HINTS as c, runMaintenanceUpgrade as i, OPENMELD_UPGRADE_METADATA_RECOVERY_HINTS as l, isUpgradeOutputHandledError as n, emitTopLevelAgentOverview as o, resolveBinaryUpgradeRecoveryUrl as r, emitTopLevelCliAgentOverview as s, UPGRADE_INTERNAL_ALIGN_SERVICE_FLAG as t };
|
|
1094
1114
|
|
|
1095
|
-
//# sourceMappingURL=upgrade-
|
|
1115
|
+
//# sourceMappingURL=upgrade-DfJwCD5H.js.map
|