@skaile/workspaces 6.13.1 → 6.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/app-sdk/index.js +1 -1
  3. package/dist/{asset-feeds-HS4IUMUN.js → asset-feeds-PM7FKHJP.js} +6 -6
  4. package/dist/{asset-feeds-HS4IUMUN.js.map → asset-feeds-PM7FKHJP.js.map} +1 -1
  5. package/dist/asset-manager/index.js +1 -1
  6. package/dist/bridge/harnesses/claude-sdk.js +15 -17
  7. package/dist/bridge/harnesses/claude-sdk.js.map +1 -1
  8. package/dist/bridge/harnesses/codex.js +4 -4
  9. package/dist/bridge/harnesses/continue.js +5 -5
  10. package/dist/bridge/harnesses/echo.js +4 -4
  11. package/dist/bridge/harnesses/gemini.js +7 -7
  12. package/dist/bridge/harnesses/goose.js +5 -5
  13. package/dist/bridge/harnesses/omp.js +9 -8
  14. package/dist/bridge/harnesses/omp.js.map +1 -1
  15. package/dist/bridge/harnesses/opencode.js +7 -88
  16. package/dist/bridge/harnesses/opencode.js.map +1 -1
  17. package/dist/bridge/harnesses/qwen.js +7 -7
  18. package/dist/bridge/index.js +13 -11
  19. package/dist/bridge/src/harness-binaries.d.ts +52 -5
  20. package/dist/bridge/src/harness-binaries.d.ts.map +1 -1
  21. package/dist/bridge/src/harness-detect.d.ts +73 -0
  22. package/dist/bridge/src/harness-detect.d.ts.map +1 -0
  23. package/dist/bridge/src/harness-model-check.d.ts.map +1 -1
  24. package/dist/bridge/src/harness-model-discovery.d.ts +66 -0
  25. package/dist/bridge/src/harness-model-discovery.d.ts.map +1 -0
  26. package/dist/bridge/src/harnesses/_subprocess-cli.d.ts.map +1 -1
  27. package/dist/bridge/src/harnesses/claude-sdk.d.ts +4 -2
  28. package/dist/bridge/src/harnesses/claude-sdk.d.ts.map +1 -1
  29. package/dist/bridge/src/harnesses/omp.d.ts.map +1 -1
  30. package/dist/bridge/src/index.d.ts +3 -1
  31. package/dist/bridge/src/index.d.ts.map +1 -1
  32. package/dist/bridge/src/models.d.ts +9 -0
  33. package/dist/bridge/src/models.d.ts.map +1 -1
  34. package/dist/{chunk-GFBKUX3J.js → chunk-2RVEYDQK.js} +7 -21
  35. package/dist/chunk-2RVEYDQK.js.map +1 -0
  36. package/dist/{chunk-MVUXBWNW.js → chunk-6HTN2UIJ.js} +3 -3
  37. package/dist/{chunk-MVUXBWNW.js.map → chunk-6HTN2UIJ.js.map} +1 -1
  38. package/dist/{chunk-4KALKIWP.js → chunk-6VQW2X2F.js} +7 -7
  39. package/dist/{chunk-4KALKIWP.js.map → chunk-6VQW2X2F.js.map} +1 -1
  40. package/dist/{chunk-4OAUOH3A.js → chunk-6WIZC6GM.js} +5 -5
  41. package/dist/{chunk-4OAUOH3A.js.map → chunk-6WIZC6GM.js.map} +1 -1
  42. package/dist/{chunk-6EPNTAF3.js → chunk-72PPC4SC.js} +4 -4
  43. package/dist/{chunk-6EPNTAF3.js.map → chunk-72PPC4SC.js.map} +1 -1
  44. package/dist/{chunk-3NKXGAP4.js → chunk-A3G3FHGB.js} +2 -2
  45. package/dist/{chunk-3NKXGAP4.js.map → chunk-A3G3FHGB.js.map} +1 -1
  46. package/dist/{chunk-Z56QSYGJ.js → chunk-A4VKIVGB.js} +4 -4
  47. package/dist/{chunk-Z56QSYGJ.js.map → chunk-A4VKIVGB.js.map} +1 -1
  48. package/dist/chunk-AEFDFCS2.js +88 -0
  49. package/dist/chunk-AEFDFCS2.js.map +1 -0
  50. package/dist/{chunk-HTJPDSAC.js → chunk-C5ZCREBI.js} +3 -3
  51. package/dist/{chunk-HTJPDSAC.js.map → chunk-C5ZCREBI.js.map} +1 -1
  52. package/dist/{chunk-TBH6UXYN.js → chunk-CWUHUL6W.js} +3 -3
  53. package/dist/{chunk-TBH6UXYN.js.map → chunk-CWUHUL6W.js.map} +1 -1
  54. package/dist/{chunk-G2ZWIYZR.js → chunk-DFFJKGCW.js} +3 -3
  55. package/dist/{chunk-G2ZWIYZR.js.map → chunk-DFFJKGCW.js.map} +1 -1
  56. package/dist/{chunk-EISPUJ7D.js → chunk-EMIOFJQJ.js} +3 -3
  57. package/dist/{chunk-EISPUJ7D.js.map → chunk-EMIOFJQJ.js.map} +1 -1
  58. package/dist/{chunk-2O4QWC5S.js → chunk-FJJEC6O2.js} +4 -4
  59. package/dist/{chunk-2O4QWC5S.js.map → chunk-FJJEC6O2.js.map} +1 -1
  60. package/dist/{chunk-HP62IELJ.js → chunk-HCIXCCUH.js} +3 -3
  61. package/dist/{chunk-HP62IELJ.js.map → chunk-HCIXCCUH.js.map} +1 -1
  62. package/dist/{chunk-GJT2Q5XD.js → chunk-HXST2IYJ.js} +3 -3
  63. package/dist/{chunk-GJT2Q5XD.js.map → chunk-HXST2IYJ.js.map} +1 -1
  64. package/dist/{chunk-YYQDSC7I.js → chunk-IRIWNKQS.js} +3 -3
  65. package/dist/{chunk-YYQDSC7I.js.map → chunk-IRIWNKQS.js.map} +1 -1
  66. package/dist/{chunk-GIMFNRNR.js → chunk-IYXOSBQ4.js} +419 -15
  67. package/dist/chunk-IYXOSBQ4.js.map +1 -0
  68. package/dist/{chunk-MECT5Z5D.js → chunk-J7FEWDRQ.js} +5 -5
  69. package/dist/{chunk-MECT5Z5D.js.map → chunk-J7FEWDRQ.js.map} +1 -1
  70. package/dist/{chunk-E6BXLB5Z.js → chunk-JIZ35OOU.js} +3 -3
  71. package/dist/{chunk-E6BXLB5Z.js.map → chunk-JIZ35OOU.js.map} +1 -1
  72. package/dist/{chunk-DWPQBMCY.js → chunk-JPV4WE5L.js} +2 -2
  73. package/dist/{chunk-DWPQBMCY.js.map → chunk-JPV4WE5L.js.map} +1 -1
  74. package/dist/{chunk-AONNQPPS.js → chunk-KIFAU62K.js} +3 -3
  75. package/dist/{chunk-AONNQPPS.js.map → chunk-KIFAU62K.js.map} +1 -1
  76. package/dist/{chunk-JXKT2QGT.js → chunk-LBJCOEXH.js} +10 -4
  77. package/dist/chunk-LBJCOEXH.js.map +1 -0
  78. package/dist/{chunk-HG2PDB3T.js → chunk-MUQBP2BK.js} +2 -2
  79. package/dist/{chunk-HG2PDB3T.js.map → chunk-MUQBP2BK.js.map} +1 -1
  80. package/dist/{chunk-DUIZB6JM.js → chunk-O74SRQ3W.js} +3 -3
  81. package/dist/{chunk-DUIZB6JM.js.map → chunk-O74SRQ3W.js.map} +1 -1
  82. package/dist/{chunk-7YGOEJRD.js → chunk-OIWFXUZB.js} +4 -4
  83. package/dist/{chunk-7YGOEJRD.js.map → chunk-OIWFXUZB.js.map} +1 -1
  84. package/dist/{chunk-P6VNPRLD.js → chunk-PFBPESW7.js} +8 -8
  85. package/dist/{chunk-P6VNPRLD.js.map → chunk-PFBPESW7.js.map} +1 -1
  86. package/dist/{chunk-ZJMSX2T6.js → chunk-R7422XD4.js} +7 -7
  87. package/dist/{chunk-ZJMSX2T6.js.map → chunk-R7422XD4.js.map} +1 -1
  88. package/dist/{chunk-R2P77YRM.js → chunk-RKTEHX2S.js} +3 -3
  89. package/dist/{chunk-R2P77YRM.js.map → chunk-RKTEHX2S.js.map} +1 -1
  90. package/dist/{chunk-7MO23JPX.js → chunk-SXRN27TU.js} +5 -5
  91. package/dist/{chunk-7MO23JPX.js.map → chunk-SXRN27TU.js.map} +1 -1
  92. package/dist/{chunk-BALPY67W.js → chunk-TYRAEMWE.js} +3 -3
  93. package/dist/{chunk-BALPY67W.js.map → chunk-TYRAEMWE.js.map} +1 -1
  94. package/dist/{chunk-MNED5ZCW.js → chunk-U7EJB6LY.js} +2 -2
  95. package/dist/{chunk-MNED5ZCW.js.map → chunk-U7EJB6LY.js.map} +1 -1
  96. package/dist/{chunk-ESUF2ZYT.js → chunk-U7EZ2WSC.js} +2 -2
  97. package/dist/{chunk-ESUF2ZYT.js.map → chunk-U7EZ2WSC.js.map} +1 -1
  98. package/dist/{chunk-UZCAULGU.js → chunk-XPSZIBPU.js} +8 -8
  99. package/dist/{chunk-UZCAULGU.js.map → chunk-XPSZIBPU.js.map} +1 -1
  100. package/dist/{chunk-UBN7HI4S.js → chunk-YDMZWVZN.js} +3 -3
  101. package/dist/{chunk-UBN7HI4S.js.map → chunk-YDMZWVZN.js.map} +1 -1
  102. package/dist/chunk-YKD2MYLU.js +210 -0
  103. package/dist/chunk-YKD2MYLU.js.map +1 -0
  104. package/dist/{chunk-F6IEGYOI.js → chunk-YLKOCMU7.js} +101 -55
  105. package/dist/chunk-YLKOCMU7.js.map +1 -0
  106. package/dist/{claude-code-G52B7TRB.js → claude-code-5QYXWC5H.js} +4 -4
  107. package/dist/{claude-code-G52B7TRB.js.map → claude-code-5QYXWC5H.js.map} +1 -1
  108. package/dist/cli/index.js +95 -57
  109. package/dist/cli/index.js.map +1 -1
  110. package/dist/cli/src/commands/harness-preflight.d.ts.map +1 -1
  111. package/dist/cli/src/commands/harness.d.ts +14 -0
  112. package/dist/cli/src/commands/harness.d.ts.map +1 -1
  113. package/dist/cli/src/commands/serve-preflight.d.ts +1 -6
  114. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
  115. package/dist/connectors/index.js +15 -13
  116. package/dist/{connectors-TT6HTFH6.js → connectors-DLXW27NQ.js} +18 -16
  117. package/dist/{connectors-TT6HTFH6.js.map → connectors-DLXW27NQ.js.map} +1 -1
  118. package/dist/connectors-shared/index.js +2 -2
  119. package/dist/{ensure-sources-XZ3MUJOM.js → ensure-sources-I7GCXPXK.js} +17 -15
  120. package/dist/ensure-sources-I7GCXPXK.js.map +1 -0
  121. package/dist/factory-assets/connectors/box.js +15 -13
  122. package/dist/factory-assets/connectors/deploy.js +15 -13
  123. package/dist/factory-assets/connectors/devserver.js +15 -13
  124. package/dist/factory-assets/connectors/flow/adapter.js +15 -13
  125. package/dist/factory-assets/connectors/flow/run-flow.js +16 -14
  126. package/dist/factory-assets/connectors/flow.js +15 -13
  127. package/dist/factory-assets/connectors/git.js +15 -13
  128. package/dist/factory-assets/connectors/gmail.js +15 -13
  129. package/dist/factory-assets/connectors/googledrive.js +15 -13
  130. package/dist/factory-assets/connectors/local.js +15 -13
  131. package/dist/factory-assets/connectors/mattermost.js +15 -13
  132. package/dist/factory-assets/connectors/memory.js +15 -13
  133. package/dist/factory-assets/connectors/minio.js +15 -13
  134. package/dist/factory-assets/connectors/postgres.js +15 -13
  135. package/dist/factory-assets/connectors/s3.js +15 -13
  136. package/dist/factory-assets/connectors/sharepoint.js +15 -13
  137. package/dist/factory-assets/connectors/sqlite.js +15 -13
  138. package/dist/factory-assets/connectors/static-server.js +15 -13
  139. package/dist/factory-assets/connectors/tunnel.js +15 -13
  140. package/dist/factory-assets/connectors/webdav.js +15 -13
  141. package/dist/factory-assets/connectors/xstate-store.js +15 -13
  142. package/dist/factory-assets/connectors/xstate.js +15 -13
  143. package/dist/{helpers-Q6LFWGYT.js → helpers-U75UGGH5.js} +17 -15
  144. package/dist/{helpers-Q6LFWGYT.js.map → helpers-U75UGGH5.js.map} +1 -1
  145. package/dist/{library-publish-OADODIMW.js → library-publish-57422ULT.js} +30 -28
  146. package/dist/library-publish-57422ULT.js.map +1 -0
  147. package/dist/model-endpoint/index.js +3 -3
  148. package/dist/{open-library-MNCHOTAF.js → open-library-EVUKLOV7.js} +18 -16
  149. package/dist/{open-library-MNCHOTAF.js.map → open-library-EVUKLOV7.js.map} +1 -1
  150. package/dist/{project-PHO6JOVL.js → project-HB7OYPEF.js} +26 -24
  151. package/dist/{project-PHO6JOVL.js.map → project-HB7OYPEF.js.map} +1 -1
  152. package/dist/runner/index.js +21 -19
  153. package/dist/runner/src/compaction/prompt.d.ts.map +1 -1
  154. package/dist/runner/src/context-usage/compose.d.ts.map +1 -1
  155. package/dist/runner/src/session-builder.d.ts.map +1 -1
  156. package/dist/runner/src/work-practices.d.ts +9 -0
  157. package/dist/runner/src/work-practices.d.ts.map +1 -0
  158. package/dist/sdk/asset-manager.js +1 -1
  159. package/dist/sdk/bridge.js +13 -11
  160. package/dist/sdk/index.js +21 -19
  161. package/dist/sdk/index.js.map +1 -1
  162. package/dist/sdk/runner.js +21 -19
  163. package/dist/sdk/session.js +2 -2
  164. package/dist/sdk/types.js +1 -1
  165. package/dist/{serve-preflight-GLE2LPGT.js → serve-preflight-YY3YC6GH.js} +19 -17
  166. package/dist/{serve-preflight-GLE2LPGT.js.map → serve-preflight-YY3YC6GH.js.map} +1 -1
  167. package/dist/session/index.js +2 -2
  168. package/dist/{setup-EPNOIKDM.js → setup-2XV6T53V.js} +18 -16
  169. package/dist/setup-2XV6T53V.js.map +1 -0
  170. package/dist/{source-CUSCY3KR.js → source-VXE3RSSA.js} +28 -26
  171. package/dist/{source-CUSCY3KR.js.map → source-VXE3RSSA.js.map} +1 -1
  172. package/dist/{source-manifest-publish-AHLDG4XS.js → source-manifest-publish-IIVQLM67.js} +30 -28
  173. package/dist/source-manifest-publish-IIVQLM67.js.map +1 -0
  174. package/dist/tui/index.js +21 -19
  175. package/dist/tui/index.js.map +1 -1
  176. package/dist/types/index.js +1 -1
  177. package/dist/types/src/context-usage.d.ts +1 -1
  178. package/dist/types/src/events.d.ts +3 -2
  179. package/dist/types/src/events.d.ts.map +1 -1
  180. package/dist/workspace-plugin/adapters/mcp.js +17 -15
  181. package/dist/workspace-plugin/adapters/omp.js +7 -7
  182. package/dist/workspace-plugin/index.js +1 -1
  183. package/package.json +1 -1
  184. package/dist/chunk-F6IEGYOI.js.map +0 -1
  185. package/dist/chunk-GFBKUX3J.js.map +0 -1
  186. package/dist/chunk-GIMFNRNR.js.map +0 -1
  187. package/dist/chunk-JXKT2QGT.js.map +0 -1
  188. package/dist/chunk-WWSRIT3J.js +0 -59
  189. package/dist/chunk-WWSRIT3J.js.map +0 -1
  190. package/dist/ensure-sources-XZ3MUJOM.js.map +0 -1
  191. package/dist/library-publish-OADODIMW.js.map +0 -1
  192. package/dist/setup-EPNOIKDM.js.map +0 -1
  193. package/dist/source-manifest-publish-AHLDG4XS.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { mcpNotRunnableReason } from './chunk-HG2PDB3T.js';
1
+ import { mcpNotRunnableReason } from './chunk-MUQBP2BK.js';
2
2
  import { fetchAssetFilesFromGitHub } from './chunk-F3D25RGM.js';
3
3
  import { isValidAssetName } from './chunk-7HRZACI4.js';
4
4
  import { createHash } from 'crypto';
@@ -27,5 +27,5 @@ async function mcpNotRunnableHere(manifest, name, fetcher = fetchAssetFilesFromG
27
27
  }
28
28
 
29
29
  export { mcpNotRunnableHere, storeNotInstallableReason };
30
- //# sourceMappingURL=chunk-HP62IELJ.js.map
31
- //# sourceMappingURL=chunk-HP62IELJ.js.map
30
+ //# sourceMappingURL=chunk-HCIXCCUH.js.map
31
+ //# sourceMappingURL=chunk-HCIXCCUH.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../cli/src/store-addable.ts"],"names":[],"mappings":";;;;;AAsBO,SAAS,0BACd,CAAA,EACoB;AACpB,EAAA,IAAI,CAAC,gBAAA,CAAiB,CAAA,CAAE,IAAI,CAAA,EAAG;AAC7B,IAAA,OAAO,CAAA,UAAA,EAAa,EAAE,IAAI,CAAA,mDAAA,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,MAAA;AACT;AAUA,eAAsB,kBAAA,CACpB,QAAA,EACA,IAAA,EACA,OAAA,GAAwB,yBAAA,EACK;AAC7B,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,IAAA,CAAK,QAAA,CAAS,SAAS,CAAC,CAAA;AACzF,EAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAClB,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ;AAAA,MAC1B,GAAA,EAAK,SAAS,MAAA,CAAO,GAAA;AAAA,MACrB,SAAA,EAAW,SAAS,MAAA,CAAO,SAAA;AAAA,MAC3B,KAAA,EAAO,CAAC,IAAA,CAAK,IAAI;AAAA,KAClB,CAAA;AACD,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAC3B,IAAA,IAAI,CAAC,GAAA,IAAO,UAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,GAAG,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA,KAAM,IAAA,CAAK,QAAQ,OAAO,KAAA,CAAA;AACnF,IAAA,OAAO,oBAAA,CAAqB,GAAA,CAAI,QAAA,CAAS,MAAM,GAAG,IAAI,CAAA;AAAA,EACxD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF","file":"chunk-HP62IELJ.js","sourcesContent":["/**\n * Which store entries `skaile add` can take. The store lists only what `add` can install\n * (owner decision, RCV p385): one rule for `search`, `store search`, `store show` and the\n * `manage` store feed, so a listing never offers a ref that then fails.\n *\n * Every store kind is installable (owner decision, RCW p610): `add` stages the pointer's files\n * into the store cache and deploys them (skills, agents, contracts) or composes them at session\n * start (mcp-server). Only a name that is no canonical asset name cannot be added.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { mcpNotRunnableReason } from \"@skaile/workspaces/asset-manager\";\nimport { isValidAssetName } from \"@skaile/workspaces/core\";\nimport { type AssetFetcher, fetchAssetFilesFromGitHub } from \"@skaile/workspaces/library\";\nimport type { CatalogAsset } from \"@skaile/workspaces/plugins\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\n\n/**\n * Why `skaile add` cannot take a store row as printed, or `undefined` when it can: a name that\n * is not a canonical asset name (`UI Rendering` copied from a listing is two shell arguments\n * and no ref).\n */\nexport function storeNotInstallableReason(\n a: Pick<CatalogAsset, \"kind\" | \"name\">,\n): string | undefined {\n if (!isValidAssetName(a.name)) {\n return `the name \"${a.name}\" is not a canonical asset name, so no ref names it`;\n }\n return undefined;\n}\n\n/**\n * Why the `mcp-server` of `manifest` gets no `.mcp.json` entry from this CLI (a Nix-recipe\n * server, a placeholder url), read from its pinned `MCP.md`: the catalog row carries no manifest\n * fields. `undefined` when it would get one, or when the file cannot be fetched or does not match\n * the recorded sha256: nothing is claimed then (p1491).\n *\n * @param fetcher - Fetches the file at the pinned commit; GitHub's raw host by default.\n */\nexport async function mcpNotRunnableHere(\n manifest: Pick<InstallManifest, \"files\" | \"source\">,\n name: string,\n fetcher: AssetFetcher = fetchAssetFilesFromGitHub,\n): Promise<string | undefined> {\n const file = manifest.files.find((f) => f.path === \"MCP.md\" || f.path.endsWith(\"/MCP.md\"));\n if (!file) return undefined;\n try {\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths: [file.path],\n });\n const buf = bytes[file.path];\n if (!buf || createHash(\"sha256\").update(buf).digest(\"hex\") !== file.sha256) return undefined;\n return mcpNotRunnableReason(buf.toString(\"utf8\"), name);\n } catch {\n return undefined;\n }\n}\n"]}
1
+ {"version":3,"sources":["../cli/src/store-addable.ts"],"names":[],"mappings":";;;;;AAsBO,SAAS,0BACd,CAAA,EACoB;AACpB,EAAA,IAAI,CAAC,gBAAA,CAAiB,CAAA,CAAE,IAAI,CAAA,EAAG;AAC7B,IAAA,OAAO,CAAA,UAAA,EAAa,EAAE,IAAI,CAAA,mDAAA,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,MAAA;AACT;AAUA,eAAsB,kBAAA,CACpB,QAAA,EACA,IAAA,EACA,OAAA,GAAwB,yBAAA,EACK;AAC7B,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,IAAA,CAAK,QAAA,CAAS,SAAS,CAAC,CAAA;AACzF,EAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAClB,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ;AAAA,MAC1B,GAAA,EAAK,SAAS,MAAA,CAAO,GAAA;AAAA,MACrB,SAAA,EAAW,SAAS,MAAA,CAAO,SAAA;AAAA,MAC3B,KAAA,EAAO,CAAC,IAAA,CAAK,IAAI;AAAA,KAClB,CAAA;AACD,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAC3B,IAAA,IAAI,CAAC,GAAA,IAAO,UAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,GAAG,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA,KAAM,IAAA,CAAK,QAAQ,OAAO,KAAA,CAAA;AACnF,IAAA,OAAO,oBAAA,CAAqB,GAAA,CAAI,QAAA,CAAS,MAAM,GAAG,IAAI,CAAA;AAAA,EACxD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF","file":"chunk-HCIXCCUH.js","sourcesContent":["/**\n * Which store entries `skaile add` can take. The store lists only what `add` can install\n * (owner decision, RCV p385): one rule for `search`, `store search`, `store show` and the\n * `manage` store feed, so a listing never offers a ref that then fails.\n *\n * Every store kind is installable (owner decision, RCW p610): `add` stages the pointer's files\n * into the store cache and deploys them (skills, agents, contracts) or composes them at session\n * start (mcp-server). Only a name that is no canonical asset name cannot be added.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { mcpNotRunnableReason } from \"@skaile/workspaces/asset-manager\";\nimport { isValidAssetName } from \"@skaile/workspaces/core\";\nimport { type AssetFetcher, fetchAssetFilesFromGitHub } from \"@skaile/workspaces/library\";\nimport type { CatalogAsset } from \"@skaile/workspaces/plugins\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\n\n/**\n * Why `skaile add` cannot take a store row as printed, or `undefined` when it can: a name that\n * is not a canonical asset name (`UI Rendering` copied from a listing is two shell arguments\n * and no ref).\n */\nexport function storeNotInstallableReason(\n a: Pick<CatalogAsset, \"kind\" | \"name\">,\n): string | undefined {\n if (!isValidAssetName(a.name)) {\n return `the name \"${a.name}\" is not a canonical asset name, so no ref names it`;\n }\n return undefined;\n}\n\n/**\n * Why the `mcp-server` of `manifest` gets no `.mcp.json` entry from this CLI (a Nix-recipe\n * server, a placeholder url), read from its pinned `MCP.md`: the catalog row carries no manifest\n * fields. `undefined` when it would get one, or when the file cannot be fetched or does not match\n * the recorded sha256: nothing is claimed then (p1491).\n *\n * @param fetcher - Fetches the file at the pinned commit; GitHub's raw host by default.\n */\nexport async function mcpNotRunnableHere(\n manifest: Pick<InstallManifest, \"files\" | \"source\">,\n name: string,\n fetcher: AssetFetcher = fetchAssetFilesFromGitHub,\n): Promise<string | undefined> {\n const file = manifest.files.find((f) => f.path === \"MCP.md\" || f.path.endsWith(\"/MCP.md\"));\n if (!file) return undefined;\n try {\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths: [file.path],\n });\n const buf = bytes[file.path];\n if (!buf || createHash(\"sha256\").update(buf).digest(\"hex\") !== file.sha256) return undefined;\n return mcpNotRunnableReason(buf.toString(\"utf8\"), name);\n } catch {\n return undefined;\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { declaresActivityLabel, stripActivityLabel } from './chunk-DWPQBMCY.js';
1
+ import { declaresActivityLabel, stripActivityLabel } from './chunk-JPV4WE5L.js';
2
2
  import { randomUUID } from 'crypto';
3
3
 
4
4
  async function dispatchCapability(hooks, name, input, onBackgroundError = () => {
@@ -52,5 +52,5 @@ function filterRenderCapabilities(caps) {
52
52
  }
53
53
 
54
54
  export { dispatchCapability, filterRenderCapabilities, renderFallback };
55
- //# sourceMappingURL=chunk-GJT2Q5XD.js.map
56
- //# sourceMappingURL=chunk-GJT2Q5XD.js.map
55
+ //# sourceMappingURL=chunk-HXST2IYJ.js.map
56
+ //# sourceMappingURL=chunk-HXST2IYJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../bridge/src/capability-dispatch.ts"],"names":[],"mappings":";;;AAgFA,eAAsB,kBAAA,CACpB,KAAA,EACA,IAAA,EACA,KAAA,EACA,oBAA4D,MAAM;AAAC,CAAA,EACnE,MAAA,EACmC;AACnC,EAAA,MAAA,EAAQ,cAAA,EAAe;AACvB,EAAA,MAAM,SAAS,UAAA,EAAW;AAC1B,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAI9B,EAAA,IAAI,CAAC,qBAAA,CAAsB,GAAA,EAAK,WAAW,CAAA,EAAG,KAAA,GAAQ,mBAAmB,KAAK,CAAA;AAK9E,EAAA,IAAI,GAAA,EAAK,MAAA,IAAU,KAAA,CAAM,UAAA,EAAY;AACnC,IAAA,KAAA,CAAM,UAAA,CAAW;AAAA,MACf,IAAA,EAAM,gBAAA;AAAA,MACN,cAAA,EAAgB,IAAA;AAAA,MAChB,KAAA,EAAO,KAAA;AAAA,MACP;AAAA,KACD,CAAA;AACD,IAAA,IAAI,GAAA,CAAI,MAAA,CAAO,QAAA,IAAY,KAAA,CAAM,QAAA,EAAU;AACzC,MAAA,MAAM,QAAA,GAAW,cAAA,CAAe,GAAA,CAAI,MAAA,CAAO,UAAU,KAAK,CAAA;AAC1D,MAAA,KAAA,CAAM,SAAS,QAAQ,CAAA;AAAA,IACzB;AAAA,EACF;AAEA,EAAA,IAAI,KAAK,aAAA,EAAe;AAEtB,IAAA,KAAK,KAAA,CAAM,MAAA,CAAO,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,MAAM,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ,iBAAA,CAAkB,GAAA,EAAK,MAAM,CAAC,CAAA;AAC5F,IAAA,OAAO,EAAE,MAAA,EAAQ,EAAC,EAAG,UAAA,EAAY,MAAM,MAAA,EAAO;AAAA,EAChD;AAEA,EAAA,MAAM,SAAS,MAAM,KAAA,CAAM,OAAO,IAAA,EAAM,KAAA,EAAO,QAAQ,MAAM,CAAA;AAC7D,EAAA,OAAO,EAAE,MAAA,EAAQ,UAAA,EAAY,KAAA,EAAO,MAAA,EAAO;AAC7C;AAqBO,SAAS,cAAA,CAAe,UAAkB,KAAA,EAAwB;AACvE,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACvC,IAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,wBAAA,EAA0B,EAAE,CAAA;AAAA,EACtD;AACA,EAAA,MAAM,KAAA,GAAQ,KAAA;AACd,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,0BAAA,EAA4B,CAAC,QAAQ,IAAA,KAAiB;AAC5E,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,EAAO,IAAI,CAAA;AAClC,IAAA,OAAO,UAAU,MAAA,IAAa,KAAA,KAAU,IAAA,GAAO,EAAA,GAAK,OAAO,KAAK,CAAA;AAAA,EAClE,CAAC,CAAA;AACH;AAEA,SAAS,QAAA,CAAS,KAA8B,IAAA,EAAuB;AACrE,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC5B,EAAA,IAAI,OAAA,GAAmB,GAAA;AACvB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,YAAY,IAAA,IAAQ,OAAA,KAAY,MAAA,IAAa,OAAO,YAAY,QAAA,EAAU;AAC5E,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAA,GAAW,QAAoC,IAAI,CAAA;AAAA,EACrD;AACA,EAAA,OAAO,OAAA;AACT;AAYO,SAAS,yBAAyB,IAAA,EAAkC;AACzE,EAAA,OAAO,KAAK,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,MAAS,CAAA;AAClD","file":"chunk-GJT2Q5XD.js","sourcesContent":["/**\n * Capability dispatch helpers for bridge harnesses.\n *\n * The runner builds a {@link BridgeCapabilityHooks} bundle from its\n * `CapabilityRegistry` and threads it through `AgentConfig.capabilities`.\n * Harnesses consume the bundle via these helpers without taking a runtime\n * dependency on `@skaile/workspaces/runner` (which would create a circular dep).\n *\n * Three behaviours are layered into a single dispatch path:\n *\n * 1. **Standard tool call** — the LLM invokes a capability; the bridge calls\n * `hooks.invoke()`, awaits the result, and returns it to the LLM.\n * 2. **Fire-and-forget** — when the resolved Capability has `fireAndForget`\n * set, the bridge resolves to `{}` immediately and runs the handler in\n * the background. Background errors are logged but never surfaced to the\n * LLM since the call is already settled.\n * 3. **Render capability** — when the resolved Capability has a non-undefined\n * `render`, the bridge emits `RenderInvokedEvent` to the runner via\n * `hooks.emitRender` and (when `render.fallback` is set) a parallel text\n * event via `hooks.emitText` with simple `{{prop}}` substitution. The\n * placeholder convention follows the v2 spec — top-level keys of `props`\n * only, with optional dotted-path traversal (`{{user.name}}`). The legacy\n * AAP `{{props.x}}` form was retired in Phase 6.\n *\n * @category Capabilities\n * @since 2.0.0\n */\nimport { randomUUID } from \"node:crypto\";\nimport {\n type Capability,\n declaresActivityLabel,\n stripActivityLabel,\n} from \"@skaile/workspaces/types\";\nimport type { BridgeCapabilityHooks } from \"./types.js\";\n\n/**\n * Result of a capability dispatch returned by {@link dispatchCapability}.\n *\n * The bridge feeds `{ result }` back to the LLM tool-use response. For\n * fire-and-forget capabilities `result` is always `{}` and `background` is `true`.\n *\n * @docLink packages/bridge/concepts#capability-dispatch-result\n */\nexport interface CapabilityDispatchResult {\n /** Value returned to the LLM. `{}` for fire-and-forget capabilities. */\n result: unknown;\n /** True when the handler is still running in the background (fire-and-forget). */\n background: boolean;\n /** The per-dispatch call id minted for this invocation (see {@link dispatchCapability}). */\n callId: string;\n}\n\n/**\n * Run a capability invocation through the runner-provided hooks, applying\n * render-event emission and fire-and-forget short-circuit.\n *\n * The result is always shaped for direct return to the LLM. For\n * fire-and-forget capabilities the background promise is fired and any error\n * is logged through `onBackgroundError` (defaulting to a no-op). For all\n * other capabilities the handler is awaited; errors propagate as a rejection\n * so the harness can surface them as tool errors.\n *\n * **Dispatch call id.** Every dispatch mints a fresh `randomUUID()` and uses it\n * for `render_invoked.callId`, `hooks.invoke`'s `callId` and — for client\n * capabilities — the outbound `capability_invoked.callId`. It is deliberately\n * NOT the harness's tool-call id: those are only as unique as the model\n * provider makes them (some harnesses emit `call_0` on every turn), and the\n * runner's pending-call map is keyed by this id, so a late `capability_result`\n * for a timed-out call must never be able to resolve a later call that reused\n * the provider's id. Harnesses map results back to their tool calls through the\n * returned value, never through this id.\n *\n * @param hooks - Capability dispatch bundle from `AgentConfig.capabilities`.\n * @param name - Registered capability name.\n * @param input - Raw tool input from the LLM.\n * @param onBackgroundError - Optional error handler for fire-and-forget failures; receives the dispatch call id.\n * @param signal - Optional abort signal forwarded to the handler.\n * @returns Resolved dispatch result with the LLM-facing value, background flag and dispatch call id.\n * @docLink packages/bridge/concepts#dispatch-capability\n */\nexport async function dispatchCapability(\n hooks: BridgeCapabilityHooks,\n name: string,\n input: unknown,\n onBackgroundError: (err: unknown, callId: string) => void = () => {},\n signal?: AbortSignal,\n): Promise<CapabilityDispatchResult> {\n signal?.throwIfAborted();\n const callId = randomUUID();\n const cap = hooks.resolve(name);\n // The advertised `activity_label` is for the UI only. Strip it before render\n // props and the handler: strict inputs would reject it and external MCP\n // passthrough would forward it. Kept when the capability declares it itself.\n if (!declaresActivityLabel(cap?.inputSchema)) input = stripActivityLabel(input);\n\n // Render emission happens before invocation so clients see the props the\n // LLM passed in even if the handler errors. The runner's gateway forwards\n // the event over the transport.\n if (cap?.render && hooks.emitRender) {\n hooks.emitRender({\n type: \"render_invoked\",\n capabilityName: name,\n props: input,\n callId,\n });\n if (cap.render.fallback && hooks.emitText) {\n const fallback = renderFallback(cap.render.fallback, input);\n hooks.emitText(fallback);\n }\n }\n\n if (cap?.fireAndForget) {\n // Resolve immediately; run handler in background.\n void hooks.invoke(name, input, signal, callId).catch((err) => onBackgroundError(err, callId));\n return { result: {}, background: true, callId };\n }\n\n const result = await hooks.invoke(name, input, signal, callId);\n return { result, background: false, callId };\n}\n\n/**\n * Substitute `{{prop}}` placeholders inside a fallback template using the\n * input record. Top-level keys of `props` resolve directly\n * (`{{name}}` → `props.name`); dotted paths traverse nested records\n * (`{{user.name}}` → `props.user.name`). Missing keys collapse to an empty\n * string; non-record inputs collapse all placeholders.\n *\n * The convention is fixed by the v2 spec (§1, `RenderSpec.fallback`). The\n * legacy AAP form `{{props.x}}` is no longer accepted — author fallbacks\n * with bare keys.\n *\n * Intentionally minimal — full template engines belong in the platform's\n * render layer, not the bridge.\n *\n * @param template - Fallback string from `RenderSpec.fallback` with `{{key}}` placeholders.\n * @param input - LLM tool input object; non-object values collapse all placeholders.\n * @returns Template with all resolvable placeholders replaced.\n * @docLink packages/bridge/concepts#render-fallback\n */\nexport function renderFallback(template: string, input: unknown): string {\n if (!input || typeof input !== \"object\") {\n return template.replace(/\\{\\{\\s*[\\w$.]+\\s*\\}\\}/g, \"\");\n }\n const props = input as Record<string, unknown>;\n return template.replace(/\\{\\{\\s*([\\w$.]+)\\s*\\}\\}/g, (_match, path: string) => {\n const value = readPath(props, path);\n return value === undefined || value === null ? \"\" : String(value);\n });\n}\n\nfunction readPath(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== \"object\") {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\n/**\n * Filter a capability list to those marked as render-capable (having a `render` spec).\n *\n * Used by harnesses that emit a separate render manifest at registration time.\n * Currently unused in production harnesses; reserved for future phases.\n *\n * @param caps - Full capability list to filter.\n * @returns Subset of capabilities with a non-undefined `render` property.\n * @docLink packages/bridge/concepts#filter-render-capabilities\n */\nexport function filterRenderCapabilities(caps: Capability[]): Capability[] {\n return caps.filter((c) => c.render !== undefined);\n}\n"]}
1
+ {"version":3,"sources":["../bridge/src/capability-dispatch.ts"],"names":[],"mappings":";;;AAgFA,eAAsB,kBAAA,CACpB,KAAA,EACA,IAAA,EACA,KAAA,EACA,oBAA4D,MAAM;AAAC,CAAA,EACnE,MAAA,EACmC;AACnC,EAAA,MAAA,EAAQ,cAAA,EAAe;AACvB,EAAA,MAAM,SAAS,UAAA,EAAW;AAC1B,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAI9B,EAAA,IAAI,CAAC,qBAAA,CAAsB,GAAA,EAAK,WAAW,CAAA,EAAG,KAAA,GAAQ,mBAAmB,KAAK,CAAA;AAK9E,EAAA,IAAI,GAAA,EAAK,MAAA,IAAU,KAAA,CAAM,UAAA,EAAY;AACnC,IAAA,KAAA,CAAM,UAAA,CAAW;AAAA,MACf,IAAA,EAAM,gBAAA;AAAA,MACN,cAAA,EAAgB,IAAA;AAAA,MAChB,KAAA,EAAO,KAAA;AAAA,MACP;AAAA,KACD,CAAA;AACD,IAAA,IAAI,GAAA,CAAI,MAAA,CAAO,QAAA,IAAY,KAAA,CAAM,QAAA,EAAU;AACzC,MAAA,MAAM,QAAA,GAAW,cAAA,CAAe,GAAA,CAAI,MAAA,CAAO,UAAU,KAAK,CAAA;AAC1D,MAAA,KAAA,CAAM,SAAS,QAAQ,CAAA;AAAA,IACzB;AAAA,EACF;AAEA,EAAA,IAAI,KAAK,aAAA,EAAe;AAEtB,IAAA,KAAK,KAAA,CAAM,MAAA,CAAO,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,MAAM,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ,iBAAA,CAAkB,GAAA,EAAK,MAAM,CAAC,CAAA;AAC5F,IAAA,OAAO,EAAE,MAAA,EAAQ,EAAC,EAAG,UAAA,EAAY,MAAM,MAAA,EAAO;AAAA,EAChD;AAEA,EAAA,MAAM,SAAS,MAAM,KAAA,CAAM,OAAO,IAAA,EAAM,KAAA,EAAO,QAAQ,MAAM,CAAA;AAC7D,EAAA,OAAO,EAAE,MAAA,EAAQ,UAAA,EAAY,KAAA,EAAO,MAAA,EAAO;AAC7C;AAqBO,SAAS,cAAA,CAAe,UAAkB,KAAA,EAAwB;AACvE,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACvC,IAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,wBAAA,EAA0B,EAAE,CAAA;AAAA,EACtD;AACA,EAAA,MAAM,KAAA,GAAQ,KAAA;AACd,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,0BAAA,EAA4B,CAAC,QAAQ,IAAA,KAAiB;AAC5E,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,EAAO,IAAI,CAAA;AAClC,IAAA,OAAO,UAAU,MAAA,IAAa,KAAA,KAAU,IAAA,GAAO,EAAA,GAAK,OAAO,KAAK,CAAA;AAAA,EAClE,CAAC,CAAA;AACH;AAEA,SAAS,QAAA,CAAS,KAA8B,IAAA,EAAuB;AACrE,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC5B,EAAA,IAAI,OAAA,GAAmB,GAAA;AACvB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,YAAY,IAAA,IAAQ,OAAA,KAAY,MAAA,IAAa,OAAO,YAAY,QAAA,EAAU;AAC5E,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAA,GAAW,QAAoC,IAAI,CAAA;AAAA,EACrD;AACA,EAAA,OAAO,OAAA;AACT;AAYO,SAAS,yBAAyB,IAAA,EAAkC;AACzE,EAAA,OAAO,KAAK,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,MAAS,CAAA;AAClD","file":"chunk-HXST2IYJ.js","sourcesContent":["/**\n * Capability dispatch helpers for bridge harnesses.\n *\n * The runner builds a {@link BridgeCapabilityHooks} bundle from its\n * `CapabilityRegistry` and threads it through `AgentConfig.capabilities`.\n * Harnesses consume the bundle via these helpers without taking a runtime\n * dependency on `@skaile/workspaces/runner` (which would create a circular dep).\n *\n * Three behaviours are layered into a single dispatch path:\n *\n * 1. **Standard tool call** — the LLM invokes a capability; the bridge calls\n * `hooks.invoke()`, awaits the result, and returns it to the LLM.\n * 2. **Fire-and-forget** — when the resolved Capability has `fireAndForget`\n * set, the bridge resolves to `{}` immediately and runs the handler in\n * the background. Background errors are logged but never surfaced to the\n * LLM since the call is already settled.\n * 3. **Render capability** — when the resolved Capability has a non-undefined\n * `render`, the bridge emits `RenderInvokedEvent` to the runner via\n * `hooks.emitRender` and (when `render.fallback` is set) a parallel text\n * event via `hooks.emitText` with simple `{{prop}}` substitution. The\n * placeholder convention follows the v2 spec — top-level keys of `props`\n * only, with optional dotted-path traversal (`{{user.name}}`). The legacy\n * AAP `{{props.x}}` form was retired in Phase 6.\n *\n * @category Capabilities\n * @since 2.0.0\n */\nimport { randomUUID } from \"node:crypto\";\nimport {\n type Capability,\n declaresActivityLabel,\n stripActivityLabel,\n} from \"@skaile/workspaces/types\";\nimport type { BridgeCapabilityHooks } from \"./types.js\";\n\n/**\n * Result of a capability dispatch returned by {@link dispatchCapability}.\n *\n * The bridge feeds `{ result }` back to the LLM tool-use response. For\n * fire-and-forget capabilities `result` is always `{}` and `background` is `true`.\n *\n * @docLink packages/bridge/concepts#capability-dispatch-result\n */\nexport interface CapabilityDispatchResult {\n /** Value returned to the LLM. `{}` for fire-and-forget capabilities. */\n result: unknown;\n /** True when the handler is still running in the background (fire-and-forget). */\n background: boolean;\n /** The per-dispatch call id minted for this invocation (see {@link dispatchCapability}). */\n callId: string;\n}\n\n/**\n * Run a capability invocation through the runner-provided hooks, applying\n * render-event emission and fire-and-forget short-circuit.\n *\n * The result is always shaped for direct return to the LLM. For\n * fire-and-forget capabilities the background promise is fired and any error\n * is logged through `onBackgroundError` (defaulting to a no-op). For all\n * other capabilities the handler is awaited; errors propagate as a rejection\n * so the harness can surface them as tool errors.\n *\n * **Dispatch call id.** Every dispatch mints a fresh `randomUUID()` and uses it\n * for `render_invoked.callId`, `hooks.invoke`'s `callId` and — for client\n * capabilities — the outbound `capability_invoked.callId`. It is deliberately\n * NOT the harness's tool-call id: those are only as unique as the model\n * provider makes them (some harnesses emit `call_0` on every turn), and the\n * runner's pending-call map is keyed by this id, so a late `capability_result`\n * for a timed-out call must never be able to resolve a later call that reused\n * the provider's id. Harnesses map results back to their tool calls through the\n * returned value, never through this id.\n *\n * @param hooks - Capability dispatch bundle from `AgentConfig.capabilities`.\n * @param name - Registered capability name.\n * @param input - Raw tool input from the LLM.\n * @param onBackgroundError - Optional error handler for fire-and-forget failures; receives the dispatch call id.\n * @param signal - Optional abort signal forwarded to the handler.\n * @returns Resolved dispatch result with the LLM-facing value, background flag and dispatch call id.\n * @docLink packages/bridge/concepts#dispatch-capability\n */\nexport async function dispatchCapability(\n hooks: BridgeCapabilityHooks,\n name: string,\n input: unknown,\n onBackgroundError: (err: unknown, callId: string) => void = () => {},\n signal?: AbortSignal,\n): Promise<CapabilityDispatchResult> {\n signal?.throwIfAborted();\n const callId = randomUUID();\n const cap = hooks.resolve(name);\n // The advertised `activity_label` is for the UI only. Strip it before render\n // props and the handler: strict inputs would reject it and external MCP\n // passthrough would forward it. Kept when the capability declares it itself.\n if (!declaresActivityLabel(cap?.inputSchema)) input = stripActivityLabel(input);\n\n // Render emission happens before invocation so clients see the props the\n // LLM passed in even if the handler errors. The runner's gateway forwards\n // the event over the transport.\n if (cap?.render && hooks.emitRender) {\n hooks.emitRender({\n type: \"render_invoked\",\n capabilityName: name,\n props: input,\n callId,\n });\n if (cap.render.fallback && hooks.emitText) {\n const fallback = renderFallback(cap.render.fallback, input);\n hooks.emitText(fallback);\n }\n }\n\n if (cap?.fireAndForget) {\n // Resolve immediately; run handler in background.\n void hooks.invoke(name, input, signal, callId).catch((err) => onBackgroundError(err, callId));\n return { result: {}, background: true, callId };\n }\n\n const result = await hooks.invoke(name, input, signal, callId);\n return { result, background: false, callId };\n}\n\n/**\n * Substitute `{{prop}}` placeholders inside a fallback template using the\n * input record. Top-level keys of `props` resolve directly\n * (`{{name}}` → `props.name`); dotted paths traverse nested records\n * (`{{user.name}}` → `props.user.name`). Missing keys collapse to an empty\n * string; non-record inputs collapse all placeholders.\n *\n * The convention is fixed by the v2 spec (§1, `RenderSpec.fallback`). The\n * legacy AAP form `{{props.x}}` is no longer accepted — author fallbacks\n * with bare keys.\n *\n * Intentionally minimal — full template engines belong in the platform's\n * render layer, not the bridge.\n *\n * @param template - Fallback string from `RenderSpec.fallback` with `{{key}}` placeholders.\n * @param input - LLM tool input object; non-object values collapse all placeholders.\n * @returns Template with all resolvable placeholders replaced.\n * @docLink packages/bridge/concepts#render-fallback\n */\nexport function renderFallback(template: string, input: unknown): string {\n if (!input || typeof input !== \"object\") {\n return template.replace(/\\{\\{\\s*[\\w$.]+\\s*\\}\\}/g, \"\");\n }\n const props = input as Record<string, unknown>;\n return template.replace(/\\{\\{\\s*([\\w$.]+)\\s*\\}\\}/g, (_match, path: string) => {\n const value = readPath(props, path);\n return value === undefined || value === null ? \"\" : String(value);\n });\n}\n\nfunction readPath(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== \"object\") {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\n/**\n * Filter a capability list to those marked as render-capable (having a `render` spec).\n *\n * Used by harnesses that emit a separate render manifest at registration time.\n * Currently unused in production harnesses; reserved for future phases.\n *\n * @param caps - Full capability list to filter.\n * @returns Subset of capabilities with a non-undefined `render` property.\n * @docLink packages/bridge/concepts#filter-render-capabilities\n */\nexport function filterRenderCapabilities(caps: Capability[]): Capability[] {\n return caps.filter((c) => c.render !== undefined);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { getAccessToken, loadStoreAuthConfig, hasStoredAuth } from './chunk-4OAUOH3A.js';
1
+ import { getAccessToken, loadStoreAuthConfig, hasStoredAuth } from './chunk-6WIZC6GM.js';
2
2
  import { globalSettingsPath, mapLegacyFields } from './chunk-MEU2HHGV.js';
3
3
  import { existsSync, readFileSync } from 'fs';
4
4
 
@@ -60,5 +60,5 @@ function isStoreAuthenticated() {
60
60
  }
61
61
 
62
62
  export { getStoreConfig, getStoreToken, isStoreAuthenticated, storeFetch };
63
- //# sourceMappingURL=chunk-YYQDSC7I.js.map
64
- //# sourceMappingURL=chunk-YYQDSC7I.js.map
63
+ //# sourceMappingURL=chunk-IRIWNKQS.js.map
64
+ //# sourceMappingURL=chunk-IRIWNKQS.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../cli/src/store-client.ts"],"names":[],"mappings":";;;;AAuBO,SAAS,cAAA,GAA8B;AAC5C,EAAA,MAAM,eAAe,kBAAA,EAAmB;AACxC,EAAA,IAAI,WAAgC,EAAC;AACrC,EAAA,IAAI,UAAA,CAAW,YAAY,CAAA,EAAG;AAC5B,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,gBAAgB,IAAA,CAAK,KAAA,CAAM,aAAa,YAAA,EAAc,OAAO,CAAC,CAAC,CAAA;AAAA,IAC5E,CAAA,CAAA,MAAQ;AACN,MAAA,QAAA,GAAW,EAAC;AAAA,IACd;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,QAAA,CAAS,QAAA,IAAY,OAAA,CAAQ,IAAI,gBAAA,IAAoB,0BAAA;AAAA,IAC1D,GAAA,EAAK;AAAA,GACP;AACF;AAOO,SAAS,cAAc,IAAA,EAAkC;AAC9D,EAAA,OAAO,cAAA,CAAe,mBAAA,EAAoB,EAAG,IAAI,CAAA;AACnD;AAaA,eAAsB,UAAA,CACpB,MAAA,EACA,IAAA,EACA,IAAA,EAOY;AACZ,EAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAA,CAAO,GAAG,GAAG,IAAI,CAAA,CAAA;AAC9B,EAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,IAAA,MAAM,EAAA,GAAK,IAAI,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAA;AAC1C,IAAA,GAAA,IAAO,IAAI,EAAE,CAAA,CAAA;AAAA,EACf;AAEA,EAAA,MAAM,OAAA,GAAkC;AAAA,IACtC,cAAA,EAAgB,kBAAA;AAAA,IAChB,MAAA,EAAQ,kBAAA;AAAA,IACR,GAAI,IAAA,EAAM,OAAA,IAAW;AAAC,GACxB;AACA,EAAA,IAAI,OAAO,GAAA,EAAK;AACd,IAAA,OAAA,CAAQ,aAAA,GAAgB,CAAA,OAAA,EAAU,MAAA,CAAO,GAAG,CAAA,CAAA;AAAA,EAC9C;AAEA,EAAA,MAAM,SAAA,GAAyB;AAAA,IAC7B,MAAA,EAAQ,MAAM,MAAA,IAAU,KAAA;AAAA,IACxB;AAAA,GACF;AACA,EAAA,IAAI,MAAM,IAAA,EAAM;AACd,IAAA,SAAA,CAAU,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA;AAAA,EAC3C;AAEA,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,OAAA,GAAU,WAAW,MAAM,UAAA,CAAW,OAAM,EAAG,IAAA,EAAM,aAAa,IAAK,CAAA;AAC7E,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,GAAG,SAAA,EAAW,MAAA,EAAQ,UAAA,CAAW,MAAA,EAAQ,CAAA;AACxE,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK,CAAE,KAAA,CAAM,OAAO,EAAE,KAAA,EAAO,CAAA,KAAA,EAAQ,GAAA,CAAI,MAAM,IAAG,CAAE,CAAA;AAI3E,MAAA,MAAM,CAAA,GAAI,IAAA;AACV,MAAA,MAAM,IAAI,MAAM,CAAA,CAAE,OAAA,IAAW,EAAE,KAAA,IAAS,CAAA,iBAAA,EAAoB,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAAA,IAC1E;AACA,IAAA,OAAO,IAAI,IAAA,EAAK;AAAA,EAClB,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,OAAO,CAAA;AAAA,EACtB;AACF;AASO,SAAS,oBAAA,GAAgC;AAC9C,EAAA,OAAO,aAAA,CAAc,qBAAqB,CAAA;AAC5C","file":"chunk-YYQDSC7I.js","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { globalSettingsPath, mapLegacyFields } from \"@skaile/workspaces/core\";\nimport { type AuthDeps, getAccessToken, hasStoredAuth, loadStoreAuthConfig } from \"./store-auth.ts\";\n\n/**\n * Connection configuration for the AI Asset Store API. `jwt` is normally left\n * null here and filled per-call by the caller from {@link getStoreToken} (the\n * device-flow session); it stays on the type for the `{ ...config, jwt }` spread.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport interface StoreConfig {\n url: string;\n jwt: string | null;\n}\n\n/**\n * Read the store API base URL (settings `storeUrl` → `SKAILE_STORE_URL` →\n * default). Auth is not read here — it lives in the device-flow session; see\n * {@link getStoreToken}.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport function getStoreConfig(): StoreConfig {\n const settingsPath = globalSettingsPath();\n let settings: Record<string, any> = {};\n if (existsSync(settingsPath)) {\n try {\n settings = mapLegacyFields(JSON.parse(readFileSync(settingsPath, \"utf-8\")));\n } catch {\n settings = {};\n }\n }\n return {\n url: settings.storeUrl ?? process.env.SKAILE_STORE_URL ?? \"https://api.skaile.store\",\n jwt: null,\n };\n}\n\n/**\n * Return a valid store access token (Keycloak device-flow session, refreshed if\n * needed). Throws a \"run `skaile store login`\" error when there is no session.\n * This is the auth source for every `/api/v1/*` publisher call.\n */\nexport function getStoreToken(deps?: AuthDeps): Promise<string> {\n return getAccessToken(loadStoreAuthConfig(), deps);\n}\n\n/**\n * Make an authenticated HTTP request to the store REST API.\n *\n * @param config - Store connection config (URL + auth token).\n * @param path - API path (e.g. `/api/assets`).\n * @param opts - Optional method, body, query params, extra headers, and\n * `timeoutMs` (default 1500). Publisher calls pass a longer timeout because\n * they trigger server-side clone/sync work.\n * @returns Parsed JSON response body.\n * @docLink cli/dev-guide#store-client\n */\nexport async function storeFetch<T = any>(\n config: StoreConfig,\n path: string,\n opts?: {\n method?: string;\n body?: unknown;\n params?: Record<string, string>;\n headers?: Record<string, string>;\n timeoutMs?: number;\n },\n): Promise<T> {\n let url = `${config.url}${path}`;\n if (opts?.params) {\n const sp = new URLSearchParams(opts.params);\n url += `?${sp}`;\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...(opts?.headers ?? {}),\n };\n if (config.jwt) {\n headers.Authorization = `Bearer ${config.jwt}`;\n }\n\n const fetchOpts: RequestInit = {\n method: opts?.method ?? \"GET\",\n headers,\n };\n if (opts?.body) {\n fetchOpts.body = JSON.stringify(opts.body);\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), opts?.timeoutMs ?? 1_500);\n try {\n const res = await fetch(url, { ...fetchOpts, signal: controller.signal });\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));\n // Prefer the store's human-readable `message` (e.g. \"Namespace '@x' is\n // reserved … Sign in with GitHub to claim it\") over the bare `error` code\n // (`UNPROCESSABLE_CONTENT`) — the message is the actionable part.\n const b = body as { message?: string; error?: string };\n throw new Error(b.message ?? b.error ?? `Store API error: ${res.status}`);\n }\n return res.json() as Promise<T>;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Return `true` when a store session exists (a Keycloak device-flow token cached\n * at `~/.skaile/auth.json`). Validity/refresh is resolved on use via\n * {@link getStoreToken}.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport function isStoreAuthenticated(): boolean {\n return hasStoredAuth(loadStoreAuthConfig());\n}\n"]}
1
+ {"version":3,"sources":["../cli/src/store-client.ts"],"names":[],"mappings":";;;;AAuBO,SAAS,cAAA,GAA8B;AAC5C,EAAA,MAAM,eAAe,kBAAA,EAAmB;AACxC,EAAA,IAAI,WAAgC,EAAC;AACrC,EAAA,IAAI,UAAA,CAAW,YAAY,CAAA,EAAG;AAC5B,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,gBAAgB,IAAA,CAAK,KAAA,CAAM,aAAa,YAAA,EAAc,OAAO,CAAC,CAAC,CAAA;AAAA,IAC5E,CAAA,CAAA,MAAQ;AACN,MAAA,QAAA,GAAW,EAAC;AAAA,IACd;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,QAAA,CAAS,QAAA,IAAY,OAAA,CAAQ,IAAI,gBAAA,IAAoB,0BAAA;AAAA,IAC1D,GAAA,EAAK;AAAA,GACP;AACF;AAOO,SAAS,cAAc,IAAA,EAAkC;AAC9D,EAAA,OAAO,cAAA,CAAe,mBAAA,EAAoB,EAAG,IAAI,CAAA;AACnD;AAaA,eAAsB,UAAA,CACpB,MAAA,EACA,IAAA,EACA,IAAA,EAOY;AACZ,EAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAA,CAAO,GAAG,GAAG,IAAI,CAAA,CAAA;AAC9B,EAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,IAAA,MAAM,EAAA,GAAK,IAAI,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAA;AAC1C,IAAA,GAAA,IAAO,IAAI,EAAE,CAAA,CAAA;AAAA,EACf;AAEA,EAAA,MAAM,OAAA,GAAkC;AAAA,IACtC,cAAA,EAAgB,kBAAA;AAAA,IAChB,MAAA,EAAQ,kBAAA;AAAA,IACR,GAAI,IAAA,EAAM,OAAA,IAAW;AAAC,GACxB;AACA,EAAA,IAAI,OAAO,GAAA,EAAK;AACd,IAAA,OAAA,CAAQ,aAAA,GAAgB,CAAA,OAAA,EAAU,MAAA,CAAO,GAAG,CAAA,CAAA;AAAA,EAC9C;AAEA,EAAA,MAAM,SAAA,GAAyB;AAAA,IAC7B,MAAA,EAAQ,MAAM,MAAA,IAAU,KAAA;AAAA,IACxB;AAAA,GACF;AACA,EAAA,IAAI,MAAM,IAAA,EAAM;AACd,IAAA,SAAA,CAAU,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA;AAAA,EAC3C;AAEA,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,OAAA,GAAU,WAAW,MAAM,UAAA,CAAW,OAAM,EAAG,IAAA,EAAM,aAAa,IAAK,CAAA;AAC7E,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,GAAG,SAAA,EAAW,MAAA,EAAQ,UAAA,CAAW,MAAA,EAAQ,CAAA;AACxE,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK,CAAE,KAAA,CAAM,OAAO,EAAE,KAAA,EAAO,CAAA,KAAA,EAAQ,GAAA,CAAI,MAAM,IAAG,CAAE,CAAA;AAI3E,MAAA,MAAM,CAAA,GAAI,IAAA;AACV,MAAA,MAAM,IAAI,MAAM,CAAA,CAAE,OAAA,IAAW,EAAE,KAAA,IAAS,CAAA,iBAAA,EAAoB,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAAA,IAC1E;AACA,IAAA,OAAO,IAAI,IAAA,EAAK;AAAA,EAClB,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,OAAO,CAAA;AAAA,EACtB;AACF;AASO,SAAS,oBAAA,GAAgC;AAC9C,EAAA,OAAO,aAAA,CAAc,qBAAqB,CAAA;AAC5C","file":"chunk-IRIWNKQS.js","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { globalSettingsPath, mapLegacyFields } from \"@skaile/workspaces/core\";\nimport { type AuthDeps, getAccessToken, hasStoredAuth, loadStoreAuthConfig } from \"./store-auth.ts\";\n\n/**\n * Connection configuration for the AI Asset Store API. `jwt` is normally left\n * null here and filled per-call by the caller from {@link getStoreToken} (the\n * device-flow session); it stays on the type for the `{ ...config, jwt }` spread.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport interface StoreConfig {\n url: string;\n jwt: string | null;\n}\n\n/**\n * Read the store API base URL (settings `storeUrl` → `SKAILE_STORE_URL` →\n * default). Auth is not read here — it lives in the device-flow session; see\n * {@link getStoreToken}.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport function getStoreConfig(): StoreConfig {\n const settingsPath = globalSettingsPath();\n let settings: Record<string, any> = {};\n if (existsSync(settingsPath)) {\n try {\n settings = mapLegacyFields(JSON.parse(readFileSync(settingsPath, \"utf-8\")));\n } catch {\n settings = {};\n }\n }\n return {\n url: settings.storeUrl ?? process.env.SKAILE_STORE_URL ?? \"https://api.skaile.store\",\n jwt: null,\n };\n}\n\n/**\n * Return a valid store access token (Keycloak device-flow session, refreshed if\n * needed). Throws a \"run `skaile store login`\" error when there is no session.\n * This is the auth source for every `/api/v1/*` publisher call.\n */\nexport function getStoreToken(deps?: AuthDeps): Promise<string> {\n return getAccessToken(loadStoreAuthConfig(), deps);\n}\n\n/**\n * Make an authenticated HTTP request to the store REST API.\n *\n * @param config - Store connection config (URL + auth token).\n * @param path - API path (e.g. `/api/assets`).\n * @param opts - Optional method, body, query params, extra headers, and\n * `timeoutMs` (default 1500). Publisher calls pass a longer timeout because\n * they trigger server-side clone/sync work.\n * @returns Parsed JSON response body.\n * @docLink cli/dev-guide#store-client\n */\nexport async function storeFetch<T = any>(\n config: StoreConfig,\n path: string,\n opts?: {\n method?: string;\n body?: unknown;\n params?: Record<string, string>;\n headers?: Record<string, string>;\n timeoutMs?: number;\n },\n): Promise<T> {\n let url = `${config.url}${path}`;\n if (opts?.params) {\n const sp = new URLSearchParams(opts.params);\n url += `?${sp}`;\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...(opts?.headers ?? {}),\n };\n if (config.jwt) {\n headers.Authorization = `Bearer ${config.jwt}`;\n }\n\n const fetchOpts: RequestInit = {\n method: opts?.method ?? \"GET\",\n headers,\n };\n if (opts?.body) {\n fetchOpts.body = JSON.stringify(opts.body);\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), opts?.timeoutMs ?? 1_500);\n try {\n const res = await fetch(url, { ...fetchOpts, signal: controller.signal });\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));\n // Prefer the store's human-readable `message` (e.g. \"Namespace '@x' is\n // reserved … Sign in with GitHub to claim it\") over the bare `error` code\n // (`UNPROCESSABLE_CONTENT`) — the message is the actionable part.\n const b = body as { message?: string; error?: string };\n throw new Error(b.message ?? b.error ?? `Store API error: ${res.status}`);\n }\n return res.json() as Promise<T>;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Return `true` when a store session exists (a Keycloak device-flow token cached\n * at `~/.skaile/auth.json`). Validity/refresh is resolved on use via\n * {@link getStoreToken}.\n *\n * @docLink cli/dev-guide#store-client\n */\nexport function isStoreAuthenticated(): boolean {\n return hasStoredAuth(loadStoreAuthConfig());\n}\n"]}
@@ -1,12 +1,16 @@
1
- import { ompRegistryModelRefusal } from './chunk-MECT5Z5D.js';
2
- import { sessionSurfaceNotice } from './chunk-BALPY67W.js';
3
- import { buildCodexConfigDocument } from './chunk-7MO23JPX.js';
4
- import { bindSingleProviderEntry } from './chunk-DUIZB6JM.js';
5
- import { classifyClaudeSdkError } from './chunk-5DE3DGVR.js';
6
- import { toMergedRegistry } from './chunk-TBH6UXYN.js';
7
- import { BUILTIN_HARNESS_CATALOG, createHarness } from './chunk-MNED5ZCW.js';
1
+ import { ompRegistryModelRefusal, renderOmpRegistry, materializeOmpProviders } from './chunk-J7FEWDRQ.js';
2
+ import { sessionSurfaceNotice } from './chunk-TYRAEMWE.js';
3
+ import { buildCodexConfigDocument } from './chunk-SXRN27TU.js';
4
+ import { materializeOpenCodeConfig } from './chunk-AEFDFCS2.js';
5
+ import { harnessSessionConfigHome } from './chunk-NBAGV6L2.js';
6
+ import { bindSingleProviderEntry, resolveEnvHarnessSession, credentialsForEveryProvider, harnessProviderName } from './chunk-O74SRQ3W.js';
7
+ import { HARNESS_BINARIES, resolveHarnessBinary, harnessSpawnPath, harnessSearchDirs, SDK_CLI_BINARIES, overrideVar, isExecutableFile } from './chunk-YKD2MYLU.js';
8
+ import { classifyClaudeSdkError, stripRunnerPrivateEnv } from './chunk-5DE3DGVR.js';
9
+ import { registryHarnessConfig, toMergedRegistry } from './chunk-CWUHUL6W.js';
10
+ import { BUILTIN_HARNESS_CATALOG, listHarnesses, listModelsForHarness, createHarness } from './chunk-U7EJB6LY.js';
8
11
  import { getProviderPreset, resolvePresetBaseUrl, expandPreset, resolveProbeUrl, buildCredentialHeaders, AI_PROVIDER_PRESETS } from './chunk-6UP2EDFN.js';
9
- import { stripActivityLabel, TOOL_ACTIVITY_LABEL_PARAM, TOOL_ACTIVITY_LABEL_MAX_CHARS } from './chunk-DWPQBMCY.js';
12
+ import { stripActivityLabel, TOOL_ACTIVITY_LABEL_PARAM, TOOL_ACTIVITY_LABEL_MAX_CHARS } from './chunk-JPV4WE5L.js';
13
+ import { loadHarnessSdk, sdkLookupPlaces, installCommandFor } from './chunk-MEU2HHGV.js';
10
14
  import { registryEntries, isEntryEnabled, parseModelRef } from './chunk-RXGPFAMN.js';
11
15
  import { openSqlite } from './chunk-RZL4TOK3.js';
12
16
  import { execFile } from 'child_process';
@@ -14,6 +18,9 @@ import { readFileSync, existsSync } from 'fs';
14
18
  import os from 'os';
15
19
  import path from 'path';
16
20
  import { parse } from 'yaml';
21
+ import semver from 'semver';
22
+ import { randomUUID } from 'crypto';
23
+ import { rm } from 'fs/promises';
17
24
 
18
25
  function nativeProviders(harnessId) {
19
26
  if (harnessId === "codex") return /* @__PURE__ */ new Set(["openai"]);
@@ -135,13 +142,17 @@ function isUnlistedModel(input) {
135
142
  }
136
143
  var OMP_THINKING_SUFFIX = /:(off|minimal|low|medium|high|xhigh)$/i;
137
144
  function ompModels(args, timeoutMs) {
138
- const bin = process.env.OMP_BRIDGE_BIN || "omp";
145
+ const bin = resolveHarnessBinary(HARNESS_BINARIES.omp) ?? (process.env.OMP_BRIDGE_BIN || "omp");
139
146
  const pre = process.env.OMP_BRIDGE_PREARGS ? process.env.OMP_BRIDGE_PREARGS.split(/\s+/).filter(Boolean) : [];
140
147
  return new Promise((resolve) => {
141
- execFile(
148
+ const child = execFile(
142
149
  bin,
143
150
  [...pre, ...args, "--json"],
144
- { timeout: timeoutMs, maxBuffer: 64 * 1024 * 1024, env: process.env },
151
+ {
152
+ timeout: timeoutMs,
153
+ maxBuffer: 64 * 1024 * 1024,
154
+ env: { ...process.env, PATH: harnessSpawnPath() }
155
+ },
145
156
  (error, out) => {
146
157
  if (error) return resolve(void 0);
147
158
  try {
@@ -153,6 +164,7 @@ function ompModels(args, timeoutMs) {
153
164
  }
154
165
  }
155
166
  );
167
+ child.stdin?.end();
156
168
  });
157
169
  }
158
170
  async function checkOmpListedModel(selector, timeoutMs = 2e4) {
@@ -175,6 +187,398 @@ async function checkOmpListedModel(selector, timeoutMs = 2e4) {
175
187
  );
176
188
  return known ? void 0 : refusal;
177
189
  }
190
+ var DETECT_CACHE_TTL_MS = 15e3;
191
+ var DEFAULT_PROBE_TIMEOUT_MS = 5e3;
192
+ var HARNESS_SDKS = {
193
+ "claude-sdk": {
194
+ pkg: "@anthropic-ai/claude-agent-sdk",
195
+ load: (projectDir) => loadHarnessSdk(
196
+ "@anthropic-ai/claude-agent-sdk",
197
+ projectDir,
198
+ () => import('@anthropic-ai/claude-agent-sdk')
199
+ )
200
+ },
201
+ codex: {
202
+ pkg: "@openai/codex-sdk",
203
+ load: (projectDir) => loadHarnessSdk("@openai/codex-sdk", projectDir, () => import('@openai/codex-sdk'))
204
+ }
205
+ };
206
+ function sdkMissingProblem(harness, pkg, projectDir) {
207
+ return `The ${harness} harness needs ${pkg}, which is not installed. Looked in ${sdkLookupPlaces(projectDir)}. Run in the project: ${installCommandFor(pkg, projectDir)} (or pick another harness with --harness).`;
208
+ }
209
+ function runProbe(bin, args, env, timeoutMs) {
210
+ return new Promise((resolve) => {
211
+ try {
212
+ const asScript = !isExecutableFile(bin);
213
+ const child = execFile(
214
+ asScript ? process.execPath : bin,
215
+ asScript ? [bin, ...args] : args,
216
+ {
217
+ timeout: timeoutMs,
218
+ // In the `bun build --compile` skaile binary, process.execPath is skaile itself;
219
+ // BUN_BE_BUN makes it act as bun so it runs the script. Node ignores the variable.
220
+ env: { ...env, PATH: harnessSpawnPath(env), ...asScript ? { BUN_BE_BUN: "1" } : {} },
221
+ windowsHide: true,
222
+ maxBuffer: 1024 * 1024
223
+ },
224
+ (error, stdout, stderr) => {
225
+ const code = error && typeof error.code === "number" ? error.code : error ? void 0 : 0;
226
+ resolve({
227
+ stdout: String(stdout ?? ""),
228
+ stderr: String(stderr ?? ""),
229
+ ...code !== void 0 ? { code } : {},
230
+ failed: error != null && typeof error.code !== "number"
231
+ });
232
+ }
233
+ );
234
+ child.stdin?.on("error", () => {
235
+ });
236
+ child.stdin?.end();
237
+ } catch (err) {
238
+ resolve({ stdout: "", stderr: err.message, failed: true });
239
+ }
240
+ });
241
+ }
242
+ var VERSION_RE = /\d+\.\d+\.\d+[-+\w.]*/;
243
+ async function probeVersion(bin, env, timeoutMs) {
244
+ const res = await runProbe(bin, ["--version"], env, timeoutMs);
245
+ if (res.failed || res.code !== 0) return void 0;
246
+ return VERSION_RE.exec(`${res.stdout}
247
+ ${res.stderr}`)?.[0];
248
+ }
249
+ function firstLine(text) {
250
+ return text.split("\n").map((l) => l.trim()).find(Boolean);
251
+ }
252
+ async function probeClaudeLogin(bin, env, timeoutMs) {
253
+ const res = await runProbe(bin, ["auth", "status"], env, timeoutMs);
254
+ const start = res.stdout.indexOf("{");
255
+ const end = res.stdout.lastIndexOf("}");
256
+ let parsed;
257
+ if (start >= 0 && end > start) {
258
+ try {
259
+ parsed = JSON.parse(res.stdout.slice(start, end + 1));
260
+ } catch {
261
+ parsed = void 0;
262
+ }
263
+ }
264
+ if (parsed?.loggedIn === true) {
265
+ return {
266
+ status: "ok",
267
+ ...typeof parsed.authMethod === "string" ? { detail: parsed.authMethod } : {}
268
+ };
269
+ }
270
+ if (parsed?.loggedIn === false) {
271
+ return {
272
+ status: "missing",
273
+ detail: "Run `claude auth login`, or configure an Anthropic provider in Settings \u2192 AI Providers."
274
+ };
275
+ }
276
+ return { status: "unknown", detail: firstLine(res.stderr) ?? "no answer" };
277
+ }
278
+ async function probeCodexLogin(bin, env, timeoutMs) {
279
+ const res = await runProbe(bin, ["login", "status"], env, timeoutMs);
280
+ const text = `${res.stdout}
281
+ ${res.stderr}`;
282
+ if (/not logged in/i.test(text)) {
283
+ return { status: "missing", detail: "Run `codex login`, or configure an OpenAI provider." };
284
+ }
285
+ if (!res.failed && res.code === 0 && /logged in/i.test(text)) {
286
+ return { status: "ok", detail: firstLine(res.stdout) ?? firstLine(res.stderr) ?? "logged in" };
287
+ }
288
+ return {
289
+ status: "unknown",
290
+ detail: firstLine(res.stderr) ?? firstLine(res.stdout) ?? "no answer"
291
+ };
292
+ }
293
+ var LOGIN_PROBES = {
294
+ "claude-sdk": probeClaudeLogin,
295
+ codex: probeCodexLogin
296
+ };
297
+ function outdatedProblem(row, version, minVersion) {
298
+ return `${row.bin} ${version} is older than ${minVersion}. ${row.hint}`;
299
+ }
300
+ async function detectBinaryHarness(id, row, env, timeoutMs) {
301
+ const found = resolveHarnessBinary(row, env);
302
+ if (!found) {
303
+ return {
304
+ id,
305
+ status: "missing",
306
+ ...row.minVersion ? { minVersion: row.minVersion } : {},
307
+ problem: row.hint,
308
+ searched: harnessSearchDirs(env)
309
+ };
310
+ }
311
+ const version = await probeVersion(found, env, timeoutMs);
312
+ const detection = {
313
+ id,
314
+ status: "ok",
315
+ path: found,
316
+ ...version ? { version } : {},
317
+ ...row.minVersion ? { minVersion: row.minVersion } : {}
318
+ };
319
+ if (version && row.minVersion) {
320
+ const have = semver.coerce(version);
321
+ if (have && semver.lt(have, row.minVersion)) {
322
+ detection.status = "outdated";
323
+ detection.problem = outdatedProblem(row, version, row.minVersion);
324
+ }
325
+ }
326
+ return detection;
327
+ }
328
+ async function detectSdkHarness(id, sdkProbe, env, projectDir, timeoutMs) {
329
+ const cli = SDK_CLI_BINARIES[id];
330
+ const cliPath = cli ? resolveHarnessBinary(cli, env) : void 0;
331
+ const loaded = await sdkProbe.load(projectDir).then(
332
+ () => true,
333
+ () => false
334
+ );
335
+ const detection = {
336
+ id,
337
+ status: loaded ? "ok" : "missing",
338
+ sdk: { pkg: sdkProbe.pkg, loaded }
339
+ };
340
+ if (!loaded) detection.problem = sdkMissingProblem(id, sdkProbe.pkg, projectDir);
341
+ if (!cliPath || !cli) {
342
+ detection.login = { status: "unknown", detail: cli?.hint ?? "no CLI to ask" };
343
+ return detection;
344
+ }
345
+ detection.path = cliPath;
346
+ const loginProbe = LOGIN_PROBES[id];
347
+ const [version, login] = await Promise.all([
348
+ probeVersion(cliPath, env, timeoutMs),
349
+ loginProbe ? loginProbe(cliPath, env, timeoutMs) : Promise.resolve({ status: "unknown" })
350
+ ]);
351
+ if (version) detection.version = version;
352
+ detection.login = login;
353
+ return detection;
354
+ }
355
+ async function detectHarness(id, options = {}) {
356
+ try {
357
+ const env = options.env ?? process.env;
358
+ const timeoutMs = options.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;
359
+ const projectDir = options.projectDir ?? process.cwd();
360
+ const row = HARNESS_BINARIES[id];
361
+ if (row) return await detectBinaryHarness(id, row, env, timeoutMs);
362
+ const sdk = HARNESS_SDKS[id];
363
+ if (sdk) return await detectSdkHarness(id, sdk, env, projectDir, timeoutMs);
364
+ if (id === "echo") return { id, status: "ok" };
365
+ return { id, status: "unknown" };
366
+ } catch (err) {
367
+ return { id, status: "unknown", problem: err instanceof Error ? err.message : String(err) };
368
+ }
369
+ }
370
+ var detectCache = /* @__PURE__ */ new Map();
371
+ function detectCacheKey(options, env) {
372
+ const overrides = [...Object.values(HARNESS_BINARIES), ...Object.values(SDK_CLI_BINARIES)].map(
373
+ (row) => `${overrideVar(row)}=${env[overrideVar(row)] ?? ""}`
374
+ );
375
+ return JSON.stringify([
376
+ path.resolve(options.projectDir ?? process.cwd()),
377
+ env.PATH ?? "",
378
+ env.HOME ?? "",
379
+ env.NVM_DIR ?? "",
380
+ env.MISE_DATA_DIR ?? "",
381
+ env.NPM_CONFIG_PREFIX ?? "",
382
+ env.npm_config_prefix ?? "",
383
+ env.FNM_DIR ?? "",
384
+ env.APPDATA ?? "",
385
+ env.LOCALAPPDATA ?? "",
386
+ options.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS,
387
+ ...overrides
388
+ ]);
389
+ }
390
+ async function detectHarnesses(options = {}) {
391
+ const env = options.env ?? process.env;
392
+ let key;
393
+ try {
394
+ key = detectCacheKey(options, env);
395
+ } catch {
396
+ key = void 0;
397
+ }
398
+ const hit = key === void 0 ? void 0 : detectCache.get(key);
399
+ if (!options.fresh && hit && Date.now() - hit.at < DETECT_CACHE_TTL_MS) return hit.value;
400
+ const value = Promise.all(listHarnesses().map((info) => detectHarness(info.id, options)));
401
+ if (key !== void 0) detectCache.set(key, { at: Date.now(), value });
402
+ return value;
403
+ }
404
+ function runProgram(harnessId, bin, args, options) {
405
+ return new Promise((resolve, reject) => {
406
+ const child = execFile(
407
+ bin,
408
+ args,
409
+ {
410
+ cwd: options.cwd,
411
+ env: options.env,
412
+ timeout: options.timeoutMs,
413
+ maxBuffer: 64 * 1024 * 1024
414
+ },
415
+ (error, stdout, stderr) => {
416
+ if (!error) return resolve(stdout);
417
+ const failure = error;
418
+ if (failure.code === "ENOENT") {
419
+ return reject(new Error(HARNESS_BINARIES[harnessId]?.hint ?? `${harnessId} not found`));
420
+ }
421
+ if (failure.killed) {
422
+ return reject(
423
+ new Error(`${harnessId} did not answer within ${options.timeoutMs / 1e3} s`)
424
+ );
425
+ }
426
+ const firstLine2 = String(stderr).split("\n").find((line) => line.trim())?.trim();
427
+ reject(
428
+ new Error(
429
+ `${harnessId} exited with ${failure.code ?? "an error"}${firstLine2 ? `: ${firstLine2}` : ""}`
430
+ )
431
+ );
432
+ }
433
+ );
434
+ child.stdin?.end();
435
+ });
436
+ }
437
+ function programFor(harnessId) {
438
+ const row = HARNESS_BINARIES[harnessId];
439
+ if (!row) throw new Error(`${harnessId} has no known program`);
440
+ const bin = resolveHarnessBinary(row);
441
+ if (!bin) throw new Error(row.hint);
442
+ const overridden = Boolean(process.env[row.overrideEnv ?? `${row.envPrefix}_BRIDGE_BIN`]);
443
+ const raw = process.env[`${row.envPrefix}_BRIDGE_PREARGS`];
444
+ return { bin, preArgs: overridden && raw ? raw.split(/\s+/).filter(Boolean) : [] };
445
+ }
446
+ function childEnv(config, extra) {
447
+ const env = { ...process.env, ...config.env, ...extra };
448
+ env.PATH = harnessSpawnPath(env);
449
+ return stripRunnerPrivateEnv(env);
450
+ }
451
+ function parseOmpModelsJson(stdout) {
452
+ let parsed;
453
+ try {
454
+ parsed = JSON.parse(stdout);
455
+ } catch {
456
+ return void 0;
457
+ }
458
+ const list = parsed && typeof parsed === "object" && "models" in parsed ? parsed.models : parsed;
459
+ if (!Array.isArray(list)) return void 0;
460
+ const seen = /* @__PURE__ */ new Set();
461
+ const models = [];
462
+ for (const item of list) {
463
+ if (!item || typeof item !== "object") continue;
464
+ const row = { ...item };
465
+ if (row.kind !== "chat") continue;
466
+ const providerId = typeof row.provider === "string" ? row.provider : void 0;
467
+ const providerModelId = typeof row.id === "string" ? row.id : void 0;
468
+ const selector = typeof row.selector === "string" && row.selector ? row.selector : providerId && providerModelId ? `${providerId}/${providerModelId}` : void 0;
469
+ if (!selector || seen.has(selector)) continue;
470
+ seen.add(selector);
471
+ models.push({
472
+ id: selector,
473
+ name: typeof row.name === "string" && row.name ? row.name : providerModelId ?? selector,
474
+ ...providerId ? { providerId } : {},
475
+ ...providerModelId ? { providerModelId } : {},
476
+ source: "harness"
477
+ });
478
+ }
479
+ return models.length > 0 ? models : void 0;
480
+ }
481
+ function parseOpenCodeModelLines(stdout) {
482
+ const seen = /* @__PURE__ */ new Set();
483
+ const lines = [];
484
+ for (const raw of stdout.split("\n")) {
485
+ const match = /^([^\s/]+)\/(\S+)$/.exec(raw.trim());
486
+ if (!match?.[1] || !match[2] || seen.has(raw.trim())) continue;
487
+ seen.add(raw.trim());
488
+ lines.push({ provider: match[1], model: match[2] });
489
+ }
490
+ return lines;
491
+ }
492
+ var ompEnumerator = {
493
+ timeoutMs: 2e4,
494
+ async list(config, timeoutMs) {
495
+ let sessionConfig = config;
496
+ if (!config.modelRef && config.registry) {
497
+ const first = renderOmpRegistry(config.registry, {
498
+ env: { ...process.env, ...config.env }
499
+ }).providerIds[0];
500
+ if (first) sessionConfig = { ...config, modelRef: first };
501
+ }
502
+ const mat = await materializeOmpProviders(sessionConfig);
503
+ try {
504
+ const { bin, preArgs } = programFor("omp");
505
+ const env = childEnv(config, {
506
+ ...mat ? { PI_CODING_AGENT_DIR: mat.agentDir, ...mat.credentialEnv } : {}
507
+ });
508
+ const stdout = await runProgram("omp", bin, [...preArgs, "models", "--json"], {
509
+ cwd: config.cwd,
510
+ env,
511
+ timeoutMs
512
+ });
513
+ return parseOmpModelsJson(stdout);
514
+ } finally {
515
+ if (mat?.ephemeral) await rm(mat.agentDir, { recursive: true, force: true });
516
+ }
517
+ }
518
+ };
519
+ var opencodeEnumerator = {
520
+ // `opencode models` fetches models.dev, which regularly takes longer than 8 s.
521
+ timeoutMs: 15e3,
522
+ async list(config, timeoutMs) {
523
+ const session = resolveEnvHarnessSession(config);
524
+ const home = harnessSessionConfigHome("opencode", config);
525
+ try {
526
+ const mat = materializeOpenCodeConfig(session, config);
527
+ const { bin, preArgs } = programFor("opencode");
528
+ const env = childEnv(config, { ...credentialsForEveryProvider(session), ...mat.env });
529
+ const stdout = await runProgram("opencode", bin, [...preArgs, "models"], {
530
+ cwd: config.cwd,
531
+ env,
532
+ timeoutMs
533
+ });
534
+ const lines = parseOpenCodeModelLines(stdout);
535
+ if (lines.length === 0) return void 0;
536
+ const entryOf = /* @__PURE__ */ new Map();
537
+ for (const [entryId, entry] of registryEntries(session.registry)) {
538
+ if (entry.kind !== "llm" || !isEntryEnabled(entry)) continue;
539
+ const name = harnessProviderName(entryId, entry);
540
+ if (!entryOf.has(name)) entryOf.set(name, entryId);
541
+ }
542
+ return lines.map(({ provider, model }) => ({
543
+ id: `${provider}/${model}`,
544
+ name: model,
545
+ providerId: entryOf.get(provider) ?? provider,
546
+ providerModelId: model,
547
+ source: "harness"
548
+ }));
549
+ } finally {
550
+ await rm(home, { recursive: true, force: true });
551
+ }
552
+ }
553
+ };
554
+ var HARNESS_MODEL_ENUMERATORS = {
555
+ omp: ompEnumerator,
556
+ opencode: opencodeEnumerator
557
+ };
558
+ async function discoverHarnessModels(harnessId, registry, options = {}) {
559
+ const enumerator = HARNESS_MODEL_ENUMERATORS[harnessId];
560
+ if (!enumerator) {
561
+ return { models: await listModelsForHarness(harnessId, registry, options), source: "registry" };
562
+ }
563
+ const config = {
564
+ cwd: options.cwd ?? process.cwd(),
565
+ sessionId: `model-discovery-${randomUUID().slice(0, 8)}`,
566
+ ...registryHarnessConfig(registry, options)
567
+ };
568
+ let error;
569
+ try {
570
+ const models = await enumerator.list(config, options.timeoutMs ?? enumerator.timeoutMs);
571
+ if (models && models.length > 0) return { models, source: "harness" };
572
+ error = `${harnessId} printed no model list`;
573
+ } catch (err) {
574
+ error = err instanceof Error ? err.message : String(err);
575
+ }
576
+ return {
577
+ models: await listModelsForHarness(harnessId, registry, options),
578
+ source: "registry",
579
+ error
580
+ };
581
+ }
178
582
 
179
583
  // bridge/src/normalizer.ts
180
584
  function resultUsageFields(event) {
@@ -581,7 +985,7 @@ function summarizeToolCall(tool, input) {
581
985
  return `Search for ${arg("pattern")}`;
582
986
  case "ApplyPatch": {
583
987
  const changes = Array.isArray(input.changes) ? input.changes : [];
584
- const paths = changes.map((change) => change?.path).filter((path2) => typeof path2 === "string");
988
+ const paths = changes.map((change) => change?.path).filter((path3) => typeof path3 === "string");
585
989
  return `Edit ${paths.join(", ").slice(0, 200) || "files"}`;
586
990
  }
587
991
  default:
@@ -819,6 +1223,6 @@ async function validateApiKey(provider, key, options = {}) {
819
1223
  }
820
1224
  }
821
1225
 
822
- export { BridgeRuntime, EventNormalizer, checkHarnessModel, checkModelProvider, checkModelSurface, checkOmpListedModel, checkOmpServeModel, createRuntime, detectFileChange, detectFileChanges, isUnlistedModel, labelToolCall, summarizeToolCall, summarizeToolResult, validateApiKey };
823
- //# sourceMappingURL=chunk-GIMFNRNR.js.map
824
- //# sourceMappingURL=chunk-GIMFNRNR.js.map
1226
+ export { BridgeRuntime, EventNormalizer, HARNESS_SDKS, checkHarnessModel, checkModelProvider, checkModelSurface, checkOmpListedModel, checkOmpServeModel, createRuntime, detectFileChange, detectFileChanges, detectHarness, detectHarnesses, discoverHarnessModels, isUnlistedModel, labelToolCall, sdkMissingProblem, summarizeToolCall, summarizeToolResult, validateApiKey };
1227
+ //# sourceMappingURL=chunk-IYXOSBQ4.js.map
1228
+ //# sourceMappingURL=chunk-IYXOSBQ4.js.map